blob: cd92c512ef42e6b0bed3f108a830a8b67982c60e [file] [log] [blame]
Stefan Tauner1e146392011-09-15 23:52:55 +00001/*
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.
Stefan Tauner1e146392011-09-15 23:52:55 +000016 */
17
Thomas Heijligen3f4d35d2022-01-17 15:11:43 +010018#include "hwaccess_physmap.h"
Stefan Tauner1e146392011-09-15 23:52:55 +000019#include "ich_descriptors.h"
Stefan Taunerb3850962011-12-24 00:00:32 +000020
Nico Huberad186312016-05-02 15:15:29 +020021#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +000022#include <stdio.h>
Nico Huber305f4172013-06-14 11:55:26 +020023#include <string.h>
Stefan Taunerb3850962011-12-24 00:00:32 +000024#define print(t, ...) printf(__VA_ARGS__)
Nico Huberad186312016-05-02 15:15:29 +020025#endif
26
Stefan Taunerb3850962011-12-24 00:00:32 +000027#define DESCRIPTOR_MODE_SIGNATURE 0x0ff0a55a
28/* The upper map is located in the word before the 256B-long OEM section at the
29 * end of the 4kB-long flash descriptor.
30 */
31#define UPPER_MAP_OFFSET (4096 - 256 - 4)
32#define getVTBA(flumap) (((flumap)->FLUMAP1 << 4) & 0x00000ff0)
33
Felix Singerd68a0ec2022-08-19 03:23:35 +020034#include <stdbool.h>
Nico Huber4d440a72017-08-15 11:26:48 +020035#include <sys/types.h>
Nico Huberad186312016-05-02 15:15:29 +020036#include <string.h>
Stefan Tauner1e146392011-09-15 23:52:55 +000037#include "flash.h" /* for msg_* */
38#include "programmer.h"
39
Nico Huberfa622942017-03-24 17:25:37 +010040ssize_t ich_number_of_regions(const enum ich_chipset cs, const struct ich_desc_content *const cont)
41{
42 switch (cs) {
Nico Huberd2d39932019-01-18 16:49:37 +010043 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +020044 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +010045 return 6;
David Hendricksa5216362017-08-08 20:02:22 -070046 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +020047 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +020048 case CHIPSET_500_SERIES_TIGER_POINT:
Werner Zehe57d4e42022-01-03 09:44:29 +010049 case CHIPSET_ELKHART_LAKE:
David Hendricksa5216362017-08-08 20:02:22 -070050 return 16;
Nico Huberfa622942017-03-24 17:25:37 +010051 case CHIPSET_100_SERIES_SUNRISE_POINT:
52 return 10;
53 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
54 case CHIPSET_9_SERIES_WILDCAT_POINT:
55 case CHIPSET_8_SERIES_LYNX_POINT_LP:
56 case CHIPSET_8_SERIES_LYNX_POINT:
57 case CHIPSET_8_SERIES_WELLSBURG:
58 if (cont->NR <= 6)
59 return cont->NR + 1;
60 else
61 return -1;
62 default:
63 if (cont->NR <= 4)
64 return cont->NR + 1;
65 else
66 return -1;
67 }
68}
69
70ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
71{
David Hendricksa5216362017-08-08 20:02:22 -070072 switch (cs) {
73 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberd2d39932019-01-18 16:49:37 +010074 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +020075 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +010076 case CHIPSET_ELKHART_LAKE:
David Hendricksa5216362017-08-08 20:02:22 -070077 if (cont->NM <= MAX_NUM_MASTERS)
78 return cont->NM;
Richard Hughesdb7482b2018-12-19 12:04:30 +000079 break;
David Hendricksa5216362017-08-08 20:02:22 -070080 default:
81 if (cont->NM < MAX_NUM_MASTERS)
82 return cont->NM + 1;
83 }
84
85 return -1;
Nico Huberfa622942017-03-24 17:25:37 +010086}
87
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000088void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000089{
90 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
91 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
92 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
93 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000094 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
95 if (print_vcl)
96 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
97 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000098}
99
100#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
101#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
102#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
103#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
104#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
105
Nico Huber67d71792017-06-17 03:10:15 +0200106void prettyprint_ich_chipset(enum ich_chipset cs)
107{
108 static const char *const chipset_names[] = {
109 "Unknown ICH", "ICH8", "ICH9", "ICH10",
110 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
111 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
112 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
Angel Pons4db0fdf2020-07-10 17:04:10 +0200113 "C620 series Lewisburg", "300/400 series Cannon/Comet Point",
Nico Huber29c23dd2022-12-21 15:25:09 +0000114 "500/600 series Tiger/Alder Point", "Apollo Lake", "Gemini Lake", "Elkhart Lake",
Nico Huber67d71792017-06-17 03:10:15 +0200115 };
116 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
117 cs = 0;
118 else
119 cs = cs - CHIPSET_ICH8 + 1;
120 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
121}
122
Stefan Tauner1e146392011-09-15 23:52:55 +0000123void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
124{
Nico Huberfa622942017-03-24 17:25:37 +0100125 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000126 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100127 prettyprint_ich_descriptor_region(cs, desc);
128 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200129#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000130 if (cs >= CHIPSET_ICH8) {
131 prettyprint_ich_descriptor_upper_map(&desc->upper);
132 prettyprint_ich_descriptor_straps(cs, desc);
133 }
Nico Huberad186312016-05-02 15:15:29 +0200134#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000135}
136
Nico Huberfa622942017-03-24 17:25:37 +0100137void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000138{
139 msg_pdbg2("=== Content Section ===\n");
140 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
141 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
142 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
143 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
144 msg_pdbg2("\n");
145
146 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100147 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
148 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
149 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
150 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
Nico Huberd2d39932019-01-18 16:49:37 +0100151 msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL);
152 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont));
Nico Huberfa622942017-03-24 17:25:37 +0100153 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
154 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
155 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
156 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000157 msg_pdbg2("\n");
158}
159
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000160static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
161{
162 if (idx > 1) {
163 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
164 return NULL;
165 }
166
167 if (desc->content.NC == 0 && idx > 0)
168 return "unused";
169
170 static const char * const size_str[] = {
171 "512 kB", /* 0000 */
172 "1 MB", /* 0001 */
173 "2 MB", /* 0010 */
174 "4 MB", /* 0011 */
175 "8 MB", /* 0100 */
176 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
177 "32 MB", /* 0110 */
178 "64 MB", /* 0111 */
179 };
180
181 switch (cs) {
182 case CHIPSET_ICH8:
183 case CHIPSET_ICH9:
184 case CHIPSET_ICH10:
185 case CHIPSET_5_SERIES_IBEX_PEAK:
186 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000187 case CHIPSET_7_SERIES_PANTHER_POINT:
188 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000189 uint8_t size_enc;
190 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000191 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000192 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000193 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000194 }
195 if (size_enc > 5)
196 return "reserved";
197 return size_str[size_enc];
198 }
199 case CHIPSET_8_SERIES_LYNX_POINT:
200 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000201 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100202 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100203 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
David Hendricksa5216362017-08-08 20:02:22 -0700204 case CHIPSET_100_SERIES_SUNRISE_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100205 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200206 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200207 case CHIPSET_500_SERIES_TIGER_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200208 case CHIPSET_APOLLO_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +0100209 case CHIPSET_GEMINI_LAKE:
210 case CHIPSET_ELKHART_LAKE: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000211 uint8_t size_enc;
212 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000213 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000214 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000215 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000216 }
217 if (size_enc > 7)
218 return "reserved";
219 return size_str[size_enc];
220 }
221 case CHIPSET_ICH_UNKNOWN:
222 default:
223 return "unknown";
224 }
225}
226
227static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000228{
Werner Zehe57d4e42022-01-03 09:44:29 +0100229 static const char *const freq_str[5][8] = { {
Nico Huber129e9382019-06-06 15:43:27 +0200230 "20 MHz",
231 "33 MHz",
232 "reserved",
233 "reserved",
234 "50 MHz", /* New since Ibex Peak */
235 "reserved",
236 "reserved",
237 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100238 }, {
Nico Huber129e9382019-06-06 15:43:27 +0200239 "reserved",
240 "reserved",
241 "48 MHz",
242 "reserved",
243 "30 MHz",
244 "reserved",
245 "17 MHz",
246 "reserved"
Nico Huberd2d39932019-01-18 16:49:37 +0100247 }, {
248 "reserved",
249 "50 MHz",
250 "40 MHz",
251 "reserved",
252 "25 MHz",
253 "reserved",
254 "14 MHz / 17 MHz",
255 "reserved"
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200256 }, {
257 "100 MHz",
258 "50 MHz",
259 "reserved",
260 "33 MHz",
261 "25 MHz",
262 "reserved",
263 "14 MHz",
264 "reserved"
Werner Zehe57d4e42022-01-03 09:44:29 +0100265 }, {
266 "reserved",
267 "50 MHz",
268 "reserved",
269 "reserved",
270 "33 MHz",
271 "20 MHz",
272 "reserved",
273 "reserved",
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200274 }};
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000275
276 switch (cs) {
277 case CHIPSET_ICH8:
278 case CHIPSET_ICH9:
279 case CHIPSET_ICH10:
280 if (value > 1)
281 return "reserved";
Richard Hughesdb7482b2018-12-19 12:04:30 +0000282 /* Fall through. */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000283 case CHIPSET_5_SERIES_IBEX_PEAK:
284 case CHIPSET_6_SERIES_COUGAR_POINT:
285 case CHIPSET_7_SERIES_PANTHER_POINT:
286 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000287 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000288 case CHIPSET_8_SERIES_LYNX_POINT_LP:
289 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000290 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100291 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100292 return freq_str[0][value];
293 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700294 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200295 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100296 return freq_str[1][value];
Nico Huberd2d39932019-01-18 16:49:37 +0100297 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200298 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100299 return freq_str[2][value];
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200300 case CHIPSET_500_SERIES_TIGER_POINT:
301 return freq_str[3][value];
Werner Zehe57d4e42022-01-03 09:44:29 +0100302 case CHIPSET_ELKHART_LAKE:
303 return freq_str[4][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000304 case CHIPSET_ICH_UNKNOWN:
305 default:
306 return "unknown";
307 }
308}
309
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200310static void pprint_read_freq(enum ich_chipset cs, uint8_t value)
311{
312 static const char *const freq_str[1][8] = { {
313 "20 MHz",
314 "24 MHz",
315 "30 MHz",
316 "48 MHz",
317 "60 MHz",
318 "reserved",
319 "reserved",
320 "reserved"
321 }};
322
323 switch (cs) {
324 case CHIPSET_300_SERIES_CANNON_POINT:
325 msg_pdbg2("eSPI/EC Bus Clock Frequency: %s\n", freq_str[0][value]);
326 return;
327 case CHIPSET_500_SERIES_TIGER_POINT:
328 msg_pdbg2("Read Clock Frequency: %s\n", "reserved");
329 return;
330 default:
331 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, value));
332 return;
333 }
334}
335
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000336void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
337{
Nico Huberd2d39932019-01-18 16:49:37 +0100338 bool has_flill1;
339
340 switch (cs) {
341 case CHIPSET_100_SERIES_SUNRISE_POINT:
342 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200343 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200344 case CHIPSET_500_SERIES_TIGER_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100345 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200346 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +0100347 case CHIPSET_ELKHART_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100348 has_flill1 = true;
349 break;
350 default:
351 has_flill1 = false;
352 break;
353 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000354
355 msg_pdbg2("=== Component Section ===\n");
356 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
357 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberd2d39932019-01-18 16:49:37 +0100358 if (has_flill1)
Nico Huberfa622942017-03-24 17:25:37 +0100359 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000360 msg_pdbg2("\n");
361
362 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000363 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000364 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000365 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000366 else
367 msg_pdbg2("Component 2 is not used.\n");
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200368
369 pprint_read_freq(cs, desc->component.modes.freq_read);
370
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000371 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
372 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
373 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
374 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000375 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000376 pprint_freq(cs, desc->component.modes.freq_fastread));
Nico Huber3f75d442024-07-14 19:17:56 +0200377 switch (cs) {
378 case CHIPSET_7_SERIES_PANTHER_POINT:
379 case CHIPSET_8_SERIES_LYNX_POINT:
380 case CHIPSET_BAYTRAIL:
381 case CHIPSET_8_SERIES_LYNX_POINT_LP:
382 case CHIPSET_8_SERIES_WELLSBURG:
383 case CHIPSET_9_SERIES_WILDCAT_POINT:
384 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
385 case CHIPSET_100_SERIES_SUNRISE_POINT:
386 case CHIPSET_APOLLO_LAKE:
387 case CHIPSET_C620_SERIES_LEWISBURG:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000388 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Werner Zehd3e8fd92022-01-25 07:02:49 +0100389 desc->component.modes.dual_output ? "en" : "dis");
Nico Huber3f75d442024-07-14 19:17:56 +0200390 break;
391 default:
392 break;
393 }
David Hendricksa5216362017-08-08 20:02:22 -0700394
Felix Singerd68a0ec2022-08-19 03:23:35 +0200395 bool has_forbidden_opcode = false;
David Hendricksa5216362017-08-08 20:02:22 -0700396 if (desc->component.FLILL != 0) {
Felix Singerd68a0ec2022-08-19 03:23:35 +0200397 has_forbidden_opcode = true;
Stefan Tauner1e146392011-09-15 23:52:55 +0000398 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
399 desc->component.invalid_instr0);
400 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
401 desc->component.invalid_instr1);
402 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
403 desc->component.invalid_instr2);
404 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
405 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700406 }
Nico Huberd2d39932019-01-18 16:49:37 +0100407 if (has_flill1) {
David Hendricksa5216362017-08-08 20:02:22 -0700408 if (desc->component.FLILL1 != 0) {
Felix Singerd68a0ec2022-08-19 03:23:35 +0200409 has_forbidden_opcode = true;
Nico Huberfa622942017-03-24 17:25:37 +0100410 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
411 desc->component.invalid_instr4);
412 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
413 desc->component.invalid_instr5);
414 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
415 desc->component.invalid_instr6);
416 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
417 desc->component.invalid_instr7);
418 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000419 }
David Hendricksa5216362017-08-08 20:02:22 -0700420 if (!has_forbidden_opcode)
421 msg_pdbg2("No forbidden opcodes.\n");
422
Stefan Tauner1e146392011-09-15 23:52:55 +0000423 msg_pdbg2("\n");
424}
425
426static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
427{
Nico Huberfa622942017-03-24 17:25:37 +0100428 static const char *const region_names[] = {
Nico Huberd2d39932019-01-18 16:49:37 +0100429 "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown",
David Hendricksa5216362017-08-08 20:02:22 -0700430 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000431 };
Nico Huberfa622942017-03-24 17:25:37 +0100432 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000433 msg_pdbg2("%s: region index too high.\n", __func__);
434 return;
435 }
436 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
437 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100438 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000439 if (base > limit)
440 msg_pdbg2("is unused.\n");
441 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200442 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000443}
444
Nico Huberfa622942017-03-24 17:25:37 +0100445void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000446{
Nico Huber519be662018-12-23 20:03:35 +0100447 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100448 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000449 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100450 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000451 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100452 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000453 return;
454 }
Nico Huberfa622942017-03-24 17:25:37 +0100455 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100456 msg_pdbg2("FLREG%zd 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000457 msg_pdbg2("\n");
458
459 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100460 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100461 pprint_freg(&desc->region, (uint32_t)i);
Stefan Tauner1e146392011-09-15 23:52:55 +0000462 msg_pdbg2("\n");
463}
464
Nico Huberfa622942017-03-24 17:25:37 +0100465void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000466{
Nico Huber519be662018-12-23 20:03:35 +0100467 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100468 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000469 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100470 if (nm < 0) {
471 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
472 desc->content.NM + 1);
473 return;
474 }
475 for (i = 0; i < nm; i++)
Nico Huber519be662018-12-23 20:03:35 +0100476 msg_pdbg2("FLMSTR%zd 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000477 msg_pdbg2("\n");
478
479 msg_pdbg2("--- Details ---\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200480 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT ||
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200481 cs == CHIPSET_300_SERIES_CANNON_POINT ||
482 cs == CHIPSET_500_SERIES_TIGER_POINT) {
Nico Huberfa622942017-03-24 17:25:37 +0100483 const char *const master_names[] = {
484 "BIOS", "ME", "GbE", "unknown", "EC",
485 };
Nico Huber519be662018-12-23 20:03:35 +0100486 if (nm >= (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberfa622942017-03-24 17:25:37 +0100487 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
488 desc->content.NM + 1);
489 return;
490 }
491
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200492 size_t num_regions;
493 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9");
494 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
495 num_regions = 10;
496 msg_pdbg2("\n");
497 } else {
498 num_regions = 16;
499 msg_pdbg2(" RegA RegB RegC RegD RegE RegF\n");
500 }
Nico Huberfa622942017-03-24 17:25:37 +0100501 for (i = 0; i < nm; i++) {
aarya0ac29562022-03-13 15:35:12 +0530502 const unsigned int ext_region_start = 12;
Nico Huberfa622942017-03-24 17:25:37 +0100503 size_t j;
504 msg_pdbg2("%-4s", master_names[i]);
aarya0ac29562022-03-13 15:35:12 +0530505 for (j = 0; j < (size_t)min(num_regions, ext_region_start); j++)
Nico Huberfa622942017-03-24 17:25:37 +0100506 msg_pdbg2(" %c%c ",
507 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
508 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
aarya0ac29562022-03-13 15:35:12 +0530509 for (j = ext_region_start; j < num_regions; j++)
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200510 msg_pdbg2(" %c%c ",
aarya0ac29562022-03-13 15:35:12 +0530511 desc->master.mstr[i].ext_read & (1 << (j - ext_region_start)) ? 'r' : ' ',
512 desc->master.mstr[i].ext_write & (1 << (j - ext_region_start)) ? 'w' : ' ');
Nico Huberfa622942017-03-24 17:25:37 +0100513 msg_pdbg2("\n");
514 }
David Hendricksa5216362017-08-08 20:02:22 -0700515 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
516 const char *const master_names[] = {
517 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
518 };
519 /* NM starts at 1 instead of 0 for LBG */
Nico Huber519be662018-12-23 20:03:35 +0100520 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
David Hendricksa5216362017-08-08 20:02:22 -0700521 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
522 desc->content.NM);
523 return;
524 }
525
526 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
527 " ", /* width of master name (4 chars minimum) */
528 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
529 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
530 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
531 "Reg15");
532 for (i = 0; i < nm; i++) {
533 size_t j;
534 msg_pdbg2("%-4s", master_names[i]);
535 for (j = 0; j < 16; j++)
536 msg_pdbg2(" %c%c ",
537 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
538 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
539 msg_pdbg2("\n");
540 }
Werner Zehe57d4e42022-01-03 09:44:29 +0100541 } else if (cs == CHIPSET_APOLLO_LAKE || cs == CHIPSET_GEMINI_LAKE || cs == CHIPSET_ELKHART_LAKE) {
Nico Huberd2d39932019-01-18 16:49:37 +0100542 const char *const master_names[] = { "BIOS", "TXE", };
Nico Huber519be662018-12-23 20:03:35 +0100543 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberd2d39932019-01-18 16:49:37 +0100544 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
545 return;
546 }
547
548 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
549 for (i = 0; i < nm; i++) {
Nico Huber519be662018-12-23 20:03:35 +0100550 ssize_t j;
Nico Huberd2d39932019-01-18 16:49:37 +0100551 msg_pdbg2("%-4s", master_names[i]);
552 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
553 msg_pdbg2(" %c%c ",
554 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
555 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
556 msg_pdbg2("\n");
557 }
Nico Huberfa622942017-03-24 17:25:37 +0100558 } else {
559 const struct ich_desc_master *const mstr = &desc->master;
560 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
561 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
562 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
563 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
564 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
565 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
566 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
567 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
568 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
569 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
570 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
571 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
572 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
573 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
574 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
575 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
576 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
577 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
578 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
579 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000580 msg_pdbg2("\n");
581}
582
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600583static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000584{
585 static const char * const str_GPIO12[4] = {
586 "GPIO12",
587 "LAN PHY Power Control Function (Native Output)",
588 "GLAN_DOCK# (Native Input)",
589 "invalid configuration",
590 };
591
592 msg_pdbg2("--- MCH details ---\n");
593 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
594 msg_pdbg2("\n");
595
596 msg_pdbg2("--- ICH details ---\n");
597 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
598 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
599 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
600 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
601 msg_pdbg2("SPI CS1 is used for %s.\n",
602 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
603 "LAN PHY Power Control Function" :
604 "SPI Chip Select");
605 msg_pdbg2("GPIO12 is used as %s.\n",
606 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
607 msg_pdbg2("PCIe Port 6 is used for %s.\n",
608 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
609 msg_pdbg2("%sn BMC Mode: "
610 "Intel AMT SMBus Controller 1 is connected to %s.\n",
611 desc->south.ich8.BMCMODE ? "I" : "Not i",
612 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
613 msg_pdbg2("TCO is in %s Mode.\n",
614 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
615 msg_pdbg2("ME A is %sabled.\n",
616 desc->south.ich8.ME_DISABLE ? "dis" : "en");
617 msg_pdbg2("\n");
618}
619
620static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
621{
622 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
623
624 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000625 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000626 case 0:
627 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
628 break;
629 case 1:
630 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
631 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
632 break;
633 case 2:
634 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
635 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
636 break;
637 case 3:
638 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
639 1+off, 2+off, 4+off);
640 break;
641 }
642 msg_pdbg2("\n");
643}
644
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600645static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000646{
647 /* PCHSTRP4 */
648 msg_pdbg2("Intel PHY is %s.\n",
649 (s->ibex.PHYCON == 2) ? "connected" :
650 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
651 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
652 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
653 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
654 s->ibex.GBEMAC_SMBUS_ADDR);
655 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
656 s->ibex.GBEPHY_SMBUS_ADDR);
657
658 /* PCHSTRP5 */
659 /* PCHSTRP6 */
660 /* PCHSTRP7 */
661 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
662 s->ibex.MESMA2UDID_VENDOR);
663 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
664 s->ibex.MESMA2UDID_VENDOR);
665
666 /* PCHSTRP8 */
667}
668
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600669static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000670{
671 /* PCHSTRP11 */
672 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
673 s->ibex.SML1GPAEN ? "en" : "dis");
674 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
675 s->ibex.SML1GPA);
676 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
677 s->ibex.SML1I2CAEN ? "en" : "dis");
678 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
679 s->ibex.SML1I2CA);
680
681 /* PCHSTRP12 */
682 /* PCHSTRP13 */
683}
684
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600685static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000686{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000687 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000688 100,
689 50,
690 5,
691 1
692 };
693
694 msg_pdbg2("--- PCH ---\n");
695
696 /* PCHSTRP0 */
697 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
698 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
699 s->ibex.SMB_EN ? "en" : "dis");
700 msg_pdbg2("SMLink0 segment is %sabled.\n",
701 s->ibex.SML0_EN ? "en" : "dis");
702 msg_pdbg2("SMLink1 segment is %sabled.\n",
703 s->ibex.SML1_EN ? "en" : "dis");
704 msg_pdbg2("SMLink1 Frequency: %s\n",
705 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
706 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
707 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
708 msg_pdbg2("SMLink0 Frequency: %s\n",
709 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
710 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
711 "LAN_PHY_PWR_CTRL" : "general purpose output");
712 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
713 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
714 s->ibex.DMI_REQID_DIS ? "en" : "dis");
715 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
716 1 << (6 + s->ibex.BBBS));
717
718 /* PCHSTRP1 */
719 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
720
721 /* PCHSTRP2 */
722 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
723 s->ibex.MESMASDEN ? "en" : "dis");
724 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
725 s->ibex.MESMASDA);
726 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
727 s->ibex.MESMI2CEN ? "en" : "dis");
728 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
729 s->ibex.MESMI2CA);
730
731 /* PCHSTRP3 */
732 prettyprint_ich_descriptor_pchstraps45678_56(s);
733 /* PCHSTRP9 */
734 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
735 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
736 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
737 s->ibex.PCIELR1 ? "" : "not ");
738 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
739 s->ibex.PCIELR2 ? "" : "not ");
740 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
741 s->ibex.DMILR ? "" : "not ");
742 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
743 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
744 s->ibex.PHY_PCIE_EN ? "en" : "dis");
745
746 /* PCHSTRP10 */
747 msg_pdbg2("Management Engine will boot from %sflash.\n",
748 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
749 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
750 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
751 s->ibex.VE_EN ? "en" : "dis");
752 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
753 s->ibex.MMDDE ? "en" : "dis");
754 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
755 s->ibex.MMADDR);
756 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
757 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
758 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
759 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
760 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
761
762 prettyprint_ich_descriptor_pchstraps111213_56(s);
763
764 /* PCHSTRP14 */
765 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
766 s->ibex.VE_EN2 ? "en" : "dis");
767 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
768 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
769 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
770 s->ibex.BW_SSD ? "en" : "dis");
771 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
772 s->ibex.NVMHCI_EN ? "en" : "dis");
773
774 /* PCHSTRP15 */
775 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
776 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
777 s->ibex.IWL_EN ? "en" : "dis");
778 msg_pdbg2("t209 min Timing: %d ms\n",
779 dec_t209min[s->ibex.t209min]);
780 msg_pdbg2("\n");
781}
782
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600783static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000784{
785 msg_pdbg2("--- PCH ---\n");
786
787 /* PCHSTRP0 */
788 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
789 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
790 s->ibex.SMB_EN ? "en" : "dis");
791 msg_pdbg2("SMLink0 segment is %sabled.\n",
792 s->ibex.SML0_EN ? "en" : "dis");
793 msg_pdbg2("SMLink1 segment is %sabled.\n",
794 s->ibex.SML1_EN ? "en" : "dis");
795 msg_pdbg2("SMLink1 Frequency: %s\n",
796 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
797 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
798 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
799 msg_pdbg2("SMLink0 Frequency: %s\n",
800 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
801 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
802 "LAN_PHY_PWR_CTRL" : "general purpose output");
803 msg_pdbg2("LinkSec is %sabled.\n",
804 s->cougar.LINKSEC_DIS ? "en" : "dis");
805 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
806 s->ibex.DMI_REQID_DIS ? "en" : "dis");
807 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
808 1 << (6 + s->ibex.BBBS));
809
810 /* PCHSTRP1 */
811 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
812 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
813
814 /* PCHSTRP2 */
815 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
816 s->ibex.MESMASDEN ? "en" : "dis");
817 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
818 s->ibex.MESMASDA);
819 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
820 s->cougar.MESMMCTPAEN ? "en" : "dis");
821 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
822 s->cougar.MESMMCTPA);
823 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
824 s->ibex.MESMI2CEN ? "en" : "dis");
825 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
826 s->ibex.MESMI2CA);
827
828 /* PCHSTRP3 */
829 prettyprint_ich_descriptor_pchstraps45678_56(s);
830 /* PCHSTRP9 */
831 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
832 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
833 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
834 s->ibex.PCIELR1 ? "" : "not ");
835 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
836 s->ibex.PCIELR2 ? "" : "not ");
837 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
838 s->ibex.DMILR ? "" : "not ");
839 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
840 s->cougar.MDSMBE_EN ? "en" : "dis");
841 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
842 s->cougar.MDSMBE_ADD);
843 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
844 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
845 s->ibex.PHY_PCIE_EN ? "en" : "dis");
846 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
847 s->cougar.SUB_DECODE_EN ? "en" : "dis");
848 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
849 "PCHHOT#" : "SML1ALERT#");
850
851 /* PCHSTRP10 */
852 msg_pdbg2("Management Engine will boot from %sflash.\n",
853 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
854
855 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
856 s->cougar.MDSMBE_EN ? "en" : "dis");
857 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
858 s->cougar.MDSMBE_ADD);
859
860 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
861 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000862 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
863 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000864 msg_pdbg2("ICC Profile is selected by %s.\n",
865 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
866 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
867 s->cougar.Deep_SX_EN ? "not " : "");
868 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
869 s->cougar.ME_DBG_LAN ? "en" : "dis");
870
871 prettyprint_ich_descriptor_pchstraps111213_56(s);
872
873 /* PCHSTRP14 */
874 /* PCHSTRP15 */
875 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
876 msg_pdbg2("Integrated wired LAN is %sabled.\n",
877 s->cougar.IWL_EN ? "en" : "dis");
878 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
879 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000880 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000881 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
882 "general purpose output" : "SLP_LAN#");
883
884 /* PCHSTRP16 */
885 /* PCHSTRP17 */
886 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
887 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
888 msg_pdbg2("\n");
889}
890
891void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
892{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000893 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000894 msg_pdbg2("=== Softstraps ===\n");
895
Nico Huber519be662018-12-23 20:03:35 +0100896 max_count = MIN(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
Nico Huberd7c75522017-03-29 16:31:49 +0200897 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000898 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200899 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000900 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200901 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000902
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000903 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
904 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000905 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
906 msg_pdbg2("\n");
907
Nico Huber519be662018-12-23 20:03:35 +0100908 max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
Nico Huberd7c75522017-03-29 16:31:49 +0200909 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000910 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
911 desc->content.ISL, max_count);
912 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200913 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000914
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000915 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
916 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000917 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
918 msg_pdbg2("\n");
919
920 switch (cs) {
921 case CHIPSET_ICH8:
922 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
923 msg_pdbg2("Detailed North/MCH/PROC information is "
924 "probably not reliable, printing anyway.\n");
925 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
926 msg_pdbg2("Detailed South/ICH/PCH information is "
927 "probably not reliable, printing anyway.\n");
928 prettyprint_ich_descriptor_straps_ich8(desc);
929 break;
930 case CHIPSET_5_SERIES_IBEX_PEAK:
931 /* PCH straps only. PROCSTRPs are unknown. */
932 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
933 msg_pdbg2("Detailed South/ICH/PCH information is "
934 "probably not reliable, printing anyway.\n");
935 prettyprint_ich_descriptor_straps_ibex(&desc->south);
936 break;
937 case CHIPSET_6_SERIES_COUGAR_POINT:
938 /* PCH straps only. PROCSTRP0 is "reserved". */
939 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
940 msg_pdbg2("Detailed South/ICH/PCH information is "
941 "probably not reliable, printing anyway.\n");
942 prettyprint_ich_descriptor_straps_cougar(&desc->south);
943 break;
944 case CHIPSET_ICH_UNKNOWN:
945 break;
946 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000947 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000948 break;
949 }
950}
951
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600952static void prettyprint_rdid(uint32_t reg_val)
Stefan Taunerb3850962011-12-24 00:00:32 +0000953{
954 uint8_t mid = reg_val & 0xFF;
955 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
956 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
957}
958
959void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
960{
961 int i;
962 msg_pdbg2("=== Upper Map Section ===\n");
963 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
964 msg_pdbg2("\n");
965
966 msg_pdbg2("--- Details ---\n");
967 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
968 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
969 msg_pdbg2("\n");
970
971 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000972 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000973 uint32_t jid = umap->vscc_table[i].JID;
974 uint32_t vscc = umap->vscc_table[i].VSCC;
975 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
976 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
Martin Rothf6c1cb12022-03-15 10:55:25 -0600977 msg_pdbg2(" "); /* indentation */
Stefan Taunerb3850962011-12-24 00:00:32 +0000978 prettyprint_rdid(jid);
Martin Rothf6c1cb12022-03-15 10:55:25 -0600979 msg_pdbg2(" "); /* indentation */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000980 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000981 }
982 msg_pdbg2("\n");
983}
984
David Hendricks66565a72021-09-20 21:56:40 -0700985static inline void warn_peculiar_desc(const char *const name)
Nico Huber964007a2021-06-17 21:12:47 +0200986{
Nico Huber964007a2021-06-17 21:12:47 +0200987 msg_pwarn("Peculiar flash descriptor, assuming %s compatibility.\n", name);
988}
989
Nico Huber1dc3d422017-06-17 00:09:31 +0200990/*
991 * Guesses a minimum chipset version based on the maximum number of
Nico Huber3ad9aad2021-06-17 22:05:00 +0200992 * soft straps per generation and presence of the MIP base (MDTBA).
Nico Huber1dc3d422017-06-17 00:09:31 +0200993 */
Nico Huber3ad9aad2021-06-17 22:05:00 +0200994static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content,
995 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +0200996{
997 if (content->ICCRIBA == 0x00) {
998 if (content->MSL == 0 && content->ISL <= 2)
999 return CHIPSET_ICH8;
Nico Huber83b01c82021-06-17 21:20:09 +02001000 if (content->ISL <= 2)
Nico Huber1dc3d422017-06-17 00:09:31 +02001001 return CHIPSET_ICH9;
Nico Huber83b01c82021-06-17 21:20:09 +02001002 if (content->ISL <= 10)
Nico Huber1dc3d422017-06-17 00:09:31 +02001003 return CHIPSET_ICH10;
David Hendricks66565a72021-09-20 21:56:40 -07001004 if (content->ISL <= 16)
1005 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber83b01c82021-06-17 21:20:09 +02001006 if (content->FLMAP2 == 0) {
Nico Huber81965f32021-06-17 23:25:35 +02001007 if (content->ISL == 19)
1008 return CHIPSET_APOLLO_LAKE;
David Hendricks66565a72021-09-20 21:56:40 -07001009 if (content->ISL == 23)
1010 return CHIPSET_GEMINI_LAKE;
1011 warn_peculiar_desc("Gemini Lake");
Nico Huber81965f32021-06-17 23:25:35 +02001012 return CHIPSET_GEMINI_LAKE;
Nico Huberd2d39932019-01-18 16:49:37 +01001013 }
Jonathan Zhang3bf7cfb2021-08-30 23:25:06 -07001014 if (content->ISL <= 80)
1015 return CHIPSET_C620_SERIES_LEWISBURG;
David Hendricks66565a72021-09-20 21:56:40 -07001016 warn_peculiar_desc("Ibex Peak");
Nico Huber1dc3d422017-06-17 00:09:31 +02001017 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber3ad9aad2021-06-17 22:05:00 +02001018 } else if (upper->MDTBA == 0x00) {
1019 if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
1020 if (content->MSL == 0 && content->ISL <= 17)
1021 return CHIPSET_BAYTRAIL;
1022 if (content->MSL <= 1 && content->ISL <= 18)
1023 return CHIPSET_6_SERIES_COUGAR_POINT;
David Hendricks66565a72021-09-20 21:56:40 -07001024 if (content->MSL <= 1 && content->ISL <= 21)
1025 return CHIPSET_8_SERIES_LYNX_POINT;
1026 warn_peculiar_desc("Lynx Point");
Nico Huber81965f32021-06-17 23:25:35 +02001027 return CHIPSET_8_SERIES_LYNX_POINT;
Nico Huber3ad9aad2021-06-17 22:05:00 +02001028 }
1029 if (content->NM == 6) {
David Hendricks66565a72021-09-20 21:56:40 -07001030 if (content->ICCRIBA <= 0x34)
1031 return CHIPSET_C620_SERIES_LEWISBURG;
1032 warn_peculiar_desc("C620 series");
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001033 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber3ad9aad2021-06-17 22:05:00 +02001034 }
David Hendricks66565a72021-09-20 21:56:40 -07001035 if (content->ICCRIBA == 0x31)
1036 return CHIPSET_100_SERIES_SUNRISE_POINT;
1037 warn_peculiar_desc("100 series");
Nico Huber83b01c82021-06-17 21:20:09 +02001038 return CHIPSET_100_SERIES_SUNRISE_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +02001039 } else {
David Hendricks66565a72021-09-20 21:56:40 -07001040 if (content->ICCRIBA == 0x34)
1041 return CHIPSET_300_SERIES_CANNON_POINT;
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001042 if (content->CSSL == 0x11)
1043 return CHIPSET_500_SERIES_TIGER_POINT;
Nico Huber29c23dd2022-12-21 15:25:09 +00001044 if (content->CSSL == 0x14) /* backwards compatible Alder Point */
1045 return CHIPSET_500_SERIES_TIGER_POINT;
Nico Huber756b6b32022-12-21 17:15:13 +00001046 if (content->CSSL == 0x03) {
1047 if (content->CSSO == 0x58)
1048 return CHIPSET_ELKHART_LAKE;
1049 else if (content->CSSO == 0x6c) /* backwards compatible Jasper Lake */
1050 return CHIPSET_300_SERIES_CANNON_POINT;
1051 }
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001052 msg_pwarn("Unknown flash descriptor, assuming 500 series compatibility.\n");
1053 return CHIPSET_500_SERIES_TIGER_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +02001054 }
1055}
1056
1057/*
1058 * As an additional measure, we check the read frequency like `ifdtool`.
1059 * The frequency value 6 (17MHz) was reserved before Skylake and is the
1060 * only valid value since. Skylake is currently the most important dis-
1061 * tinction because of the dropped number of regions field (NR).
1062 */
Nico Huberfa622942017-03-24 17:25:37 +01001063static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
Nico Huber3ad9aad2021-06-17 22:05:00 +02001064 const struct ich_desc_component *const component,
1065 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +02001066{
Nico Huber3ad9aad2021-06-17 22:05:00 +02001067 const enum ich_chipset guess = guess_ich_chipset_from_content(content, upper);
Nico Huber1dc3d422017-06-17 00:09:31 +02001068
Nico Huberd2d39932019-01-18 16:49:37 +01001069 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001070 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001071 case CHIPSET_500_SERIES_TIGER_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001072 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +01001073 case CHIPSET_ELKHART_LAKE:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001074 /* `freq_read` was repurposed, so can't check on it any more. */
Nico Huber72a9dc02021-06-17 22:47:00 +02001075 break;
Nico Huberd2d39932019-01-18 16:49:37 +01001076 case CHIPSET_100_SERIES_SUNRISE_POINT:
1077 case CHIPSET_C620_SERIES_LEWISBURG:
1078 case CHIPSET_APOLLO_LAKE:
1079 if (component->modes.freq_read != 6) {
Nico Huber964007a2021-06-17 21:12:47 +02001080 msg_pwarn("\nThe flash descriptor looks like a Skylake/Sunrise Point descriptor.\n"
Nico Huberd2d39932019-01-18 16:49:37 +01001081 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
1082 "Please report this message, the output of `ich_descriptors_tool` for\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +02001083 "your descriptor and the output of `lspci -nn` to flashprog@flashprog.org\n\n");
Nico Huberd2d39932019-01-18 16:49:37 +01001084 }
Nico Huber72a9dc02021-06-17 22:47:00 +02001085 break;
Nico Huberd2d39932019-01-18 16:49:37 +01001086 default:
1087 if (component->modes.freq_read == 6) {
Nico Huber964007a2021-06-17 21:12:47 +02001088 msg_pwarn("\nThe flash descriptor has the read frequency set to 17MHz. However,\n"
Nico Huber1dc3d422017-06-17 00:09:31 +02001089 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
1090 "Please report this message, the output of `ich_descriptors_tool` for\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +02001091 "your descriptor and the output of `lspci -nn` to flashprog@flashprog.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -07001092 }
Nico Huber1dc3d422017-06-17 00:09:31 +02001093 }
Nico Huber72a9dc02021-06-17 22:47:00 +02001094 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +02001095}
1096
Stefan Taunerb3850962011-12-24 00:00:32 +00001097/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +01001098int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
1099 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +00001100{
Nico Huber519be662018-12-23 20:03:35 +01001101 ssize_t i, max_count;
1102 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +00001103
1104 if (dump == NULL || desc == NULL)
1105 return ICH_RET_PARAM;
1106
1107 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1108 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1109 pch_bug_offset = 4;
1110 else
1111 return ICH_RET_ERR;
1112 }
1113
1114 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001115 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001116 return ICH_RET_OOB;
1117 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1118 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1119 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1120 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1121
1122 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001123 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001124 return ICH_RET_OOB;
1125 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1126 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1127 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1128
Nico Huber8a03c902021-06-17 21:23:29 +02001129 /* upper map */
1130 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1131
1132 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1133 * "Identifies the 1s based number of DWORDS contained in the VSCC
1134 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1135 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1136 * check ensures that the maximum offset actually accessed is available.
1137 */
1138 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
1139 return ICH_RET_OOB;
1140
1141 for (i = 0; i < desc->upper.VTL/2; i++) {
1142 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1143 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
1144 }
1145
Nico Huber67d71792017-06-17 03:10:15 +02001146 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huber3ad9aad2021-06-17 22:05:00 +02001147 *cs = guess_ich_chipset(&desc->content, &desc->component, &desc->upper);
Nico Huber67d71792017-06-17 03:10:15 +02001148 prettyprint_ich_chipset(*cs);
1149 }
Nico Huberfa622942017-03-24 17:25:37 +01001150
Stefan Taunerb3850962011-12-24 00:00:32 +00001151 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001152 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001153 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001154 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001155 for (i = 0; i < nr; i++)
1156 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001157
1158 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001159 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001160 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001161 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001162 for (i = 0; i < nm; i++)
1163 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001164
Stefan Taunerb3850962011-12-24 00:00:32 +00001165 /* MCH/PROC (aka. North) straps */
1166 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1167 return ICH_RET_OOB;
1168
1169 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001170 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001171 for (i = 0; i < max_count; i++)
1172 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001173
1174 /* ICH/PCH (aka. South) straps */
1175 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1176 return ICH_RET_OOB;
1177
1178 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001179 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001180 for (i = 0; i < max_count; i++)
1181 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001182
1183 return ICH_RET_OK;
1184}
1185
Nico Huberad186312016-05-02 15:15:29 +02001186#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001187
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001188/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001189\em idx in bytes or -1 if the correct size can not be determined. */
1190int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001191{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001192 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001193 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001194 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001195 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001196
1197 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001198 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001199
1200 uint8_t size_enc;
1201 uint8_t size_max;
1202
1203 switch (cs) {
1204 case CHIPSET_ICH8:
1205 case CHIPSET_ICH9:
1206 case CHIPSET_ICH10:
1207 case CHIPSET_5_SERIES_IBEX_PEAK:
1208 case CHIPSET_6_SERIES_COUGAR_POINT:
1209 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001210 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001211 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001212 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001213 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001214 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001215 }
1216 size_max = 5;
1217 break;
1218 case CHIPSET_8_SERIES_LYNX_POINT:
1219 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1220 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001221 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001222 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001223 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001224 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001225 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001226 case CHIPSET_500_SERIES_TIGER_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001227 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001228 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +01001229 case CHIPSET_ELKHART_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001230 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001231 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001232 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001233 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001234 }
1235 size_max = 7;
1236 break;
1237 case CHIPSET_ICH_UNKNOWN:
1238 default:
1239 msg_pwarn("Density encoding is unknown on this chipset.\n");
1240 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001241 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001242
1243 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001244 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001245 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1246 idx, size_enc, size_max);
1247 return -1;
1248 }
1249
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001250 return (1 << (19 + size_enc));
1251}
1252
Nico Huber8d494992017-06-19 12:18:33 +02001253/* Only used by ichspi.c */
1254#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001255static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001256{
1257 uint32_t control = 0;
1258 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1259 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001260 switch (cs) {
1261 case CHIPSET_100_SERIES_SUNRISE_POINT:
1262 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001263 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001264 case CHIPSET_500_SERIES_TIGER_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001265 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001266 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +01001267 case CHIPSET_ELKHART_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001268 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1269 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001270 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001271 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1272 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1273 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001274}
1275
Nico Huberd54e4f42017-03-23 23:45:47 +01001276int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001277{
Nico Huber519be662018-12-23 20:03:35 +01001278 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001279 struct ich_desc_region *r = &desc->region;
1280
1281 /* Test if bit-fields are working as expected.
1282 * FIXME: Replace this with dynamic bitfield fixup
1283 */
1284 for (i = 0; i < 4; i++)
1285 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001286 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1287 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1288 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1289 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001290 msg_pdbg("The combination of compiler and CPU architecture used"
1291 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001292 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1293 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1294 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1295 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1296 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1297 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1298 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1299 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001300 return ICH_RET_ERR;
1301 }
1302
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001303 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001304 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001305 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1306 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1307 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1308 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001309
1310 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001311 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1312 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1313 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001314
1315 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001316 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1317 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001318 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001319 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001320 return ICH_RET_ERR;
1321 }
Nico Huberfa622942017-03-24 17:25:37 +01001322 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001323 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001324
1325 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001326 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1327 if (nm < 0) {
1328 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1329 __func__, desc->content.NM + 1);
1330 return ICH_RET_ERR;
1331 }
1332 for (i = 0; i < nm; i++)
1333 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001334
1335 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1336 * reading the upper map is impossible on all chipsets, so don't bother.
1337 */
1338
1339 msg_pdbg2(" done.\n");
1340 return ICH_RET_OK;
1341}
Nico Huber8d494992017-06-19 12:18:33 +02001342#endif
Nico Huber305f4172013-06-14 11:55:26 +02001343
1344/**
1345 * @brief Read a layout from the dump of an Intel ICH descriptor.
1346 *
1347 * @param layout Pointer where to store the layout.
1348 * @param dump The descriptor dump to read from.
1349 * @param len The length of the descriptor dump.
1350 *
1351 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001352 * 1 if the descriptor couldn't be parsed,
1353 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001354 */
Nico Huber5bd990c2019-06-16 19:46:46 +02001355int layout_from_ich_descriptors(
Nico Huberc3b02dc2023-08-12 01:13:45 +02001356 struct flashprog_layout **const layout,
Nico Huber5bd990c2019-06-16 19:46:46 +02001357 const void *const dump, const size_t len)
Nico Huber305f4172013-06-14 11:55:26 +02001358{
Nico Huberfa622942017-03-24 17:25:37 +01001359 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001360 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1361 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001362 };
Nico Huber305f4172013-06-14 11:55:26 +02001363
1364 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001365 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1366 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001367 return 1;
1368
Nico Huberc3b02dc2023-08-12 01:13:45 +02001369 if (flashprog_layout_new(layout))
Nico Huber5bd990c2019-06-16 19:46:46 +02001370 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001371
Nico Huber92e0b622019-06-15 15:55:11 +02001372 ssize_t i;
Nico Huber519be662018-12-23 20:03:35 +01001373 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
Nico Huber92e0b622019-06-15 15:55:11 +02001374 for (i = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001375 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001376 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001377 if (limit <= base)
1378 continue;
Nico Huberc3b02dc2023-08-12 01:13:45 +02001379 if (flashprog_layout_add_region(*layout, base, limit, regions[i])) {
1380 flashprog_layout_release(*layout);
Nico Huber5bd990c2019-06-16 19:46:46 +02001381 *layout = NULL;
Nico Huber70461a92019-06-15 14:56:19 +02001382 return 2;
Nico Huber5bd990c2019-06-16 19:46:46 +02001383 }
Nico Huber305f4172013-06-14 11:55:26 +02001384 }
Nico Huber305f4172013-06-14 11:55:26 +02001385 return 0;
1386}
1387
Nico Huberad186312016-05-02 15:15:29 +02001388#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */