blob: 081481d4f9fbe7b9e1e4e1f9a904b7c2d0bd3523 [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
Stefan Tauner1e146392011-09-15 23:52:55 +000018#include "ich_descriptors.h"
Thomas Heijligencce1e5b2021-11-02 20:33:35 +010019#include "hwaccess.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
Nico Huber4d440a72017-08-15 11:26:48 +020034#include <sys/types.h>
Nico Huberad186312016-05-02 15:15:29 +020035#include <string.h>
Stefan Tauner1e146392011-09-15 23:52:55 +000036#include "flash.h" /* for msg_* */
37#include "programmer.h"
38
Nico Huberfa622942017-03-24 17:25:37 +010039ssize_t ich_number_of_regions(const enum ich_chipset cs, const struct ich_desc_content *const cont)
40{
41 switch (cs) {
Nico Huberd2d39932019-01-18 16:49:37 +010042 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +020043 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +010044 return 6;
David Hendricksa5216362017-08-08 20:02:22 -070045 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +020046 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +020047 case CHIPSET_500_SERIES_TIGER_POINT:
Werner Zehe57d4e42022-01-03 09:44:29 +010048 case CHIPSET_ELKHART_LAKE:
David Hendricksa5216362017-08-08 20:02:22 -070049 return 16;
Nico Huberfa622942017-03-24 17:25:37 +010050 case CHIPSET_100_SERIES_SUNRISE_POINT:
51 return 10;
52 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
53 case CHIPSET_9_SERIES_WILDCAT_POINT:
54 case CHIPSET_8_SERIES_LYNX_POINT_LP:
55 case CHIPSET_8_SERIES_LYNX_POINT:
56 case CHIPSET_8_SERIES_WELLSBURG:
57 if (cont->NR <= 6)
58 return cont->NR + 1;
59 else
60 return -1;
61 default:
62 if (cont->NR <= 4)
63 return cont->NR + 1;
64 else
65 return -1;
66 }
67}
68
69ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
70{
David Hendricksa5216362017-08-08 20:02:22 -070071 switch (cs) {
72 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberd2d39932019-01-18 16:49:37 +010073 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +020074 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +010075 case CHIPSET_ELKHART_LAKE:
David Hendricksa5216362017-08-08 20:02:22 -070076 if (cont->NM <= MAX_NUM_MASTERS)
77 return cont->NM;
Richard Hughesdb7482b2018-12-19 12:04:30 +000078 break;
David Hendricksa5216362017-08-08 20:02:22 -070079 default:
80 if (cont->NM < MAX_NUM_MASTERS)
81 return cont->NM + 1;
82 }
83
84 return -1;
Nico Huberfa622942017-03-24 17:25:37 +010085}
86
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000087void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000088{
89 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
90 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
91 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
92 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000093 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
94 if (print_vcl)
95 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
96 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000097}
98
99#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
100#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
101#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
102#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
103#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
104
Nico Huber67d71792017-06-17 03:10:15 +0200105void prettyprint_ich_chipset(enum ich_chipset cs)
106{
107 static const char *const chipset_names[] = {
108 "Unknown ICH", "ICH8", "ICH9", "ICH10",
109 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
110 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
111 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
Angel Pons4db0fdf2020-07-10 17:04:10 +0200112 "C620 series Lewisburg", "300/400 series Cannon/Comet Point",
Nico Huber29c23dd2022-12-21 15:25:09 +0000113 "500/600 series Tiger/Alder Point", "Apollo Lake", "Gemini Lake", "Elkhart Lake",
Nico Huber67d71792017-06-17 03:10:15 +0200114 };
115 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
116 cs = 0;
117 else
118 cs = cs - CHIPSET_ICH8 + 1;
119 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
120}
121
Stefan Tauner1e146392011-09-15 23:52:55 +0000122void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
123{
Nico Huberfa622942017-03-24 17:25:37 +0100124 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000125 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100126 prettyprint_ich_descriptor_region(cs, desc);
127 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200128#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000129 if (cs >= CHIPSET_ICH8) {
130 prettyprint_ich_descriptor_upper_map(&desc->upper);
131 prettyprint_ich_descriptor_straps(cs, desc);
132 }
Nico Huberad186312016-05-02 15:15:29 +0200133#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000134}
135
Nico Huberfa622942017-03-24 17:25:37 +0100136void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000137{
138 msg_pdbg2("=== Content Section ===\n");
139 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
140 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
141 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
142 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
143 msg_pdbg2("\n");
144
145 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100146 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
147 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
148 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
149 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
Nico Huberd2d39932019-01-18 16:49:37 +0100150 msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL);
151 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont));
Nico Huberfa622942017-03-24 17:25:37 +0100152 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
153 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
154 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
155 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000156 msg_pdbg2("\n");
157}
158
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000159static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
160{
161 if (idx > 1) {
162 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
163 return NULL;
164 }
165
166 if (desc->content.NC == 0 && idx > 0)
167 return "unused";
168
169 static const char * const size_str[] = {
170 "512 kB", /* 0000 */
171 "1 MB", /* 0001 */
172 "2 MB", /* 0010 */
173 "4 MB", /* 0011 */
174 "8 MB", /* 0100 */
175 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
176 "32 MB", /* 0110 */
177 "64 MB", /* 0111 */
178 };
179
180 switch (cs) {
181 case CHIPSET_ICH8:
182 case CHIPSET_ICH9:
183 case CHIPSET_ICH10:
184 case CHIPSET_5_SERIES_IBEX_PEAK:
185 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000186 case CHIPSET_7_SERIES_PANTHER_POINT:
187 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000188 uint8_t size_enc;
189 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000190 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000191 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000192 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000193 }
194 if (size_enc > 5)
195 return "reserved";
196 return size_str[size_enc];
197 }
198 case CHIPSET_8_SERIES_LYNX_POINT:
199 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000200 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100201 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100202 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
David Hendricksa5216362017-08-08 20:02:22 -0700203 case CHIPSET_100_SERIES_SUNRISE_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100204 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200205 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200206 case CHIPSET_500_SERIES_TIGER_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200207 case CHIPSET_APOLLO_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +0100208 case CHIPSET_GEMINI_LAKE:
209 case CHIPSET_ELKHART_LAKE: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000210 uint8_t size_enc;
211 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000212 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000213 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000214 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000215 }
216 if (size_enc > 7)
217 return "reserved";
218 return size_str[size_enc];
219 }
220 case CHIPSET_ICH_UNKNOWN:
221 default:
222 return "unknown";
223 }
224}
225
226static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000227{
Werner Zehe57d4e42022-01-03 09:44:29 +0100228 static const char *const freq_str[5][8] = { {
Nico Huber129e9382019-06-06 15:43:27 +0200229 "20 MHz",
230 "33 MHz",
231 "reserved",
232 "reserved",
233 "50 MHz", /* New since Ibex Peak */
234 "reserved",
235 "reserved",
236 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100237 }, {
Nico Huber129e9382019-06-06 15:43:27 +0200238 "reserved",
239 "reserved",
240 "48 MHz",
241 "reserved",
242 "30 MHz",
243 "reserved",
244 "17 MHz",
245 "reserved"
Nico Huberd2d39932019-01-18 16:49:37 +0100246 }, {
247 "reserved",
248 "50 MHz",
249 "40 MHz",
250 "reserved",
251 "25 MHz",
252 "reserved",
253 "14 MHz / 17 MHz",
254 "reserved"
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200255 }, {
256 "100 MHz",
257 "50 MHz",
258 "reserved",
259 "33 MHz",
260 "25 MHz",
261 "reserved",
262 "14 MHz",
263 "reserved"
Werner Zehe57d4e42022-01-03 09:44:29 +0100264 }, {
265 "reserved",
266 "50 MHz",
267 "reserved",
268 "reserved",
269 "33 MHz",
270 "20 MHz",
271 "reserved",
272 "reserved",
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200273 }};
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000274
275 switch (cs) {
276 case CHIPSET_ICH8:
277 case CHIPSET_ICH9:
278 case CHIPSET_ICH10:
279 if (value > 1)
280 return "reserved";
Richard Hughesdb7482b2018-12-19 12:04:30 +0000281 /* Fall through. */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000282 case CHIPSET_5_SERIES_IBEX_PEAK:
283 case CHIPSET_6_SERIES_COUGAR_POINT:
284 case CHIPSET_7_SERIES_PANTHER_POINT:
285 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000286 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000287 case CHIPSET_8_SERIES_LYNX_POINT_LP:
288 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000289 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100290 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100291 return freq_str[0][value];
292 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700293 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200294 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100295 return freq_str[1][value];
Nico Huberd2d39932019-01-18 16:49:37 +0100296 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200297 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100298 return freq_str[2][value];
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200299 case CHIPSET_500_SERIES_TIGER_POINT:
300 return freq_str[3][value];
Werner Zehe57d4e42022-01-03 09:44:29 +0100301 case CHIPSET_ELKHART_LAKE:
302 return freq_str[4][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000303 case CHIPSET_ICH_UNKNOWN:
304 default:
305 return "unknown";
306 }
307}
308
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200309static void pprint_read_freq(enum ich_chipset cs, uint8_t value)
310{
311 static const char *const freq_str[1][8] = { {
312 "20 MHz",
313 "24 MHz",
314 "30 MHz",
315 "48 MHz",
316 "60 MHz",
317 "reserved",
318 "reserved",
319 "reserved"
320 }};
321
322 switch (cs) {
323 case CHIPSET_300_SERIES_CANNON_POINT:
324 msg_pdbg2("eSPI/EC Bus Clock Frequency: %s\n", freq_str[0][value]);
325 return;
326 case CHIPSET_500_SERIES_TIGER_POINT:
327 msg_pdbg2("Read Clock Frequency: %s\n", "reserved");
328 return;
329 default:
330 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, value));
331 return;
332 }
333}
334
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000335void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
336{
Nico Huberd2d39932019-01-18 16:49:37 +0100337 bool has_flill1;
338
339 switch (cs) {
340 case CHIPSET_100_SERIES_SUNRISE_POINT:
341 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200342 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200343 case CHIPSET_500_SERIES_TIGER_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100344 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200345 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +0100346 case CHIPSET_ELKHART_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100347 has_flill1 = true;
348 break;
349 default:
350 has_flill1 = false;
351 break;
352 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000353
354 msg_pdbg2("=== Component Section ===\n");
355 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
356 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberd2d39932019-01-18 16:49:37 +0100357 if (has_flill1)
Nico Huberfa622942017-03-24 17:25:37 +0100358 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000359 msg_pdbg2("\n");
360
361 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000362 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000363 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000364 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000365 else
366 msg_pdbg2("Component 2 is not used.\n");
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200367
368 pprint_read_freq(cs, desc->component.modes.freq_read);
369
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000370 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
371 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
372 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
373 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000374 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000375 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000376 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
377 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Werner Zehd3e8fd92022-01-25 07:02:49 +0100378 desc->component.modes.dual_output ? "en" : "dis");
David Hendricksa5216362017-08-08 20:02:22 -0700379
380 int has_forbidden_opcode = 0;
381 if (desc->component.FLILL != 0) {
382 has_forbidden_opcode = 1;
Stefan Tauner1e146392011-09-15 23:52:55 +0000383 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
384 desc->component.invalid_instr0);
385 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
386 desc->component.invalid_instr1);
387 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
388 desc->component.invalid_instr2);
389 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
390 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700391 }
Nico Huberd2d39932019-01-18 16:49:37 +0100392 if (has_flill1) {
David Hendricksa5216362017-08-08 20:02:22 -0700393 if (desc->component.FLILL1 != 0) {
394 has_forbidden_opcode = 1;
Nico Huberfa622942017-03-24 17:25:37 +0100395 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
396 desc->component.invalid_instr4);
397 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
398 desc->component.invalid_instr5);
399 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
400 desc->component.invalid_instr6);
401 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
402 desc->component.invalid_instr7);
403 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000404 }
David Hendricksa5216362017-08-08 20:02:22 -0700405 if (!has_forbidden_opcode)
406 msg_pdbg2("No forbidden opcodes.\n");
407
Stefan Tauner1e146392011-09-15 23:52:55 +0000408 msg_pdbg2("\n");
409}
410
411static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
412{
Nico Huberfa622942017-03-24 17:25:37 +0100413 static const char *const region_names[] = {
Nico Huberd2d39932019-01-18 16:49:37 +0100414 "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown",
David Hendricksa5216362017-08-08 20:02:22 -0700415 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000416 };
Nico Huberfa622942017-03-24 17:25:37 +0100417 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000418 msg_pdbg2("%s: region index too high.\n", __func__);
419 return;
420 }
421 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
422 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100423 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000424 if (base > limit)
425 msg_pdbg2("is unused.\n");
426 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200427 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000428}
429
Nico Huberfa622942017-03-24 17:25:37 +0100430void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000431{
Nico Huber519be662018-12-23 20:03:35 +0100432 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100433 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000434 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100435 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000436 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100437 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000438 return;
439 }
Nico Huberfa622942017-03-24 17:25:37 +0100440 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100441 msg_pdbg2("FLREG%zd 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000442 msg_pdbg2("\n");
443
444 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100445 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100446 pprint_freg(&desc->region, (uint32_t)i);
Stefan Tauner1e146392011-09-15 23:52:55 +0000447 msg_pdbg2("\n");
448}
449
Nico Huberfa622942017-03-24 17:25:37 +0100450void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000451{
Nico Huber519be662018-12-23 20:03:35 +0100452 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100453 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000454 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100455 if (nm < 0) {
456 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
457 desc->content.NM + 1);
458 return;
459 }
460 for (i = 0; i < nm; i++)
Nico Huber519be662018-12-23 20:03:35 +0100461 msg_pdbg2("FLMSTR%zd 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000462 msg_pdbg2("\n");
463
464 msg_pdbg2("--- Details ---\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200465 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT ||
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200466 cs == CHIPSET_300_SERIES_CANNON_POINT ||
467 cs == CHIPSET_500_SERIES_TIGER_POINT) {
Nico Huberfa622942017-03-24 17:25:37 +0100468 const char *const master_names[] = {
469 "BIOS", "ME", "GbE", "unknown", "EC",
470 };
Nico Huber519be662018-12-23 20:03:35 +0100471 if (nm >= (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberfa622942017-03-24 17:25:37 +0100472 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
473 desc->content.NM + 1);
474 return;
475 }
476
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200477 size_t num_regions;
478 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9");
479 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
480 num_regions = 10;
481 msg_pdbg2("\n");
482 } else {
483 num_regions = 16;
484 msg_pdbg2(" RegA RegB RegC RegD RegE RegF\n");
485 }
Nico Huberfa622942017-03-24 17:25:37 +0100486 for (i = 0; i < nm; i++) {
487 size_t j;
488 msg_pdbg2("%-4s", master_names[i]);
Nico Huber961f4a12019-10-04 17:34:22 +0200489 for (j = 0; j < (size_t)min(num_regions, 12); j++)
Nico Huberfa622942017-03-24 17:25:37 +0100490 msg_pdbg2(" %c%c ",
491 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
492 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200493 for (; j < num_regions; j++)
494 msg_pdbg2(" %c%c ",
495 desc->master.mstr[i].ext_read & (1 << (j - 12)) ? 'r' : ' ',
496 desc->master.mstr[i].ext_write & (1 << (j - 12)) ? 'w' : ' ');
Nico Huberfa622942017-03-24 17:25:37 +0100497 msg_pdbg2("\n");
498 }
David Hendricksa5216362017-08-08 20:02:22 -0700499 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
500 const char *const master_names[] = {
501 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
502 };
503 /* NM starts at 1 instead of 0 for LBG */
Nico Huber519be662018-12-23 20:03:35 +0100504 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
David Hendricksa5216362017-08-08 20:02:22 -0700505 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
506 desc->content.NM);
507 return;
508 }
509
510 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
511 " ", /* width of master name (4 chars minimum) */
512 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
513 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
514 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
515 "Reg15");
516 for (i = 0; i < nm; i++) {
517 size_t j;
518 msg_pdbg2("%-4s", master_names[i]);
519 for (j = 0; j < 16; j++)
520 msg_pdbg2(" %c%c ",
521 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
522 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
523 msg_pdbg2("\n");
524 }
Werner Zehe57d4e42022-01-03 09:44:29 +0100525 } else if (cs == CHIPSET_APOLLO_LAKE || cs == CHIPSET_GEMINI_LAKE || cs == CHIPSET_ELKHART_LAKE) {
Nico Huberd2d39932019-01-18 16:49:37 +0100526 const char *const master_names[] = { "BIOS", "TXE", };
Nico Huber519be662018-12-23 20:03:35 +0100527 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberd2d39932019-01-18 16:49:37 +0100528 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
529 return;
530 }
531
532 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
533 for (i = 0; i < nm; i++) {
Nico Huber519be662018-12-23 20:03:35 +0100534 ssize_t j;
Nico Huberd2d39932019-01-18 16:49:37 +0100535 msg_pdbg2("%-4s", master_names[i]);
536 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
537 msg_pdbg2(" %c%c ",
538 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
539 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
540 msg_pdbg2("\n");
541 }
Nico Huberfa622942017-03-24 17:25:37 +0100542 } else {
543 const struct ich_desc_master *const mstr = &desc->master;
544 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
545 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
546 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
547 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
548 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
549 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
550 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
551 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
552 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
553 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
554 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
555 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
556 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
557 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
558 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
559 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
560 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
561 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
562 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
563 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000564 msg_pdbg2("\n");
565}
566
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600567static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000568{
569 static const char * const str_GPIO12[4] = {
570 "GPIO12",
571 "LAN PHY Power Control Function (Native Output)",
572 "GLAN_DOCK# (Native Input)",
573 "invalid configuration",
574 };
575
576 msg_pdbg2("--- MCH details ---\n");
577 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
578 msg_pdbg2("\n");
579
580 msg_pdbg2("--- ICH details ---\n");
581 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
582 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
583 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
584 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
585 msg_pdbg2("SPI CS1 is used for %s.\n",
586 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
587 "LAN PHY Power Control Function" :
588 "SPI Chip Select");
589 msg_pdbg2("GPIO12 is used as %s.\n",
590 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
591 msg_pdbg2("PCIe Port 6 is used for %s.\n",
592 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
593 msg_pdbg2("%sn BMC Mode: "
594 "Intel AMT SMBus Controller 1 is connected to %s.\n",
595 desc->south.ich8.BMCMODE ? "I" : "Not i",
596 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
597 msg_pdbg2("TCO is in %s Mode.\n",
598 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
599 msg_pdbg2("ME A is %sabled.\n",
600 desc->south.ich8.ME_DISABLE ? "dis" : "en");
601 msg_pdbg2("\n");
602}
603
604static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
605{
606 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
607
608 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000609 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000610 case 0:
611 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
612 break;
613 case 1:
614 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
615 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
616 break;
617 case 2:
618 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
619 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
620 break;
621 case 3:
622 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
623 1+off, 2+off, 4+off);
624 break;
625 }
626 msg_pdbg2("\n");
627}
628
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600629static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000630{
631 /* PCHSTRP4 */
632 msg_pdbg2("Intel PHY is %s.\n",
633 (s->ibex.PHYCON == 2) ? "connected" :
634 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
635 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
636 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
637 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
638 s->ibex.GBEMAC_SMBUS_ADDR);
639 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
640 s->ibex.GBEPHY_SMBUS_ADDR);
641
642 /* PCHSTRP5 */
643 /* PCHSTRP6 */
644 /* PCHSTRP7 */
645 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
646 s->ibex.MESMA2UDID_VENDOR);
647 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
648 s->ibex.MESMA2UDID_VENDOR);
649
650 /* PCHSTRP8 */
651}
652
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600653static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000654{
655 /* PCHSTRP11 */
656 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
657 s->ibex.SML1GPAEN ? "en" : "dis");
658 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
659 s->ibex.SML1GPA);
660 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
661 s->ibex.SML1I2CAEN ? "en" : "dis");
662 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
663 s->ibex.SML1I2CA);
664
665 /* PCHSTRP12 */
666 /* PCHSTRP13 */
667}
668
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600669static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000670{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000671 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000672 100,
673 50,
674 5,
675 1
676 };
677
678 msg_pdbg2("--- PCH ---\n");
679
680 /* PCHSTRP0 */
681 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
682 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
683 s->ibex.SMB_EN ? "en" : "dis");
684 msg_pdbg2("SMLink0 segment is %sabled.\n",
685 s->ibex.SML0_EN ? "en" : "dis");
686 msg_pdbg2("SMLink1 segment is %sabled.\n",
687 s->ibex.SML1_EN ? "en" : "dis");
688 msg_pdbg2("SMLink1 Frequency: %s\n",
689 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
690 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
691 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
692 msg_pdbg2("SMLink0 Frequency: %s\n",
693 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
694 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
695 "LAN_PHY_PWR_CTRL" : "general purpose output");
696 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
697 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
698 s->ibex.DMI_REQID_DIS ? "en" : "dis");
699 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
700 1 << (6 + s->ibex.BBBS));
701
702 /* PCHSTRP1 */
703 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
704
705 /* PCHSTRP2 */
706 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
707 s->ibex.MESMASDEN ? "en" : "dis");
708 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
709 s->ibex.MESMASDA);
710 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
711 s->ibex.MESMI2CEN ? "en" : "dis");
712 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
713 s->ibex.MESMI2CA);
714
715 /* PCHSTRP3 */
716 prettyprint_ich_descriptor_pchstraps45678_56(s);
717 /* PCHSTRP9 */
718 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
719 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
720 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
721 s->ibex.PCIELR1 ? "" : "not ");
722 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
723 s->ibex.PCIELR2 ? "" : "not ");
724 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
725 s->ibex.DMILR ? "" : "not ");
726 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
727 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
728 s->ibex.PHY_PCIE_EN ? "en" : "dis");
729
730 /* PCHSTRP10 */
731 msg_pdbg2("Management Engine will boot from %sflash.\n",
732 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
733 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
734 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
735 s->ibex.VE_EN ? "en" : "dis");
736 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
737 s->ibex.MMDDE ? "en" : "dis");
738 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
739 s->ibex.MMADDR);
740 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
741 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
742 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
743 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
744 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
745
746 prettyprint_ich_descriptor_pchstraps111213_56(s);
747
748 /* PCHSTRP14 */
749 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
750 s->ibex.VE_EN2 ? "en" : "dis");
751 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
752 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
753 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
754 s->ibex.BW_SSD ? "en" : "dis");
755 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
756 s->ibex.NVMHCI_EN ? "en" : "dis");
757
758 /* PCHSTRP15 */
759 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
760 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
761 s->ibex.IWL_EN ? "en" : "dis");
762 msg_pdbg2("t209 min Timing: %d ms\n",
763 dec_t209min[s->ibex.t209min]);
764 msg_pdbg2("\n");
765}
766
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600767static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000768{
769 msg_pdbg2("--- PCH ---\n");
770
771 /* PCHSTRP0 */
772 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
773 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
774 s->ibex.SMB_EN ? "en" : "dis");
775 msg_pdbg2("SMLink0 segment is %sabled.\n",
776 s->ibex.SML0_EN ? "en" : "dis");
777 msg_pdbg2("SMLink1 segment is %sabled.\n",
778 s->ibex.SML1_EN ? "en" : "dis");
779 msg_pdbg2("SMLink1 Frequency: %s\n",
780 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
781 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
782 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
783 msg_pdbg2("SMLink0 Frequency: %s\n",
784 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
785 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
786 "LAN_PHY_PWR_CTRL" : "general purpose output");
787 msg_pdbg2("LinkSec is %sabled.\n",
788 s->cougar.LINKSEC_DIS ? "en" : "dis");
789 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
790 s->ibex.DMI_REQID_DIS ? "en" : "dis");
791 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
792 1 << (6 + s->ibex.BBBS));
793
794 /* PCHSTRP1 */
795 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
796 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
797
798 /* PCHSTRP2 */
799 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
800 s->ibex.MESMASDEN ? "en" : "dis");
801 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
802 s->ibex.MESMASDA);
803 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
804 s->cougar.MESMMCTPAEN ? "en" : "dis");
805 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
806 s->cougar.MESMMCTPA);
807 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
808 s->ibex.MESMI2CEN ? "en" : "dis");
809 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
810 s->ibex.MESMI2CA);
811
812 /* PCHSTRP3 */
813 prettyprint_ich_descriptor_pchstraps45678_56(s);
814 /* PCHSTRP9 */
815 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
816 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
817 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
818 s->ibex.PCIELR1 ? "" : "not ");
819 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
820 s->ibex.PCIELR2 ? "" : "not ");
821 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
822 s->ibex.DMILR ? "" : "not ");
823 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
824 s->cougar.MDSMBE_EN ? "en" : "dis");
825 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
826 s->cougar.MDSMBE_ADD);
827 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
828 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
829 s->ibex.PHY_PCIE_EN ? "en" : "dis");
830 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
831 s->cougar.SUB_DECODE_EN ? "en" : "dis");
832 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
833 "PCHHOT#" : "SML1ALERT#");
834
835 /* PCHSTRP10 */
836 msg_pdbg2("Management Engine will boot from %sflash.\n",
837 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
838
839 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
840 s->cougar.MDSMBE_EN ? "en" : "dis");
841 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
842 s->cougar.MDSMBE_ADD);
843
844 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
845 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000846 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
847 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000848 msg_pdbg2("ICC Profile is selected by %s.\n",
849 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
850 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
851 s->cougar.Deep_SX_EN ? "not " : "");
852 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
853 s->cougar.ME_DBG_LAN ? "en" : "dis");
854
855 prettyprint_ich_descriptor_pchstraps111213_56(s);
856
857 /* PCHSTRP14 */
858 /* PCHSTRP15 */
859 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
860 msg_pdbg2("Integrated wired LAN is %sabled.\n",
861 s->cougar.IWL_EN ? "en" : "dis");
862 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
863 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000864 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000865 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
866 "general purpose output" : "SLP_LAN#");
867
868 /* PCHSTRP16 */
869 /* PCHSTRP17 */
870 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
871 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
872 msg_pdbg2("\n");
873}
874
875void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
876{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000877 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000878 msg_pdbg2("=== Softstraps ===\n");
879
Nico Huber519be662018-12-23 20:03:35 +0100880 max_count = MIN(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
Nico Huberd7c75522017-03-29 16:31:49 +0200881 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000882 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200883 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000884 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200885 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000886
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000887 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
888 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000889 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
890 msg_pdbg2("\n");
891
Nico Huber519be662018-12-23 20:03:35 +0100892 max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
Nico Huberd7c75522017-03-29 16:31:49 +0200893 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000894 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
895 desc->content.ISL, max_count);
896 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200897 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000898
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000899 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
900 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000901 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
902 msg_pdbg2("\n");
903
904 switch (cs) {
905 case CHIPSET_ICH8:
906 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
907 msg_pdbg2("Detailed North/MCH/PROC information is "
908 "probably not reliable, printing anyway.\n");
909 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
910 msg_pdbg2("Detailed South/ICH/PCH information is "
911 "probably not reliable, printing anyway.\n");
912 prettyprint_ich_descriptor_straps_ich8(desc);
913 break;
914 case CHIPSET_5_SERIES_IBEX_PEAK:
915 /* PCH straps only. PROCSTRPs are unknown. */
916 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
917 msg_pdbg2("Detailed South/ICH/PCH information is "
918 "probably not reliable, printing anyway.\n");
919 prettyprint_ich_descriptor_straps_ibex(&desc->south);
920 break;
921 case CHIPSET_6_SERIES_COUGAR_POINT:
922 /* PCH straps only. PROCSTRP0 is "reserved". */
923 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
924 msg_pdbg2("Detailed South/ICH/PCH information is "
925 "probably not reliable, printing anyway.\n");
926 prettyprint_ich_descriptor_straps_cougar(&desc->south);
927 break;
928 case CHIPSET_ICH_UNKNOWN:
929 break;
930 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000931 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000932 break;
933 }
934}
935
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600936static void prettyprint_rdid(uint32_t reg_val)
Stefan Taunerb3850962011-12-24 00:00:32 +0000937{
938 uint8_t mid = reg_val & 0xFF;
939 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
940 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
941}
942
943void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
944{
945 int i;
946 msg_pdbg2("=== Upper Map Section ===\n");
947 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
948 msg_pdbg2("\n");
949
950 msg_pdbg2("--- Details ---\n");
951 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
952 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
953 msg_pdbg2("\n");
954
955 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000956 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000957 uint32_t jid = umap->vscc_table[i].JID;
958 uint32_t vscc = umap->vscc_table[i].VSCC;
959 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
960 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
961 msg_pdbg2(" "); /* indention */
962 prettyprint_rdid(jid);
963 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000964 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000965 }
966 msg_pdbg2("\n");
967}
968
David Hendricks66565a72021-09-20 21:56:40 -0700969static inline void warn_peculiar_desc(const char *const name)
Nico Huber964007a2021-06-17 21:12:47 +0200970{
Nico Huber964007a2021-06-17 21:12:47 +0200971 msg_pwarn("Peculiar flash descriptor, assuming %s compatibility.\n", name);
972}
973
Nico Huber1dc3d422017-06-17 00:09:31 +0200974/*
975 * Guesses a minimum chipset version based on the maximum number of
Nico Huber3ad9aad2021-06-17 22:05:00 +0200976 * soft straps per generation and presence of the MIP base (MDTBA).
Nico Huber1dc3d422017-06-17 00:09:31 +0200977 */
Nico Huber3ad9aad2021-06-17 22:05:00 +0200978static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content,
979 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +0200980{
981 if (content->ICCRIBA == 0x00) {
982 if (content->MSL == 0 && content->ISL <= 2)
983 return CHIPSET_ICH8;
Nico Huber83b01c82021-06-17 21:20:09 +0200984 if (content->ISL <= 2)
Nico Huber1dc3d422017-06-17 00:09:31 +0200985 return CHIPSET_ICH9;
Nico Huber83b01c82021-06-17 21:20:09 +0200986 if (content->ISL <= 10)
Nico Huber1dc3d422017-06-17 00:09:31 +0200987 return CHIPSET_ICH10;
David Hendricks66565a72021-09-20 21:56:40 -0700988 if (content->ISL <= 16)
989 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber83b01c82021-06-17 21:20:09 +0200990 if (content->FLMAP2 == 0) {
Nico Huber81965f32021-06-17 23:25:35 +0200991 if (content->ISL == 19)
992 return CHIPSET_APOLLO_LAKE;
David Hendricks66565a72021-09-20 21:56:40 -0700993 if (content->ISL == 23)
994 return CHIPSET_GEMINI_LAKE;
995 warn_peculiar_desc("Gemini Lake");
Nico Huber81965f32021-06-17 23:25:35 +0200996 return CHIPSET_GEMINI_LAKE;
Nico Huberd2d39932019-01-18 16:49:37 +0100997 }
Jonathan Zhang3bf7cfb2021-08-30 23:25:06 -0700998 if (content->ISL <= 80)
999 return CHIPSET_C620_SERIES_LEWISBURG;
David Hendricks66565a72021-09-20 21:56:40 -07001000 warn_peculiar_desc("Ibex Peak");
Nico Huber1dc3d422017-06-17 00:09:31 +02001001 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber3ad9aad2021-06-17 22:05:00 +02001002 } else if (upper->MDTBA == 0x00) {
1003 if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
1004 if (content->MSL == 0 && content->ISL <= 17)
1005 return CHIPSET_BAYTRAIL;
1006 if (content->MSL <= 1 && content->ISL <= 18)
1007 return CHIPSET_6_SERIES_COUGAR_POINT;
David Hendricks66565a72021-09-20 21:56:40 -07001008 if (content->MSL <= 1 && content->ISL <= 21)
1009 return CHIPSET_8_SERIES_LYNX_POINT;
1010 warn_peculiar_desc("Lynx Point");
Nico Huber81965f32021-06-17 23:25:35 +02001011 return CHIPSET_8_SERIES_LYNX_POINT;
Nico Huber3ad9aad2021-06-17 22:05:00 +02001012 }
1013 if (content->NM == 6) {
David Hendricks66565a72021-09-20 21:56:40 -07001014 if (content->ICCRIBA <= 0x34)
1015 return CHIPSET_C620_SERIES_LEWISBURG;
1016 warn_peculiar_desc("C620 series");
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001017 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber3ad9aad2021-06-17 22:05:00 +02001018 }
David Hendricks66565a72021-09-20 21:56:40 -07001019 if (content->ICCRIBA == 0x31)
1020 return CHIPSET_100_SERIES_SUNRISE_POINT;
1021 warn_peculiar_desc("100 series");
Nico Huber83b01c82021-06-17 21:20:09 +02001022 return CHIPSET_100_SERIES_SUNRISE_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +02001023 } else {
David Hendricks66565a72021-09-20 21:56:40 -07001024 if (content->ICCRIBA == 0x34)
1025 return CHIPSET_300_SERIES_CANNON_POINT;
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001026 if (content->CSSL == 0x11)
1027 return CHIPSET_500_SERIES_TIGER_POINT;
Nico Huber29c23dd2022-12-21 15:25:09 +00001028 if (content->CSSL == 0x14) /* backwards compatible Alder Point */
1029 return CHIPSET_500_SERIES_TIGER_POINT;
Werner Zehe57d4e42022-01-03 09:44:29 +01001030 if (content->CSSL == 0x03)
1031 return CHIPSET_ELKHART_LAKE;
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001032 msg_pwarn("Unknown flash descriptor, assuming 500 series compatibility.\n");
1033 return CHIPSET_500_SERIES_TIGER_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +02001034 }
1035}
1036
1037/*
1038 * As an additional measure, we check the read frequency like `ifdtool`.
1039 * The frequency value 6 (17MHz) was reserved before Skylake and is the
1040 * only valid value since. Skylake is currently the most important dis-
1041 * tinction because of the dropped number of regions field (NR).
1042 */
Nico Huberfa622942017-03-24 17:25:37 +01001043static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
Nico Huber3ad9aad2021-06-17 22:05:00 +02001044 const struct ich_desc_component *const component,
1045 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +02001046{
Nico Huber3ad9aad2021-06-17 22:05:00 +02001047 const enum ich_chipset guess = guess_ich_chipset_from_content(content, upper);
Nico Huber1dc3d422017-06-17 00:09:31 +02001048
Nico Huberd2d39932019-01-18 16:49:37 +01001049 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001050 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001051 case CHIPSET_500_SERIES_TIGER_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001052 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +01001053 case CHIPSET_ELKHART_LAKE:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001054 /* `freq_read` was repurposed, so can't check on it any more. */
Nico Huber72a9dc02021-06-17 22:47:00 +02001055 break;
Nico Huberd2d39932019-01-18 16:49:37 +01001056 case CHIPSET_100_SERIES_SUNRISE_POINT:
1057 case CHIPSET_C620_SERIES_LEWISBURG:
1058 case CHIPSET_APOLLO_LAKE:
1059 if (component->modes.freq_read != 6) {
Nico Huber964007a2021-06-17 21:12:47 +02001060 msg_pwarn("\nThe flash descriptor looks like a Skylake/Sunrise Point descriptor.\n"
Nico Huberd2d39932019-01-18 16:49:37 +01001061 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
1062 "Please report this message, the output of `ich_descriptors_tool` for\n"
1063 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
Nico Huberd2d39932019-01-18 16:49:37 +01001064 }
Nico Huber72a9dc02021-06-17 22:47:00 +02001065 break;
Nico Huberd2d39932019-01-18 16:49:37 +01001066 default:
1067 if (component->modes.freq_read == 6) {
Nico Huber964007a2021-06-17 21:12:47 +02001068 msg_pwarn("\nThe flash descriptor has the read frequency set to 17MHz. However,\n"
Nico Huber1dc3d422017-06-17 00:09:31 +02001069 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
1070 "Please report this message, the output of `ich_descriptors_tool` for\n"
1071 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -07001072 }
Nico Huber1dc3d422017-06-17 00:09:31 +02001073 }
Nico Huber72a9dc02021-06-17 22:47:00 +02001074 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +02001075}
1076
Stefan Taunerb3850962011-12-24 00:00:32 +00001077/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +01001078int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
1079 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +00001080{
Nico Huber519be662018-12-23 20:03:35 +01001081 ssize_t i, max_count;
1082 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +00001083
1084 if (dump == NULL || desc == NULL)
1085 return ICH_RET_PARAM;
1086
1087 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1088 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1089 pch_bug_offset = 4;
1090 else
1091 return ICH_RET_ERR;
1092 }
1093
1094 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001095 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001096 return ICH_RET_OOB;
1097 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1098 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1099 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1100 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1101
1102 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001103 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001104 return ICH_RET_OOB;
1105 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1106 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1107 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1108
Nico Huber8a03c902021-06-17 21:23:29 +02001109 /* upper map */
1110 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1111
1112 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1113 * "Identifies the 1s based number of DWORDS contained in the VSCC
1114 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1115 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1116 * check ensures that the maximum offset actually accessed is available.
1117 */
1118 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
1119 return ICH_RET_OOB;
1120
1121 for (i = 0; i < desc->upper.VTL/2; i++) {
1122 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1123 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
1124 }
1125
Nico Huber67d71792017-06-17 03:10:15 +02001126 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huber3ad9aad2021-06-17 22:05:00 +02001127 *cs = guess_ich_chipset(&desc->content, &desc->component, &desc->upper);
Nico Huber67d71792017-06-17 03:10:15 +02001128 prettyprint_ich_chipset(*cs);
1129 }
Nico Huberfa622942017-03-24 17:25:37 +01001130
Stefan Taunerb3850962011-12-24 00:00:32 +00001131 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001132 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001133 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001134 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001135 for (i = 0; i < nr; i++)
1136 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001137
1138 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001139 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001140 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001141 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001142 for (i = 0; i < nm; i++)
1143 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001144
Stefan Taunerb3850962011-12-24 00:00:32 +00001145 /* MCH/PROC (aka. North) straps */
1146 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1147 return ICH_RET_OOB;
1148
1149 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001150 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001151 for (i = 0; i < max_count; i++)
1152 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001153
1154 /* ICH/PCH (aka. South) straps */
1155 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1156 return ICH_RET_OOB;
1157
1158 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001159 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001160 for (i = 0; i < max_count; i++)
1161 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001162
1163 return ICH_RET_OK;
1164}
1165
Nico Huberad186312016-05-02 15:15:29 +02001166#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001167
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001168/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001169\em idx in bytes or -1 if the correct size can not be determined. */
1170int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001171{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001172 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001173 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001174 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001175 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001176
1177 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001178 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001179
1180 uint8_t size_enc;
1181 uint8_t size_max;
1182
1183 switch (cs) {
1184 case CHIPSET_ICH8:
1185 case CHIPSET_ICH9:
1186 case CHIPSET_ICH10:
1187 case CHIPSET_5_SERIES_IBEX_PEAK:
1188 case CHIPSET_6_SERIES_COUGAR_POINT:
1189 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001190 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001191 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001192 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001193 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001194 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001195 }
1196 size_max = 5;
1197 break;
1198 case CHIPSET_8_SERIES_LYNX_POINT:
1199 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1200 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001201 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001202 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001203 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001204 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001205 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001206 case CHIPSET_500_SERIES_TIGER_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001207 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001208 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +01001209 case CHIPSET_ELKHART_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001210 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001211 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001212 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001213 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001214 }
1215 size_max = 7;
1216 break;
1217 case CHIPSET_ICH_UNKNOWN:
1218 default:
1219 msg_pwarn("Density encoding is unknown on this chipset.\n");
1220 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001221 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001222
1223 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001224 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001225 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1226 idx, size_enc, size_max);
1227 return -1;
1228 }
1229
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001230 return (1 << (19 + size_enc));
1231}
1232
Nico Huber8d494992017-06-19 12:18:33 +02001233/* Only used by ichspi.c */
1234#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001235static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001236{
1237 uint32_t control = 0;
1238 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1239 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001240 switch (cs) {
1241 case CHIPSET_100_SERIES_SUNRISE_POINT:
1242 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001243 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001244 case CHIPSET_500_SERIES_TIGER_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001245 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001246 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +01001247 case CHIPSET_ELKHART_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001248 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1249 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001250 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001251 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1252 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1253 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001254}
1255
Nico Huberd54e4f42017-03-23 23:45:47 +01001256int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001257{
Nico Huber519be662018-12-23 20:03:35 +01001258 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001259 struct ich_desc_region *r = &desc->region;
1260
1261 /* Test if bit-fields are working as expected.
1262 * FIXME: Replace this with dynamic bitfield fixup
1263 */
1264 for (i = 0; i < 4; i++)
1265 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001266 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1267 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1268 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1269 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001270 msg_pdbg("The combination of compiler and CPU architecture used"
1271 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001272 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1273 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1274 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1275 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1276 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1277 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1278 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1279 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001280 return ICH_RET_ERR;
1281 }
1282
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001283 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001284 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001285 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1286 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1287 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1288 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001289
1290 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001291 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1292 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1293 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001294
1295 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001296 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1297 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001298 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001299 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001300 return ICH_RET_ERR;
1301 }
Nico Huberfa622942017-03-24 17:25:37 +01001302 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001303 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001304
1305 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001306 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1307 if (nm < 0) {
1308 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1309 __func__, desc->content.NM + 1);
1310 return ICH_RET_ERR;
1311 }
1312 for (i = 0; i < nm; i++)
1313 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001314
1315 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1316 * reading the upper map is impossible on all chipsets, so don't bother.
1317 */
1318
1319 msg_pdbg2(" done.\n");
1320 return ICH_RET_OK;
1321}
Nico Huber8d494992017-06-19 12:18:33 +02001322#endif
Nico Huber305f4172013-06-14 11:55:26 +02001323
1324/**
1325 * @brief Read a layout from the dump of an Intel ICH descriptor.
1326 *
1327 * @param layout Pointer where to store the layout.
1328 * @param dump The descriptor dump to read from.
1329 * @param len The length of the descriptor dump.
1330 *
1331 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001332 * 1 if the descriptor couldn't be parsed,
1333 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001334 */
1335int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1336{
Nico Huberfa622942017-03-24 17:25:37 +01001337 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001338 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1339 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001340 };
Nico Huber305f4172013-06-14 11:55:26 +02001341
1342 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001343 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1344 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001345 return 1;
1346
1347 memset(layout, 0x00, sizeof(*layout));
1348
Nico Huberfa622942017-03-24 17:25:37 +01001349 ssize_t i, j;
Nico Huber519be662018-12-23 20:03:35 +01001350 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
1351 for (i = 0, j = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001352 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001353 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001354 if (limit <= base)
1355 continue;
1356 layout->entries[j].start = base;
1357 layout->entries[j].end = limit;
1358 layout->entries[j].included = false;
Nico Huber70461a92019-06-15 14:56:19 +02001359 layout->entries[j].name = strdup(regions[i]);
1360 if (!layout->entries[j].name)
1361 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001362 ++j;
1363 }
1364 layout->base.entries = layout->entries;
1365 layout->base.num_entries = j;
1366 return 0;
1367}
1368
Nico Huberad186312016-05-02 15:15:29 +02001369#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */