blob: c5f9f826062520255504e2a74107dfb75436a312 [file] [log] [blame]
David Hendricksce6b2fa2011-07-11 22:12:43 -07001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (c) 2010 Matthias Wenzel <bios at mazzoo dot de>
5 * Copyright (c) 2011 Stefan Tauner
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
David Hendricksce6b2fa2011-07-11 22:12:43 -070016 */
17
stefanct1fc3a732011-09-15 23:52:55 +000018#include "ich_descriptors.h"
Stefan Tauner34f6f5a2016-08-03 11:20:38 -070019
Edward O'Callaghanb76b4e62020-07-26 13:03:12 +100020#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Tauner34f6f5a2016-08-03 11:20:38 -070021#include <stdio.h>
Edward O'Callaghan568cd262020-05-26 23:10:45 +100022#include <string.h>
Stefan Tauner34f6f5a2016-08-03 11:20:38 -070023#define print(t, ...) printf(__VA_ARGS__)
Edward O'Callaghanb76b4e62020-07-26 13:03:12 +100024#endif
25
Stefan Tauner34f6f5a2016-08-03 11:20:38 -070026#define DESCRIPTOR_MODE_SIGNATURE 0x0ff0a55a
27/* The upper map is located in the word before the 256B-long OEM section at the
28 * end of the 4kB-long flash descriptor.
29 */
30#define UPPER_MAP_OFFSET (4096 - 256 - 4)
31#define getVTBA(flumap) (((flumap)->FLUMAP1 << 4) & 0x00000ff0)
32
Edward O'Callaghan01e8d322020-07-09 18:26:43 +100033#include <sys/types.h>
34#include <string.h>
David Hendricksce6b2fa2011-07-11 22:12:43 -070035#include "flash.h" /* for msg_* */
stefanct1fc3a732011-09-15 23:52:55 +000036#include "programmer.h"
David Hendricksce6b2fa2011-07-11 22:12:43 -070037
Edward O'Callaghane7efd052020-07-03 14:57:28 +100038ssize_t ich_number_of_regions(const enum ich_chipset cs, const struct ich_desc_content *const cont)
39{
40 switch (cs) {
41 case CHIPSET_APOLLO_LAKE:
Angel Pons00b29cf2020-07-10 17:04:10 +020042 case CHIPSET_GEMINI_LAKE:
Edward O'Callaghane7efd052020-07-03 14:57:28 +100043 return 6;
44 case CHIPSET_C620_SERIES_LEWISBURG:
45 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillier81bc4d32020-08-12 12:48:06 -050046 case CHIPSET_400_SERIES_COMET_POINT:
Edward O'Callaghane7efd052020-07-03 14:57:28 +100047 return 16;
48 case CHIPSET_100_SERIES_SUNRISE_POINT:
49 return 10;
50 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
51 case CHIPSET_9_SERIES_WILDCAT_POINT:
52 case CHIPSET_8_SERIES_LYNX_POINT_LP:
53 case CHIPSET_8_SERIES_LYNX_POINT:
54 case CHIPSET_8_SERIES_WELLSBURG:
55 if (cont->NR <= 6)
56 return cont->NR + 1;
57 else
58 return -1;
59 default:
60 if (cont->NR <= 4)
61 return cont->NR + 1;
62 else
63 return -1;
64 }
65}
Stefan Tauner34f6f5a2016-08-03 11:20:38 -070066
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +100067ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
68{
69 switch (cs) {
70 case CHIPSET_C620_SERIES_LEWISBURG:
71 case CHIPSET_APOLLO_LAKE:
Angel Pons00b29cf2020-07-10 17:04:10 +020072 case CHIPSET_GEMINI_LAKE:
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +100073 if (cont->NM <= MAX_NUM_MASTERS)
74 return cont->NM;
75 break;
76 default:
77 if (cont->NM < MAX_NUM_MASTERS)
78 return cont->NM + 1;
79 }
80
81 return -1;
82}
Stefan Tauner34f6f5a2016-08-03 11:20:38 -070083
Edward O'Callaghand757b422020-05-26 21:22:12 +100084void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
David Hendricksce6b2fa2011-07-11 22:12:43 -070085{
stefanct1fc3a732011-09-15 23:52:55 +000086 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
87 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
88 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
89 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Edward O'Callaghand757b422020-05-26 21:22:12 +100090 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
91 if (print_vcl)
92 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
93 print(verbosity, "\n");
David Hendricksce6b2fa2011-07-11 22:12:43 -070094}
95
stefanct1fc3a732011-09-15 23:52:55 +000096#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
97#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
98#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
99#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
100#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
101
Edward O'Callaghan01e8d322020-07-09 18:26:43 +1000102void prettyprint_ich_chipset(enum ich_chipset cs)
103{
104 static const char *const chipset_names[] = {
105 "Unknown ICH", "ICH8", "ICH9", "ICH10",
106 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
107 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
108 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
Angel Pons00b29cf2020-07-10 17:04:10 +0200109 "C620 series Lewisburg", "300 series Cannon Point", "Apollo Lake", "Gemini Lake",
Edward O'Callaghan01e8d322020-07-09 18:26:43 +1000110 };
111 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
112 cs = 0;
113 else
114 cs = cs - CHIPSET_ICH8 + 1;
115 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
116}
117
stefanct1fc3a732011-09-15 23:52:55 +0000118void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
David Hendricksce6b2fa2011-07-11 22:12:43 -0700119{
Edward O'Callaghane7efd052020-07-03 14:57:28 +1000120 prettyprint_ich_descriptor_content(cs, &desc->content);
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000121 prettyprint_ich_descriptor_component(cs, desc);
Edward O'Callaghane7efd052020-07-03 14:57:28 +1000122 prettyprint_ich_descriptor_region(cs, desc);
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000123 prettyprint_ich_descriptor_master(cs, desc);
Edward O'Callaghanb76b4e62020-07-26 13:03:12 +1000124#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700125 if (cs >= CHIPSET_ICH8) {
126 prettyprint_ich_descriptor_upper_map(&desc->upper);
127 prettyprint_ich_descriptor_straps(cs, desc);
128 }
Edward O'Callaghanb76b4e62020-07-26 13:03:12 +1000129#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
David Hendricksce6b2fa2011-07-11 22:12:43 -0700130}
131
Edward O'Callaghane7efd052020-07-03 14:57:28 +1000132void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
David Hendricksce6b2fa2011-07-11 22:12:43 -0700133{
stefanct1fc3a732011-09-15 23:52:55 +0000134 msg_pdbg2("=== Content Section ===\n");
135 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
136 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
137 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
138 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
139 msg_pdbg2("\n");
140
141 msg_pdbg2("--- Details ---\n");
Edward O'Callaghane7efd052020-07-03 14:57:28 +1000142 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
Edward O'Callaghan86bd8da2020-07-09 18:17:42 +1000143 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
144 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
145 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
146 msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL);
147 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont));
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000148 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
Edward O'Callaghan86bd8da2020-07-09 18:17:42 +1000149 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
150 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
151 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
stefanct1fc3a732011-09-15 23:52:55 +0000152 msg_pdbg2("\n");
David Hendricksce6b2fa2011-07-11 22:12:43 -0700153}
154
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000155static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
David Hendricksce6b2fa2011-07-11 22:12:43 -0700156{
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000157 if (idx > 1) {
158 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
159 return NULL;
160 }
161
162 if (desc->content.NC == 0 && idx > 0)
163 return "unused";
164
165 static const char * const size_str[] = {
166 "512 kB", /* 0000 */
167 "1 MB", /* 0001 */
168 "2 MB", /* 0010 */
169 "4 MB", /* 0011 */
170 "8 MB", /* 0100 */
171 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
172 "32 MB", /* 0110 */
173 "64 MB", /* 0111 */
David Hendricksce6b2fa2011-07-11 22:12:43 -0700174 };
175
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000176 switch (cs) {
177 case CHIPSET_ICH8:
178 case CHIPSET_ICH9:
179 case CHIPSET_ICH10:
180 case CHIPSET_5_SERIES_IBEX_PEAK:
181 case CHIPSET_6_SERIES_COUGAR_POINT:
182 case CHIPSET_7_SERIES_PANTHER_POINT:
183 case CHIPSET_BAYTRAIL: {
184 uint8_t size_enc;
185 if (idx == 0) {
186 size_enc = desc->component.dens_old.comp1_density;
187 } else {
188 size_enc = desc->component.dens_old.comp2_density;
189 }
190 if (size_enc > 5)
191 return "reserved";
192 return size_str[size_enc];
193 }
194 case CHIPSET_8_SERIES_LYNX_POINT:
195 case CHIPSET_8_SERIES_LYNX_POINT_LP:
196 case CHIPSET_8_SERIES_WELLSBURG:
197 case CHIPSET_9_SERIES_WILDCAT_POINT:
198 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
199 case CHIPSET_100_SERIES_SUNRISE_POINT:
200 case CHIPSET_C620_SERIES_LEWISBURG:
201 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillier81bc4d32020-08-12 12:48:06 -0500202 case CHIPSET_400_SERIES_COMET_POINT:
Angel Pons00b29cf2020-07-10 17:04:10 +0200203 case CHIPSET_APOLLO_LAKE:
204 case CHIPSET_GEMINI_LAKE: {
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000205 uint8_t size_enc;
206 if (idx == 0) {
207 size_enc = desc->component.dens_new.comp1_density;
208 } else {
209 size_enc = desc->component.dens_new.comp2_density;
210 }
211 if (size_enc > 7)
212 return "reserved";
213 return size_str[size_enc];
214 }
215 case CHIPSET_ICH_UNKNOWN:
216 default:
217 return "unknown";
218 }
219}
220
221static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
222{
223 static const char *const freq_str[3][8] = { {
224 "20 MHz",
225 "33 MHz",
226 "reserved",
227 "reserved",
228 "50 MHz", /* New since Ibex Peak */
229 "reserved",
230 "reserved",
231 "reserved"
232 }, {
233 "reserved",
234 "reserved",
235 "48 MHz",
236 "reserved",
237 "30 MHz",
238 "reserved",
239 "17 MHz",
240 "reserved"
241 }, {
242 "reserved",
243 "50 MHz",
244 "40 MHz",
245 "reserved",
246 "25 MHz",
247 "reserved",
248 "14 MHz / 17 MHz",
249 "reserved"
250 } };
251
252 switch (cs) {
253 case CHIPSET_ICH8:
254 case CHIPSET_ICH9:
255 case CHIPSET_ICH10:
256 if (value > 1)
257 return "reserved";
258 /* Fall through. */
259 case CHIPSET_5_SERIES_IBEX_PEAK:
260 case CHIPSET_6_SERIES_COUGAR_POINT:
261 case CHIPSET_7_SERIES_PANTHER_POINT:
262 case CHIPSET_8_SERIES_LYNX_POINT:
263 case CHIPSET_BAYTRAIL:
264 case CHIPSET_8_SERIES_LYNX_POINT_LP:
265 case CHIPSET_8_SERIES_WELLSBURG:
266 case CHIPSET_9_SERIES_WILDCAT_POINT:
267 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
268 return freq_str[0][value];
269 case CHIPSET_100_SERIES_SUNRISE_POINT:
270 case CHIPSET_C620_SERIES_LEWISBURG:
271 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillier81bc4d32020-08-12 12:48:06 -0500272 case CHIPSET_400_SERIES_COMET_POINT:
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000273 return freq_str[1][value];
274 case CHIPSET_APOLLO_LAKE:
Angel Pons00b29cf2020-07-10 17:04:10 +0200275 case CHIPSET_GEMINI_LAKE:
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000276 return freq_str[2][value];
277 case CHIPSET_ICH_UNKNOWN:
278 default:
279 return "unknown";
280 }
281}
282
283void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
284{
Edward O'Callaghan224e6ba2020-07-09 18:19:36 +1000285 bool has_flill1;
286
287 switch (cs) {
288 case CHIPSET_100_SERIES_SUNRISE_POINT:
289 case CHIPSET_C620_SERIES_LEWISBURG:
290 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillier81bc4d32020-08-12 12:48:06 -0500291 case CHIPSET_400_SERIES_COMET_POINT:
Edward O'Callaghan224e6ba2020-07-09 18:19:36 +1000292 case CHIPSET_APOLLO_LAKE:
Angel Pons00b29cf2020-07-10 17:04:10 +0200293 case CHIPSET_GEMINI_LAKE:
Edward O'Callaghan224e6ba2020-07-09 18:19:36 +1000294 has_flill1 = true;
295 break;
296 default:
297 has_flill1 = false;
298 break;
299 }
300
stefanct1fc3a732011-09-15 23:52:55 +0000301 msg_pdbg2("=== Component Section ===\n");
302 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
303 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Edward O'Callaghan224e6ba2020-07-09 18:19:36 +1000304 if (has_flill1)
305 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
stefanct1fc3a732011-09-15 23:52:55 +0000306 msg_pdbg2("\n");
David Hendricksce6b2fa2011-07-11 22:12:43 -0700307
stefanct1fc3a732011-09-15 23:52:55 +0000308 msg_pdbg2("--- Details ---\n");
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000309 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
stefanct1fc3a732011-09-15 23:52:55 +0000310 if (desc->content.NC)
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000311 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
David Hendricksce6b2fa2011-07-11 22:12:43 -0700312 else
stefanct1fc3a732011-09-15 23:52:55 +0000313 msg_pdbg2("Component 2 is not used.\n");
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000314 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
315 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
316 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
317 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
318 if (desc->component.modes.fastread)
stefanct1fc3a732011-09-15 23:52:55 +0000319 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000320 pprint_freq(cs, desc->component.modes.freq_fastread));
321 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
322 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
323 desc->component.modes.dual_output ? "dis" : "en");
324
325 int has_forbidden_opcode = 0;
326 if (desc->component.FLILL != 0) {
327 has_forbidden_opcode = 1;
stefanct1fc3a732011-09-15 23:52:55 +0000328 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
329 desc->component.invalid_instr0);
330 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
331 desc->component.invalid_instr1);
332 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
333 desc->component.invalid_instr2);
334 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
335 desc->component.invalid_instr3);
336 }
Edward O'Callaghan224e6ba2020-07-09 18:19:36 +1000337 if (has_flill1) {
338 if (desc->component.FLILL1 != 0) {
339 has_forbidden_opcode = 1;
340 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
341 desc->component.invalid_instr4);
342 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
343 desc->component.invalid_instr5);
344 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
345 desc->component.invalid_instr6);
346 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
347 desc->component.invalid_instr7);
348 }
349 }
Edward O'Callaghan87595e12020-07-03 13:09:18 +1000350 if (!has_forbidden_opcode)
351 msg_pdbg2("No forbidden opcodes.\n");
352
stefanct1fc3a732011-09-15 23:52:55 +0000353 msg_pdbg2("\n");
David Hendricksce6b2fa2011-07-11 22:12:43 -0700354}
355
stefanct1fc3a732011-09-15 23:52:55 +0000356static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
David Hendricksce6b2fa2011-07-11 22:12:43 -0700357{
Edward O'Callaghan133ef002020-05-26 23:15:56 +1000358 static const char *const region_names[] = {
359 "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown",
360 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
David Hendricksce6b2fa2011-07-11 22:12:43 -0700361 };
Edward O'Callaghan133ef002020-05-26 23:15:56 +1000362 if (i >= ARRAY_SIZE(region_names)) {
stefanct1fc3a732011-09-15 23:52:55 +0000363 msg_pdbg2("%s: region index too high.\n", __func__);
364 return;
David Hendricksce6b2fa2011-07-11 22:12:43 -0700365 }
stefanct1fc3a732011-09-15 23:52:55 +0000366 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
367 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Edward O'Callaghan133ef002020-05-26 23:15:56 +1000368 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
stefanct1fc3a732011-09-15 23:52:55 +0000369 if (base > limit)
370 msg_pdbg2("is unused.\n");
371 else
Edward O'Callaghan133ef002020-05-26 23:15:56 +1000372 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
David Hendricksce6b2fa2011-07-11 22:12:43 -0700373}
374
Edward O'Callaghane7efd052020-07-03 14:57:28 +1000375void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
David Hendricksce6b2fa2011-07-11 22:12:43 -0700376{
Edward O'Callaghande5dd912020-07-26 13:04:18 +1000377 ssize_t i;
Edward O'Callaghane7efd052020-07-03 14:57:28 +1000378 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
stefanct1fc3a732011-09-15 23:52:55 +0000379 msg_pdbg2("=== Region Section ===\n");
Edward O'Callaghane7efd052020-07-03 14:57:28 +1000380 if (nr < 0) {
stefanct1fc3a732011-09-15 23:52:55 +0000381 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Edward O'Callaghane7efd052020-07-03 14:57:28 +1000382 desc->content.NR + 1);
stefanct1fc3a732011-09-15 23:52:55 +0000383 return;
384 }
Edward O'Callaghane7efd052020-07-03 14:57:28 +1000385 for (i = 0; i < nr; i++)
Edward O'Callaghande5dd912020-07-26 13:04:18 +1000386 msg_pdbg2("FLREG%zd 0x%08x\n", i, desc->region.FLREGs[i]);
stefanct1fc3a732011-09-15 23:52:55 +0000387 msg_pdbg2("\n");
388
389 msg_pdbg2("--- Details ---\n");
Edward O'Callaghane7efd052020-07-03 14:57:28 +1000390 for (i = 0; i < nr; i++)
Edward O'Callaghande5dd912020-07-26 13:04:18 +1000391 pprint_freg(&desc->region, (uint32_t)i);
stefanct1fc3a732011-09-15 23:52:55 +0000392 msg_pdbg2("\n");
David Hendricksce6b2fa2011-07-11 22:12:43 -0700393}
394
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000395void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
David Hendricksce6b2fa2011-07-11 22:12:43 -0700396{
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000397 ssize_t i;
398 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
stefanct1fc3a732011-09-15 23:52:55 +0000399 msg_pdbg2("=== Master Section ===\n");
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000400 if (nm < 0) {
401 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
402 desc->content.NM + 1);
403 return;
404 }
405 for (i = 0; i < nm; i++)
406 msg_pdbg2("FLMSTR%zd 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
stefanct1fc3a732011-09-15 23:52:55 +0000407 msg_pdbg2("\n");
David Hendricksce6b2fa2011-07-11 22:12:43 -0700408
stefanct1fc3a732011-09-15 23:52:55 +0000409 msg_pdbg2("--- Details ---\n");
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000410 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT ||
Matt DeVillier81bc4d32020-08-12 12:48:06 -0500411 cs == CHIPSET_300_SERIES_CANNON_POINT ||
412 cs == CHIPSET_400_SERIES_COMET_POINT) {
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000413 const char *const master_names[] = {
414 "BIOS", "ME", "GbE", "unknown", "EC",
415 };
416 if (nm >= (ssize_t)ARRAY_SIZE(master_names)) {
417 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
418 desc->content.NM + 1);
419 return;
420 }
David Hendricksce6b2fa2011-07-11 22:12:43 -0700421
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000422 size_t num_regions;
423 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9");
424 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
425 num_regions = 10;
426 msg_pdbg2("\n");
427 } else {
428 num_regions = 16;
429 msg_pdbg2(" RegA RegB RegC RegD RegE RegF\n");
430 }
431 for (i = 0; i < nm; i++) {
432 size_t j;
433 msg_pdbg2("%-4s", master_names[i]);
Edward O'Callaghanb2370fd2021-01-22 14:51:13 +1100434 for (j = 0; j < (size_t)min(num_regions, 12); j++)
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000435 msg_pdbg2(" %c%c ",
436 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
437 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
438 for (; j < num_regions; j++)
439 msg_pdbg2(" %c%c ",
440 desc->master.mstr[i].ext_read & (1 << (j - 12)) ? 'r' : ' ',
441 desc->master.mstr[i].ext_write & (1 << (j - 12)) ? 'w' : ' ');
442 msg_pdbg2("\n");
443 }
444 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
445 const char *const master_names[] = {
446 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
447 };
448 /* NM starts at 1 instead of 0 for LBG */
449 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
450 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
451 desc->content.NM);
452 return;
453 }
Duncan Lauriedbbf2222019-04-25 12:06:19 -0700454
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000455 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
456 " ", /* width of master name (4 chars minimum) */
457 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
458 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
459 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
460 "Reg15");
461 for (i = 0; i < nm; i++) {
462 size_t j;
463 msg_pdbg2("%-4s", master_names[i]);
464 for (j = 0; j < 16; j++)
465 msg_pdbg2(" %c%c ",
466 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
467 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
468 msg_pdbg2("\n");
469 }
Angel Pons00b29cf2020-07-10 17:04:10 +0200470 } else if (cs == CHIPSET_APOLLO_LAKE || cs == CHIPSET_GEMINI_LAKE) {
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000471 const char *const master_names[] = { "BIOS", "TXE", };
472 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
473 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
474 return;
475 }
Duncan Lauriedbbf2222019-04-25 12:06:19 -0700476
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +1000477 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
478 for (i = 0; i < nm; i++) {
479 ssize_t j;
480 msg_pdbg2("%-4s", master_names[i]);
481 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
482 msg_pdbg2(" %c%c ",
483 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
484 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
485 msg_pdbg2("\n");
486 }
487 } else {
488 const struct ich_desc_master *const mstr = &desc->master;
489 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
490 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
491 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
492 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
493 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
494 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
495 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
496 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
497 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
498 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
499 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
500 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
501 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
502 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
503 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
504 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
505 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
506 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
507 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
508 }
509 msg_pdbg2("\n");
Duncan Lauriedbbf2222019-04-25 12:06:19 -0700510}
511
Edward O'Callaghan568cd262020-05-26 23:10:45 +1000512static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700513{
514 static const char * const str_GPIO12[4] = {
515 "GPIO12",
516 "LAN PHY Power Control Function (Native Output)",
517 "GLAN_DOCK# (Native Input)",
518 "invalid configuration",
519 };
520
521 msg_pdbg2("--- MCH details ---\n");
522 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
523 msg_pdbg2("\n");
524
525 msg_pdbg2("--- ICH details ---\n");
526 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
527 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
528 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
529 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
530 msg_pdbg2("SPI CS1 is used for %s.\n",
531 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
532 "LAN PHY Power Control Function" :
533 "SPI Chip Select");
534 msg_pdbg2("GPIO12 is used as %s.\n",
535 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
536 msg_pdbg2("PCIe Port 6 is used for %s.\n",
537 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
538 msg_pdbg2("%sn BMC Mode: "
539 "Intel AMT SMBus Controller 1 is connected to %s.\n",
540 desc->south.ich8.BMCMODE ? "I" : "Not i",
541 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
542 msg_pdbg2("TCO is in %s Mode.\n",
543 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
544 msg_pdbg2("ME A is %sabled.\n",
545 desc->south.ich8.ME_DISABLE ? "dis" : "en");
546 msg_pdbg2("\n");
547}
548
549static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
550{
551 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
552
553 off *= 4;
Edward O'Callaghan568cd262020-05-26 23:10:45 +1000554 switch (conf){
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700555 case 0:
556 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
557 break;
558 case 1:
559 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
560 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
561 break;
562 case 2:
563 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
564 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
565 break;
566 case 3:
567 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
568 1+off, 2+off, 4+off);
569 break;
570 }
571 msg_pdbg2("\n");
572}
573
Edward O'Callaghan568cd262020-05-26 23:10:45 +1000574static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700575{
576 /* PCHSTRP4 */
577 msg_pdbg2("Intel PHY is %s.\n",
578 (s->ibex.PHYCON == 2) ? "connected" :
579 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
580 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
581 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
582 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
583 s->ibex.GBEMAC_SMBUS_ADDR);
584 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
585 s->ibex.GBEPHY_SMBUS_ADDR);
586
587 /* PCHSTRP5 */
588 /* PCHSTRP6 */
589 /* PCHSTRP7 */
590 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
591 s->ibex.MESMA2UDID_VENDOR);
592 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
593 s->ibex.MESMA2UDID_VENDOR);
594
595 /* PCHSTRP8 */
596}
597
Edward O'Callaghan568cd262020-05-26 23:10:45 +1000598static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700599{
600 /* PCHSTRP11 */
601 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
602 s->ibex.SML1GPAEN ? "en" : "dis");
603 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
604 s->ibex.SML1GPA);
605 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
606 s->ibex.SML1I2CAEN ? "en" : "dis");
607 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
608 s->ibex.SML1I2CA);
609
610 /* PCHSTRP12 */
611 /* PCHSTRP13 */
612}
613
Edward O'Callaghan568cd262020-05-26 23:10:45 +1000614static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700615{
Patrick Georgi3a5bcb92017-04-11 20:45:07 +0200616 static const uint8_t dec_t209min[4] = {
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700617 100,
618 50,
619 5,
620 1
621 };
622
623 msg_pdbg2("--- PCH ---\n");
624
625 /* PCHSTRP0 */
626 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
627 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
628 s->ibex.SMB_EN ? "en" : "dis");
629 msg_pdbg2("SMLink0 segment is %sabled.\n",
630 s->ibex.SML0_EN ? "en" : "dis");
631 msg_pdbg2("SMLink1 segment is %sabled.\n",
632 s->ibex.SML1_EN ? "en" : "dis");
633 msg_pdbg2("SMLink1 Frequency: %s\n",
634 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
635 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
636 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
637 msg_pdbg2("SMLink0 Frequency: %s\n",
638 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
639 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
640 "LAN_PHY_PWR_CTRL" : "general purpose output");
641 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
642 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
643 s->ibex.DMI_REQID_DIS ? "en" : "dis");
644 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
645 1 << (6 + s->ibex.BBBS));
646
647 /* PCHSTRP1 */
648 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
649
650 /* PCHSTRP2 */
651 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
652 s->ibex.MESMASDEN ? "en" : "dis");
653 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
654 s->ibex.MESMASDA);
655 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
656 s->ibex.MESMI2CEN ? "en" : "dis");
657 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
658 s->ibex.MESMI2CA);
659
660 /* PCHSTRP3 */
661 prettyprint_ich_descriptor_pchstraps45678_56(s);
662 /* PCHSTRP9 */
663 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
664 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
665 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
666 s->ibex.PCIELR1 ? "" : "not ");
667 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
668 s->ibex.PCIELR2 ? "" : "not ");
669 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
670 s->ibex.DMILR ? "" : "not ");
671 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
672 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
673 s->ibex.PHY_PCIE_EN ? "en" : "dis");
674
675 /* PCHSTRP10 */
676 msg_pdbg2("Management Engine will boot from %sflash.\n",
677 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
678 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
679 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
680 s->ibex.VE_EN ? "en" : "dis");
681 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
682 s->ibex.MMDDE ? "en" : "dis");
683 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
684 s->ibex.MMADDR);
685 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
686 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
687 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
688 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
689 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
690
691 prettyprint_ich_descriptor_pchstraps111213_56(s);
692
693 /* PCHSTRP14 */
694 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
695 s->ibex.VE_EN2 ? "en" : "dis");
696 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
697 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
698 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
699 s->ibex.BW_SSD ? "en" : "dis");
700 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
701 s->ibex.NVMHCI_EN ? "en" : "dis");
702
703 /* PCHSTRP15 */
704 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
705 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
706 s->ibex.IWL_EN ? "en" : "dis");
707 msg_pdbg2("t209 min Timing: %d ms\n",
708 dec_t209min[s->ibex.t209min]);
709 msg_pdbg2("\n");
710}
711
Edward O'Callaghan568cd262020-05-26 23:10:45 +1000712static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700713{
714 msg_pdbg2("--- PCH ---\n");
715
716 /* PCHSTRP0 */
717 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
718 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
719 s->ibex.SMB_EN ? "en" : "dis");
720 msg_pdbg2("SMLink0 segment is %sabled.\n",
721 s->ibex.SML0_EN ? "en" : "dis");
722 msg_pdbg2("SMLink1 segment is %sabled.\n",
723 s->ibex.SML1_EN ? "en" : "dis");
724 msg_pdbg2("SMLink1 Frequency: %s\n",
725 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
726 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
727 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
728 msg_pdbg2("SMLink0 Frequency: %s\n",
729 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
730 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
731 "LAN_PHY_PWR_CTRL" : "general purpose output");
732 msg_pdbg2("LinkSec is %sabled.\n",
733 s->cougar.LINKSEC_DIS ? "en" : "dis");
734 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
735 s->ibex.DMI_REQID_DIS ? "en" : "dis");
736 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
737 1 << (6 + s->ibex.BBBS));
738
739 /* PCHSTRP1 */
740 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
741 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
742
743 /* PCHSTRP2 */
744 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
745 s->ibex.MESMASDEN ? "en" : "dis");
746 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
747 s->ibex.MESMASDA);
748 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
749 s->cougar.MESMMCTPAEN ? "en" : "dis");
750 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
751 s->cougar.MESMMCTPA);
752 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
753 s->ibex.MESMI2CEN ? "en" : "dis");
754 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
755 s->ibex.MESMI2CA);
756
757 /* PCHSTRP3 */
758 prettyprint_ich_descriptor_pchstraps45678_56(s);
759 /* PCHSTRP9 */
760 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
761 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
762 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
763 s->ibex.PCIELR1 ? "" : "not ");
764 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
765 s->ibex.PCIELR2 ? "" : "not ");
766 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
767 s->ibex.DMILR ? "" : "not ");
768 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
769 s->cougar.MDSMBE_EN ? "en" : "dis");
770 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
771 s->cougar.MDSMBE_ADD);
772 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
773 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
774 s->ibex.PHY_PCIE_EN ? "en" : "dis");
775 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
776 s->cougar.SUB_DECODE_EN ? "en" : "dis");
777 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
778 "PCHHOT#" : "SML1ALERT#");
779
780 /* PCHSTRP10 */
781 msg_pdbg2("Management Engine will boot from %sflash.\n",
782 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
783
784 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
785 s->cougar.MDSMBE_EN ? "en" : "dis");
786 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
787 s->cougar.MDSMBE_ADD);
788
789 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
790 s->cougar.ICC_SEL);
Edward O'Callaghan568cd262020-05-26 23:10:45 +1000791 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
792 s->ibex.MER_CL1 ? "" : "not ");
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700793 msg_pdbg2("ICC Profile is selected by %s.\n",
794 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
795 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
796 s->cougar.Deep_SX_EN ? "not " : "");
797 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
798 s->cougar.ME_DBG_LAN ? "en" : "dis");
799
800 prettyprint_ich_descriptor_pchstraps111213_56(s);
801
802 /* PCHSTRP14 */
803 /* PCHSTRP15 */
804 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
805 msg_pdbg2("Integrated wired LAN is %sabled.\n",
806 s->cougar.IWL_EN ? "en" : "dis");
807 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
808 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Edward O'Callaghan568cd262020-05-26 23:10:45 +1000809 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700810 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
811 "general purpose output" : "SLP_LAN#");
812
813 /* PCHSTRP16 */
814 /* PCHSTRP17 */
815 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
816 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
817 msg_pdbg2("\n");
818}
819
820void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
821{
Edward O'Callaghanc172e172020-05-26 23:19:02 +1000822 unsigned int i, max_count;
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700823 msg_pdbg2("=== Softstraps ===\n");
824
Edward O'Callaghanc172e172020-05-26 23:19:02 +1000825 max_count = MIN(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
826 if (max_count < desc->content.MSL) {
827 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
828 desc->content.MSL, max_count);
829 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
830 }
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700831
Edward O'Callaghanc172e172020-05-26 23:19:02 +1000832 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
833 for (i = 0; i < max_count; i++)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700834 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
835 msg_pdbg2("\n");
836
Edward O'Callaghanc172e172020-05-26 23:19:02 +1000837 max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
838 if (max_count < desc->content.ISL) {
839 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
840 desc->content.ISL, max_count);
841 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
842 }
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700843
Edward O'Callaghanc172e172020-05-26 23:19:02 +1000844 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
845 for (i = 0; i < max_count; i++)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700846 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
847 msg_pdbg2("\n");
848
849 switch (cs) {
850 case CHIPSET_ICH8:
851 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
852 msg_pdbg2("Detailed North/MCH/PROC information is "
853 "probably not reliable, printing anyway.\n");
854 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
855 msg_pdbg2("Detailed South/ICH/PCH information is "
856 "probably not reliable, printing anyway.\n");
857 prettyprint_ich_descriptor_straps_ich8(desc);
858 break;
859 case CHIPSET_5_SERIES_IBEX_PEAK:
860 /* PCH straps only. PROCSTRPs are unknown. */
861 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
862 msg_pdbg2("Detailed South/ICH/PCH information is "
863 "probably not reliable, printing anyway.\n");
864 prettyprint_ich_descriptor_straps_ibex(&desc->south);
865 break;
866 case CHIPSET_6_SERIES_COUGAR_POINT:
867 /* PCH straps only. PROCSTRP0 is "reserved". */
868 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
869 msg_pdbg2("Detailed South/ICH/PCH information is "
870 "probably not reliable, printing anyway.\n");
871 prettyprint_ich_descriptor_straps_cougar(&desc->south);
872 break;
873 case CHIPSET_ICH_UNKNOWN:
874 break;
875 default:
Edward O'Callaghan568cd262020-05-26 23:10:45 +1000876 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700877 break;
878 }
879}
880
Edward O'Callaghan568cd262020-05-26 23:10:45 +1000881static void prettyprint_rdid(uint32_t reg_val)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700882{
883 uint8_t mid = reg_val & 0xFF;
884 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
885 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
886}
887
888void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
889{
890 int i;
891 msg_pdbg2("=== Upper Map Section ===\n");
892 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
893 msg_pdbg2("\n");
894
895 msg_pdbg2("--- Details ---\n");
896 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
897 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
898 msg_pdbg2("\n");
899
900 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Edward O'Callaghan568cd262020-05-26 23:10:45 +1000901 for (i = 0; i < umap->VTL/2; i++) {
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700902 uint32_t jid = umap->vscc_table[i].JID;
903 uint32_t vscc = umap->vscc_table[i].VSCC;
904 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
905 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
906 msg_pdbg2(" "); /* indention */
907 prettyprint_rdid(jid);
908 msg_pdbg2(" "); /* indention */
Edward O'Callaghand757b422020-05-26 21:22:12 +1000909 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Tauner34f6f5a2016-08-03 11:20:38 -0700910 }
911 msg_pdbg2("\n");
912}
913
Edward O'Callaghan01e8d322020-07-09 18:26:43 +1000914/*
915 * Guesses a minimum chipset version based on the maximum number of
916 * soft straps per generation.
917 */
918static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
919{
920 if (content->ICCRIBA == 0x00) {
921 if (content->MSL == 0 && content->ISL <= 2)
922 return CHIPSET_ICH8;
923 else if (content->ISL <= 2)
924 return CHIPSET_ICH9;
925 else if (content->ISL <= 10)
926 return CHIPSET_ICH10;
927 else if (content->ISL <= 16)
928 return CHIPSET_5_SERIES_IBEX_PEAK;
929 else if (content->FLMAP2 == 0) {
Angel Pons00b29cf2020-07-10 17:04:10 +0200930 if (content->ISL == 23)
931 return CHIPSET_GEMINI_LAKE;
932 else if (content->ISL != 19)
Edward O'Callaghan01e8d322020-07-09 18:26:43 +1000933 msg_pwarn("Peculiar firmware descriptor, assuming Apollo Lake compatibility.\n");
934 return CHIPSET_APOLLO_LAKE;
935 }
936 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
937 return CHIPSET_5_SERIES_IBEX_PEAK;
938 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
939 if (content->MSL == 0 && content->ISL <= 17)
940 return CHIPSET_BAYTRAIL;
941 else if (content->MSL <= 1 && content->ISL <= 18)
942 return CHIPSET_6_SERIES_COUGAR_POINT;
943 else if (content->MSL <= 1 && content->ISL <= 21)
944 return CHIPSET_8_SERIES_LYNX_POINT;
945 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
946 return CHIPSET_9_SERIES_WILDCAT_POINT;
947 } else if (content->ICCRIBA < 0x34) {
948 if (content->NM == 6)
949 return CHIPSET_C620_SERIES_LEWISBURG;
950 else
951 return CHIPSET_100_SERIES_SUNRISE_POINT;
Jonathan Zhangee234f92020-08-19 12:19:06 -0700952 } else if (content->ICCRIBA == 0x34) {
953 if (content->NM == 6)
954 return CHIPSET_C620_SERIES_LEWISBURG;
955 else
956 return CHIPSET_300_SERIES_CANNON_POINT;
Edward O'Callaghan01e8d322020-07-09 18:26:43 +1000957 } else {
Jonathan Zhangee234f92020-08-19 12:19:06 -0700958 msg_pwarn("Unknown firmware descriptor, assuming 300 series compatibility.\n");
Edward O'Callaghan01e8d322020-07-09 18:26:43 +1000959 return CHIPSET_300_SERIES_CANNON_POINT;
960 }
961}
962
963/*
964 * As an additional measure, we check the read frequency like `ifdtool`.
965 * The frequency value 6 (17MHz) was reserved before Skylake and is the
966 * only valid value since. Skylake is currently the most important dis-
967 * tinction because of the dropped number of regions field (NR).
968 */
969static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
970 const struct ich_desc_component *const component)
971{
972 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
973
974 switch (guess) {
975 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillier81bc4d32020-08-12 12:48:06 -0500976 case CHIPSET_400_SERIES_COMET_POINT:
Angel Pons00b29cf2020-07-10 17:04:10 +0200977 case CHIPSET_GEMINI_LAKE:
Edward O'Callaghan01e8d322020-07-09 18:26:43 +1000978 /* `freq_read` was repurposed, so can't check on it any more. */
979 return guess;
980 case CHIPSET_100_SERIES_SUNRISE_POINT:
981 case CHIPSET_C620_SERIES_LEWISBURG:
982 case CHIPSET_APOLLO_LAKE:
983 if (component->modes.freq_read != 6) {
984 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
985 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
986 "Please report this message, the output of `ich_descriptors_tool` for\n"
987 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
988 return CHIPSET_9_SERIES_WILDCAT_POINT;
989 }
990 return guess;
991 default:
992 if (component->modes.freq_read == 6) {
993 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
994 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
995 "Please report this message, the output of `ich_descriptors_tool` for\n"
996 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
997 return CHIPSET_100_SERIES_SUNRISE_POINT;
998 }
999 return guess;
1000 }
1001}
1002
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001003/* len is the length of dump in bytes */
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +10001004int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
1005 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001006{
Edward O'Callaghan01e8d322020-07-09 18:26:43 +10001007 ssize_t i, max_count;
1008 size_t pch_bug_offset = 0;
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001009
1010 if (dump == NULL || desc == NULL)
1011 return ICH_RET_PARAM;
1012
1013 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1014 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1015 pch_bug_offset = 4;
1016 else
1017 return ICH_RET_ERR;
1018 }
1019
1020 /* map */
Nico Huber61b10c72017-03-28 17:08:46 +02001021 if (len < (4 + pch_bug_offset) * 4)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001022 return ICH_RET_OOB;
1023 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1024 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1025 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1026 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1027
1028 /* component */
Nico Huber61b10c72017-03-28 17:08:46 +02001029 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001030 return ICH_RET_OOB;
1031 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1032 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1033 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1034
Edward O'Callaghan01e8d322020-07-09 18:26:43 +10001035 if (*cs == CHIPSET_ICH_UNKNOWN) {
1036 *cs = guess_ich_chipset(&desc->content, &desc->component);
1037 prettyprint_ich_chipset(*cs);
1038 }
1039
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001040 /* region */
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +10001041 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Edward O'Callaghane7efd052020-07-03 14:57:28 +10001042 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001043 return ICH_RET_OOB;
Edward O'Callaghane7efd052020-07-03 14:57:28 +10001044 for (i = 0; i < nr; i++)
1045 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001046
1047 /* master */
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +10001048 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
1049 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001050 return ICH_RET_OOB;
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +10001051 for (i = 0; i < nm; i++)
1052 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001053
1054 /* upper map */
1055 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1056
1057 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1058 * "Identifies the 1s based number of DWORDS contained in the VSCC
1059 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1060 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1061 * check ensures that the maximum offset actually accessed is available.
1062 */
Nico Huber61b10c72017-03-28 17:08:46 +02001063 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001064 return ICH_RET_OOB;
1065
1066 for (i = 0; i < desc->upper.VTL/2; i++) {
Edward O'Callaghan568cd262020-05-26 23:10:45 +10001067 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1068 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001069 }
1070
1071 /* MCH/PROC (aka. North) straps */
1072 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1073 return ICH_RET_OOB;
1074
1075 /* limit the range to be written */
Edward O'Callaghan01e8d322020-07-09 18:26:43 +10001076 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
1077 for (i = 0; i < max_count; i++)
Edward O'Callaghan568cd262020-05-26 23:10:45 +10001078 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001079
1080 /* ICH/PCH (aka. South) straps */
1081 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1082 return ICH_RET_OOB;
1083
1084 /* limit the range to be written */
Edward O'Callaghan01e8d322020-07-09 18:26:43 +10001085 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
1086 for (i = 0; i < max_count; i++)
Edward O'Callaghan568cd262020-05-26 23:10:45 +10001087 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001088
1089 return ICH_RET_OK;
1090}
1091
Edward O'Callaghanb76b4e62020-07-26 13:03:12 +10001092#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Tauner34f6f5a2016-08-03 11:20:38 -07001093
stefanct3d3b6ee2011-10-20 12:57:14 +00001094/** Returns the integer representation of the component density with index
Edward O'Callaghane0845d72020-07-05 13:28:03 +10001095\em idx in bytes or -1 if the correct size can not be determined. */
1096int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
stefanct3d3b6ee2011-10-20 12:57:14 +00001097{
Edward O'Callaghane0845d72020-07-05 13:28:03 +10001098 if (idx > 1) {
1099 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
1100 return -1;
1101 }
Edward O'Callaghan1229b212020-07-05 13:28:03 +10001102
Edward O'Callaghane0845d72020-07-05 13:28:03 +10001103 if (desc->content.NC == 0 && idx > 0)
1104 return 0;
1105
1106 uint8_t size_enc;
1107 uint8_t size_max;
1108
1109 switch (cs) {
1110 case CHIPSET_ICH8:
1111 case CHIPSET_ICH9:
1112 case CHIPSET_ICH10:
1113 case CHIPSET_5_SERIES_IBEX_PEAK:
1114 case CHIPSET_6_SERIES_COUGAR_POINT:
1115 case CHIPSET_7_SERIES_PANTHER_POINT:
1116 case CHIPSET_BAYTRAIL:
1117 if (idx == 0) {
1118 size_enc = desc->component.dens_old.comp1_density;
1119 } else {
1120 size_enc = desc->component.dens_old.comp2_density;
1121 }
1122 size_max = 5;
stefanct3d3b6ee2011-10-20 12:57:14 +00001123 break;
Edward O'Callaghane0845d72020-07-05 13:28:03 +10001124 case CHIPSET_8_SERIES_LYNX_POINT:
1125 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1126 case CHIPSET_8_SERIES_WELLSBURG:
1127 case CHIPSET_9_SERIES_WILDCAT_POINT:
1128 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
1129 case CHIPSET_100_SERIES_SUNRISE_POINT:
1130 case CHIPSET_C620_SERIES_LEWISBURG:
1131 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillier81bc4d32020-08-12 12:48:06 -05001132 case CHIPSET_400_SERIES_COMET_POINT:
Edward O'Callaghane0845d72020-07-05 13:28:03 +10001133 case CHIPSET_APOLLO_LAKE:
Angel Pons00b29cf2020-07-10 17:04:10 +02001134 case CHIPSET_GEMINI_LAKE:
Edward O'Callaghane0845d72020-07-05 13:28:03 +10001135 if (idx == 0) {
1136 size_enc = desc->component.dens_new.comp1_density;
1137 } else {
1138 size_enc = desc->component.dens_new.comp2_density;
1139 }
1140 size_max = 7;
stefanct3d3b6ee2011-10-20 12:57:14 +00001141 break;
Edward O'Callaghane0845d72020-07-05 13:28:03 +10001142 case CHIPSET_ICH_UNKNOWN:
stefanct3d3b6ee2011-10-20 12:57:14 +00001143 default:
Edward O'Callaghane0845d72020-07-05 13:28:03 +10001144 msg_pwarn("Density encoding is unknown on this chipset.\n");
1145 return -1;
stefanct3d3b6ee2011-10-20 12:57:14 +00001146 }
Edward O'Callaghane0845d72020-07-05 13:28:03 +10001147
1148 if (size_enc > size_max) {
1149 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
1150 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1151 idx, size_enc, size_max);
1152 return -1;
stefanct3d3b6ee2011-10-20 12:57:14 +00001153 }
Edward O'Callaghane0845d72020-07-05 13:28:03 +10001154
stefanct3d3b6ee2011-10-20 12:57:14 +00001155 return (1 << (19 + size_enc));
1156}
1157
Edward O'Callaghanb76b4e62020-07-26 13:03:12 +10001158/* Only used by ichspi.c */
1159#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Edward O'Callaghan5a7ae7a2020-05-18 16:29:45 +10001160static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
David Hendricksce6b2fa2011-07-11 22:12:43 -07001161{
1162 uint32_t control = 0;
1163 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1164 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Edward O'Callaghan9e6046c2020-05-26 23:24:08 +10001165 switch (cs) {
1166 case CHIPSET_100_SERIES_SUNRISE_POINT:
1167 case CHIPSET_C620_SERIES_LEWISBURG:
1168 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillier81bc4d32020-08-12 12:48:06 -05001169 case CHIPSET_400_SERIES_COMET_POINT:
Edward O'Callaghan9e6046c2020-05-26 23:24:08 +10001170 case CHIPSET_APOLLO_LAKE:
Angel Pons00b29cf2020-07-10 17:04:10 +02001171 case CHIPSET_GEMINI_LAKE:
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301172 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1173 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Edward O'Callaghan9e6046c2020-05-26 23:24:08 +10001174 default:
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301175 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1176 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1177 }
David Hendricksce6b2fa2011-07-11 22:12:43 -07001178}
1179
Edward O'Callaghan4b90b622020-05-18 16:20:56 +10001180int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
David Hendricksce6b2fa2011-07-11 22:12:43 -07001181{
Edward O'Callaghan0f6a2e52020-07-09 18:16:16 +10001182 ssize_t i;
stefanct1fc3a732011-09-15 23:52:55 +00001183 struct ich_desc_region *r = &desc->region;
1184
1185 /* Test if bit-fields are working as expected.
1186 * FIXME: Replace this with dynamic bitfield fixup
1187 */
1188 for (i = 0; i < 4; i++)
1189 desc->region.FLREGs[i] = 0x5A << (i * 8);
Edward O'Callaghan0f6a2e52020-07-09 18:16:16 +10001190 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1191 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1192 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1193 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
stefanct1fc3a732011-09-15 23:52:55 +00001194 msg_pdbg("The combination of compiler and CPU architecture used"
1195 "does not lay out bit-fields as expected, sorry.\n");
Edward O'Callaghan0f6a2e52020-07-09 18:16:16 +10001196 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1197 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1198 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1199 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1200 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1201 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1202 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1203 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
stefanct1fc3a732011-09-15 23:52:55 +00001204 return ICH_RET_ERR;
1205 }
1206
Edward O'Callaghan568cd262020-05-26 23:10:45 +10001207 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
stefanct1fc3a732011-09-15 23:52:55 +00001208 /* content section */
Edward O'Callaghan5a7ae7a2020-05-18 16:29:45 +10001209 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1210 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1211 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1212 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
David Hendricksce6b2fa2011-07-11 22:12:43 -07001213
1214 /* component section */
Edward O'Callaghan5a7ae7a2020-05-18 16:29:45 +10001215 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1216 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1217 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
David Hendricksce6b2fa2011-07-11 22:12:43 -07001218
1219 /* region section */
Edward O'Callaghane7efd052020-07-03 14:57:28 +10001220 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1221 if (nr < 0) {
stefanct1fc3a732011-09-15 23:52:55 +00001222 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Edward O'Callaghane7efd052020-07-03 14:57:28 +10001223 __func__, desc->content.NR + 1);
stefanct1fc3a732011-09-15 23:52:55 +00001224 return ICH_RET_ERR;
1225 }
Edward O'Callaghane7efd052020-07-03 14:57:28 +10001226 for (i = 0; i < nr; i++)
Edward O'Callaghan5a7ae7a2020-05-18 16:29:45 +10001227 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
David Hendricksce6b2fa2011-07-11 22:12:43 -07001228
1229 /* master section */
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +10001230 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1231 if (nm < 0) {
1232 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1233 __func__, desc->content.NM + 1);
1234 return ICH_RET_ERR;
Duncan Lauriedbbf2222019-04-25 12:06:19 -07001235 }
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +10001236 for (i = 0; i < nm; i++)
1237 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
David Hendricksce6b2fa2011-07-11 22:12:43 -07001238
stefanct1fc3a732011-09-15 23:52:55 +00001239 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1240 * reading the upper map is impossible on all chipsets, so don't bother.
1241 */
1242
1243 msg_pdbg2(" done.\n");
1244 return ICH_RET_OK;
David Hendricksce6b2fa2011-07-11 22:12:43 -07001245}
Edward O'Callaghanb76b4e62020-07-26 13:03:12 +10001246#endif
1247
Edward O'Callaghan0055dc42020-12-06 10:33:45 +11001248/**
1249 * @brief Read a layout from the dump of an Intel ICH descriptor.
1250 *
1251 * @param layout Pointer where to store the layout.
1252 * @param dump The descriptor dump to read from.
1253 * @param len The length of the descriptor dump.
1254 *
1255 * @return 0 on success,
1256 * 1 if the descriptor couldn't be parsed,
1257 * 2 when out of memory.
1258 */
1259int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1260{
1261 static const char *const regions[] = {
1262 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1263 "10gbe", "reg12", "reg13", "reg14", "reg15"
1264 };
1265
1266 struct ich_descriptors desc;
1267 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1268 int ret = read_ich_descriptors_from_dump(dump, len, &cs, &desc);
1269 if (ret) {
1270 msg_pdbg("%s():%d, returned with value %d.\n",
1271 __func__, __LINE__, ret);
1272 return 1;
1273 }
1274
1275 memset(layout, 0x00, sizeof(*layout));
1276
1277 ssize_t i, j;
1278 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
1279 for (i = 0, j = 0; i < nr; ++i) {
1280 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
1281 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
1282 if (limit <= base)
1283 continue;
1284 layout->entries[j].start = base;
1285 layout->entries[j].end = limit;
1286 layout->entries[j].included = false;
1287 layout->entries[j].name = strdup(regions[i]);
1288 if (!layout->entries[j].name)
1289 return 2;
1290 ++j;
1291 }
1292 layout->base.entries = layout->entries;
1293 layout->base.num_entries = j;
1294 return 0;
1295}
1296
Edward O'Callaghanb76b4e62020-07-26 13:03:12 +10001297#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */