blob: 47ce1c648736ac7f0711cd07f89d5a2b8246d99f [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 Huberb2ad9fd2024-07-14 23:18:53 +0200338 const bool has_flill1 = cs >= SPI_ENGINE_PCH100;
Stefan Tauner1e146392011-09-15 23:52:55 +0000339
340 msg_pdbg2("=== Component Section ===\n");
341 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
342 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberd2d39932019-01-18 16:49:37 +0100343 if (has_flill1)
Nico Huberfa622942017-03-24 17:25:37 +0100344 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000345 msg_pdbg2("\n");
346
347 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000348 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000349 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000350 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000351 else
352 msg_pdbg2("Component 2 is not used.\n");
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200353
354 pprint_read_freq(cs, desc->component.modes.freq_read);
355
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000356 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
357 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
358 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
359 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000360 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000361 pprint_freq(cs, desc->component.modes.freq_fastread));
Nico Huber3f75d442024-07-14 19:17:56 +0200362 switch (cs) {
363 case CHIPSET_7_SERIES_PANTHER_POINT:
364 case CHIPSET_8_SERIES_LYNX_POINT:
365 case CHIPSET_BAYTRAIL:
366 case CHIPSET_8_SERIES_LYNX_POINT_LP:
367 case CHIPSET_8_SERIES_WELLSBURG:
368 case CHIPSET_9_SERIES_WILDCAT_POINT:
369 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
370 case CHIPSET_100_SERIES_SUNRISE_POINT:
371 case CHIPSET_APOLLO_LAKE:
372 case CHIPSET_C620_SERIES_LEWISBURG:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000373 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Werner Zehd3e8fd92022-01-25 07:02:49 +0100374 desc->component.modes.dual_output ? "en" : "dis");
Nico Huber3f75d442024-07-14 19:17:56 +0200375 break;
376 default:
377 break;
378 }
David Hendricksa5216362017-08-08 20:02:22 -0700379
Felix Singerd68a0ec2022-08-19 03:23:35 +0200380 bool has_forbidden_opcode = false;
David Hendricksa5216362017-08-08 20:02:22 -0700381 if (desc->component.FLILL != 0) {
Felix Singerd68a0ec2022-08-19 03:23:35 +0200382 has_forbidden_opcode = true;
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) {
Felix Singerd68a0ec2022-08-19 03:23:35 +0200394 has_forbidden_opcode = true;
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++) {
aarya0ac29562022-03-13 15:35:12 +0530487 const unsigned int ext_region_start = 12;
Nico Huberfa622942017-03-24 17:25:37 +0100488 size_t j;
489 msg_pdbg2("%-4s", master_names[i]);
aarya0ac29562022-03-13 15:35:12 +0530490 for (j = 0; j < (size_t)min(num_regions, ext_region_start); j++)
Nico Huberfa622942017-03-24 17:25:37 +0100491 msg_pdbg2(" %c%c ",
492 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
493 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
aarya0ac29562022-03-13 15:35:12 +0530494 for (j = ext_region_start; j < num_regions; j++)
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200495 msg_pdbg2(" %c%c ",
aarya0ac29562022-03-13 15:35:12 +0530496 desc->master.mstr[i].ext_read & (1 << (j - ext_region_start)) ? 'r' : ' ',
497 desc->master.mstr[i].ext_write & (1 << (j - ext_region_start)) ? 'w' : ' ');
Nico Huberfa622942017-03-24 17:25:37 +0100498 msg_pdbg2("\n");
499 }
David Hendricksa5216362017-08-08 20:02:22 -0700500 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
501 const char *const master_names[] = {
502 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
503 };
504 /* NM starts at 1 instead of 0 for LBG */
Nico Huber519be662018-12-23 20:03:35 +0100505 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
David Hendricksa5216362017-08-08 20:02:22 -0700506 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
507 desc->content.NM);
508 return;
509 }
510
511 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
512 " ", /* width of master name (4 chars minimum) */
513 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
514 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
515 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
516 "Reg15");
517 for (i = 0; i < nm; i++) {
518 size_t j;
519 msg_pdbg2("%-4s", master_names[i]);
520 for (j = 0; j < 16; j++)
521 msg_pdbg2(" %c%c ",
522 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
523 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
524 msg_pdbg2("\n");
525 }
Werner Zehe57d4e42022-01-03 09:44:29 +0100526 } else if (cs == CHIPSET_APOLLO_LAKE || cs == CHIPSET_GEMINI_LAKE || cs == CHIPSET_ELKHART_LAKE) {
Nico Huberd2d39932019-01-18 16:49:37 +0100527 const char *const master_names[] = { "BIOS", "TXE", };
Nico Huber519be662018-12-23 20:03:35 +0100528 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberd2d39932019-01-18 16:49:37 +0100529 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
530 return;
531 }
532
533 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
534 for (i = 0; i < nm; i++) {
Nico Huber519be662018-12-23 20:03:35 +0100535 ssize_t j;
Nico Huberd2d39932019-01-18 16:49:37 +0100536 msg_pdbg2("%-4s", master_names[i]);
537 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
538 msg_pdbg2(" %c%c ",
539 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
540 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
541 msg_pdbg2("\n");
542 }
Nico Huberfa622942017-03-24 17:25:37 +0100543 } else {
544 const struct ich_desc_master *const mstr = &desc->master;
545 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
546 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
547 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
548 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
549 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
550 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
551 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
552 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
553 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
554 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
555 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
556 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
557 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
558 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
559 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
560 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
561 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
562 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
563 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
564 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000565 msg_pdbg2("\n");
566}
567
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600568static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000569{
570 static const char * const str_GPIO12[4] = {
571 "GPIO12",
572 "LAN PHY Power Control Function (Native Output)",
573 "GLAN_DOCK# (Native Input)",
574 "invalid configuration",
575 };
576
577 msg_pdbg2("--- MCH details ---\n");
578 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
579 msg_pdbg2("\n");
580
581 msg_pdbg2("--- ICH details ---\n");
582 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
583 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
584 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
585 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
586 msg_pdbg2("SPI CS1 is used for %s.\n",
587 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
588 "LAN PHY Power Control Function" :
589 "SPI Chip Select");
590 msg_pdbg2("GPIO12 is used as %s.\n",
591 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
592 msg_pdbg2("PCIe Port 6 is used for %s.\n",
593 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
594 msg_pdbg2("%sn BMC Mode: "
595 "Intel AMT SMBus Controller 1 is connected to %s.\n",
596 desc->south.ich8.BMCMODE ? "I" : "Not i",
597 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
598 msg_pdbg2("TCO is in %s Mode.\n",
599 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
600 msg_pdbg2("ME A is %sabled.\n",
601 desc->south.ich8.ME_DISABLE ? "dis" : "en");
602 msg_pdbg2("\n");
603}
604
605static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
606{
607 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
608
609 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000610 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000611 case 0:
612 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
613 break;
614 case 1:
615 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
616 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
617 break;
618 case 2:
619 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
620 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
621 break;
622 case 3:
623 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
624 1+off, 2+off, 4+off);
625 break;
626 }
627 msg_pdbg2("\n");
628}
629
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600630static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000631{
632 /* PCHSTRP4 */
633 msg_pdbg2("Intel PHY is %s.\n",
634 (s->ibex.PHYCON == 2) ? "connected" :
635 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
636 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
637 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
638 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
639 s->ibex.GBEMAC_SMBUS_ADDR);
640 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
641 s->ibex.GBEPHY_SMBUS_ADDR);
642
643 /* PCHSTRP5 */
644 /* PCHSTRP6 */
645 /* PCHSTRP7 */
646 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
647 s->ibex.MESMA2UDID_VENDOR);
648 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
649 s->ibex.MESMA2UDID_VENDOR);
650
651 /* PCHSTRP8 */
652}
653
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600654static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000655{
656 /* PCHSTRP11 */
657 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
658 s->ibex.SML1GPAEN ? "en" : "dis");
659 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
660 s->ibex.SML1GPA);
661 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
662 s->ibex.SML1I2CAEN ? "en" : "dis");
663 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
664 s->ibex.SML1I2CA);
665
666 /* PCHSTRP12 */
667 /* PCHSTRP13 */
668}
669
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600670static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000671{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000672 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000673 100,
674 50,
675 5,
676 1
677 };
678
679 msg_pdbg2("--- PCH ---\n");
680
681 /* PCHSTRP0 */
682 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
683 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
684 s->ibex.SMB_EN ? "en" : "dis");
685 msg_pdbg2("SMLink0 segment is %sabled.\n",
686 s->ibex.SML0_EN ? "en" : "dis");
687 msg_pdbg2("SMLink1 segment is %sabled.\n",
688 s->ibex.SML1_EN ? "en" : "dis");
689 msg_pdbg2("SMLink1 Frequency: %s\n",
690 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
691 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
692 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
693 msg_pdbg2("SMLink0 Frequency: %s\n",
694 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
695 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
696 "LAN_PHY_PWR_CTRL" : "general purpose output");
697 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
698 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
699 s->ibex.DMI_REQID_DIS ? "en" : "dis");
700 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
701 1 << (6 + s->ibex.BBBS));
702
703 /* PCHSTRP1 */
704 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
705
706 /* PCHSTRP2 */
707 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
708 s->ibex.MESMASDEN ? "en" : "dis");
709 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
710 s->ibex.MESMASDA);
711 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
712 s->ibex.MESMI2CEN ? "en" : "dis");
713 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
714 s->ibex.MESMI2CA);
715
716 /* PCHSTRP3 */
717 prettyprint_ich_descriptor_pchstraps45678_56(s);
718 /* PCHSTRP9 */
719 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
720 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
721 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
722 s->ibex.PCIELR1 ? "" : "not ");
723 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
724 s->ibex.PCIELR2 ? "" : "not ");
725 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
726 s->ibex.DMILR ? "" : "not ");
727 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
728 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
729 s->ibex.PHY_PCIE_EN ? "en" : "dis");
730
731 /* PCHSTRP10 */
732 msg_pdbg2("Management Engine will boot from %sflash.\n",
733 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
734 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
735 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
736 s->ibex.VE_EN ? "en" : "dis");
737 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
738 s->ibex.MMDDE ? "en" : "dis");
739 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
740 s->ibex.MMADDR);
741 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
742 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
743 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
744 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
745 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
746
747 prettyprint_ich_descriptor_pchstraps111213_56(s);
748
749 /* PCHSTRP14 */
750 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
751 s->ibex.VE_EN2 ? "en" : "dis");
752 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
753 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
754 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
755 s->ibex.BW_SSD ? "en" : "dis");
756 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
757 s->ibex.NVMHCI_EN ? "en" : "dis");
758
759 /* PCHSTRP15 */
760 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
761 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
762 s->ibex.IWL_EN ? "en" : "dis");
763 msg_pdbg2("t209 min Timing: %d ms\n",
764 dec_t209min[s->ibex.t209min]);
765 msg_pdbg2("\n");
766}
767
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600768static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000769{
770 msg_pdbg2("--- PCH ---\n");
771
772 /* PCHSTRP0 */
773 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
774 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
775 s->ibex.SMB_EN ? "en" : "dis");
776 msg_pdbg2("SMLink0 segment is %sabled.\n",
777 s->ibex.SML0_EN ? "en" : "dis");
778 msg_pdbg2("SMLink1 segment is %sabled.\n",
779 s->ibex.SML1_EN ? "en" : "dis");
780 msg_pdbg2("SMLink1 Frequency: %s\n",
781 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
782 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
783 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
784 msg_pdbg2("SMLink0 Frequency: %s\n",
785 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
786 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
787 "LAN_PHY_PWR_CTRL" : "general purpose output");
788 msg_pdbg2("LinkSec is %sabled.\n",
789 s->cougar.LINKSEC_DIS ? "en" : "dis");
790 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
791 s->ibex.DMI_REQID_DIS ? "en" : "dis");
792 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
793 1 << (6 + s->ibex.BBBS));
794
795 /* PCHSTRP1 */
796 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
797 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
798
799 /* PCHSTRP2 */
800 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
801 s->ibex.MESMASDEN ? "en" : "dis");
802 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
803 s->ibex.MESMASDA);
804 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
805 s->cougar.MESMMCTPAEN ? "en" : "dis");
806 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
807 s->cougar.MESMMCTPA);
808 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
809 s->ibex.MESMI2CEN ? "en" : "dis");
810 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
811 s->ibex.MESMI2CA);
812
813 /* PCHSTRP3 */
814 prettyprint_ich_descriptor_pchstraps45678_56(s);
815 /* PCHSTRP9 */
816 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
817 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
818 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
819 s->ibex.PCIELR1 ? "" : "not ");
820 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
821 s->ibex.PCIELR2 ? "" : "not ");
822 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
823 s->ibex.DMILR ? "" : "not ");
824 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
825 s->cougar.MDSMBE_EN ? "en" : "dis");
826 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
827 s->cougar.MDSMBE_ADD);
828 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
829 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
830 s->ibex.PHY_PCIE_EN ? "en" : "dis");
831 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
832 s->cougar.SUB_DECODE_EN ? "en" : "dis");
833 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
834 "PCHHOT#" : "SML1ALERT#");
835
836 /* PCHSTRP10 */
837 msg_pdbg2("Management Engine will boot from %sflash.\n",
838 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
839
840 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
841 s->cougar.MDSMBE_EN ? "en" : "dis");
842 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
843 s->cougar.MDSMBE_ADD);
844
845 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
846 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000847 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
848 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000849 msg_pdbg2("ICC Profile is selected by %s.\n",
850 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
851 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
852 s->cougar.Deep_SX_EN ? "not " : "");
853 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
854 s->cougar.ME_DBG_LAN ? "en" : "dis");
855
856 prettyprint_ich_descriptor_pchstraps111213_56(s);
857
858 /* PCHSTRP14 */
859 /* PCHSTRP15 */
860 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
861 msg_pdbg2("Integrated wired LAN is %sabled.\n",
862 s->cougar.IWL_EN ? "en" : "dis");
863 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
864 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000865 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000866 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
867 "general purpose output" : "SLP_LAN#");
868
869 /* PCHSTRP16 */
870 /* PCHSTRP17 */
871 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
872 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
873 msg_pdbg2("\n");
874}
875
876void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
877{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000878 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000879 msg_pdbg2("=== Softstraps ===\n");
880
Nico Huber519be662018-12-23 20:03:35 +0100881 max_count = MIN(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
Nico Huberd7c75522017-03-29 16:31:49 +0200882 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000883 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200884 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000885 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200886 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000887
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000888 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
889 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000890 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
891 msg_pdbg2("\n");
892
Nico Huber519be662018-12-23 20:03:35 +0100893 max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
Nico Huberd7c75522017-03-29 16:31:49 +0200894 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000895 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
896 desc->content.ISL, max_count);
897 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200898 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000899
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000900 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
901 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000902 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
903 msg_pdbg2("\n");
904
905 switch (cs) {
906 case CHIPSET_ICH8:
907 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
908 msg_pdbg2("Detailed North/MCH/PROC information is "
909 "probably not reliable, printing anyway.\n");
910 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
911 msg_pdbg2("Detailed South/ICH/PCH information is "
912 "probably not reliable, printing anyway.\n");
913 prettyprint_ich_descriptor_straps_ich8(desc);
914 break;
915 case CHIPSET_5_SERIES_IBEX_PEAK:
916 /* PCH straps only. PROCSTRPs are unknown. */
917 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
918 msg_pdbg2("Detailed South/ICH/PCH information is "
919 "probably not reliable, printing anyway.\n");
920 prettyprint_ich_descriptor_straps_ibex(&desc->south);
921 break;
922 case CHIPSET_6_SERIES_COUGAR_POINT:
923 /* PCH straps only. PROCSTRP0 is "reserved". */
924 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
925 msg_pdbg2("Detailed South/ICH/PCH information is "
926 "probably not reliable, printing anyway.\n");
927 prettyprint_ich_descriptor_straps_cougar(&desc->south);
928 break;
929 case CHIPSET_ICH_UNKNOWN:
930 break;
931 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000932 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000933 break;
934 }
935}
936
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600937static void prettyprint_rdid(uint32_t reg_val)
Stefan Taunerb3850962011-12-24 00:00:32 +0000938{
939 uint8_t mid = reg_val & 0xFF;
940 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
941 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
942}
943
944void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
945{
946 int i;
947 msg_pdbg2("=== Upper Map Section ===\n");
948 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
949 msg_pdbg2("\n");
950
951 msg_pdbg2("--- Details ---\n");
952 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
953 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
954 msg_pdbg2("\n");
955
956 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000957 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000958 uint32_t jid = umap->vscc_table[i].JID;
959 uint32_t vscc = umap->vscc_table[i].VSCC;
960 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
961 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
Martin Rothf6c1cb12022-03-15 10:55:25 -0600962 msg_pdbg2(" "); /* indentation */
Stefan Taunerb3850962011-12-24 00:00:32 +0000963 prettyprint_rdid(jid);
Martin Rothf6c1cb12022-03-15 10:55:25 -0600964 msg_pdbg2(" "); /* indentation */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000965 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000966 }
967 msg_pdbg2("\n");
968}
969
David Hendricks66565a72021-09-20 21:56:40 -0700970static inline void warn_peculiar_desc(const char *const name)
Nico Huber964007a2021-06-17 21:12:47 +0200971{
Nico Huber964007a2021-06-17 21:12:47 +0200972 msg_pwarn("Peculiar flash descriptor, assuming %s compatibility.\n", name);
973}
974
Nico Huber1dc3d422017-06-17 00:09:31 +0200975/*
976 * Guesses a minimum chipset version based on the maximum number of
Nico Huber3ad9aad2021-06-17 22:05:00 +0200977 * soft straps per generation and presence of the MIP base (MDTBA).
Nico Huber1dc3d422017-06-17 00:09:31 +0200978 */
Nico Huber3ad9aad2021-06-17 22:05:00 +0200979static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content,
980 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +0200981{
982 if (content->ICCRIBA == 0x00) {
983 if (content->MSL == 0 && content->ISL <= 2)
984 return CHIPSET_ICH8;
Nico Huber83b01c82021-06-17 21:20:09 +0200985 if (content->ISL <= 2)
Nico Huber1dc3d422017-06-17 00:09:31 +0200986 return CHIPSET_ICH9;
Nico Huber83b01c82021-06-17 21:20:09 +0200987 if (content->ISL <= 10)
Nico Huber1dc3d422017-06-17 00:09:31 +0200988 return CHIPSET_ICH10;
David Hendricks66565a72021-09-20 21:56:40 -0700989 if (content->ISL <= 16)
990 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber83b01c82021-06-17 21:20:09 +0200991 if (content->FLMAP2 == 0) {
Nico Huber81965f32021-06-17 23:25:35 +0200992 if (content->ISL == 19)
993 return CHIPSET_APOLLO_LAKE;
David Hendricks66565a72021-09-20 21:56:40 -0700994 if (content->ISL == 23)
995 return CHIPSET_GEMINI_LAKE;
996 warn_peculiar_desc("Gemini Lake");
Nico Huber81965f32021-06-17 23:25:35 +0200997 return CHIPSET_GEMINI_LAKE;
Nico Huberd2d39932019-01-18 16:49:37 +0100998 }
Jonathan Zhang3bf7cfb2021-08-30 23:25:06 -0700999 if (content->ISL <= 80)
1000 return CHIPSET_C620_SERIES_LEWISBURG;
David Hendricks66565a72021-09-20 21:56:40 -07001001 warn_peculiar_desc("Ibex Peak");
Nico Huber1dc3d422017-06-17 00:09:31 +02001002 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber3ad9aad2021-06-17 22:05:00 +02001003 } else if (upper->MDTBA == 0x00) {
1004 if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
1005 if (content->MSL == 0 && content->ISL <= 17)
1006 return CHIPSET_BAYTRAIL;
1007 if (content->MSL <= 1 && content->ISL <= 18)
1008 return CHIPSET_6_SERIES_COUGAR_POINT;
David Hendricks66565a72021-09-20 21:56:40 -07001009 if (content->MSL <= 1 && content->ISL <= 21)
1010 return CHIPSET_8_SERIES_LYNX_POINT;
1011 warn_peculiar_desc("Lynx Point");
Nico Huber81965f32021-06-17 23:25:35 +02001012 return CHIPSET_8_SERIES_LYNX_POINT;
Nico Huber3ad9aad2021-06-17 22:05:00 +02001013 }
1014 if (content->NM == 6) {
David Hendricks66565a72021-09-20 21:56:40 -07001015 if (content->ICCRIBA <= 0x34)
1016 return CHIPSET_C620_SERIES_LEWISBURG;
1017 warn_peculiar_desc("C620 series");
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001018 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber3ad9aad2021-06-17 22:05:00 +02001019 }
David Hendricks66565a72021-09-20 21:56:40 -07001020 if (content->ICCRIBA == 0x31)
1021 return CHIPSET_100_SERIES_SUNRISE_POINT;
1022 warn_peculiar_desc("100 series");
Nico Huber83b01c82021-06-17 21:20:09 +02001023 return CHIPSET_100_SERIES_SUNRISE_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +02001024 } else {
David Hendricks66565a72021-09-20 21:56:40 -07001025 if (content->ICCRIBA == 0x34)
1026 return CHIPSET_300_SERIES_CANNON_POINT;
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001027 if (content->CSSL == 0x11)
1028 return CHIPSET_500_SERIES_TIGER_POINT;
Nico Huber29c23dd2022-12-21 15:25:09 +00001029 if (content->CSSL == 0x14) /* backwards compatible Alder Point */
1030 return CHIPSET_500_SERIES_TIGER_POINT;
Nico Huber756b6b32022-12-21 17:15:13 +00001031 if (content->CSSL == 0x03) {
1032 if (content->CSSO == 0x58)
1033 return CHIPSET_ELKHART_LAKE;
1034 else if (content->CSSO == 0x6c) /* backwards compatible Jasper Lake */
1035 return CHIPSET_300_SERIES_CANNON_POINT;
1036 }
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001037 msg_pwarn("Unknown flash descriptor, assuming 500 series compatibility.\n");
1038 return CHIPSET_500_SERIES_TIGER_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +02001039 }
1040}
1041
1042/*
1043 * As an additional measure, we check the read frequency like `ifdtool`.
1044 * The frequency value 6 (17MHz) was reserved before Skylake and is the
1045 * only valid value since. Skylake is currently the most important dis-
1046 * tinction because of the dropped number of regions field (NR).
1047 */
Nico Huberfa622942017-03-24 17:25:37 +01001048static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
Nico Huber3ad9aad2021-06-17 22:05:00 +02001049 const struct ich_desc_component *const component,
1050 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +02001051{
Nico Huber3ad9aad2021-06-17 22:05:00 +02001052 const enum ich_chipset guess = guess_ich_chipset_from_content(content, upper);
Nico Huber1dc3d422017-06-17 00:09:31 +02001053
Nico Huberd2d39932019-01-18 16:49:37 +01001054 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001055 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001056 case CHIPSET_500_SERIES_TIGER_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001057 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +01001058 case CHIPSET_ELKHART_LAKE:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001059 /* `freq_read` was repurposed, so can't check on it any more. */
Nico Huber72a9dc02021-06-17 22:47:00 +02001060 break;
Nico Huberd2d39932019-01-18 16:49:37 +01001061 case CHIPSET_100_SERIES_SUNRISE_POINT:
1062 case CHIPSET_C620_SERIES_LEWISBURG:
1063 case CHIPSET_APOLLO_LAKE:
1064 if (component->modes.freq_read != 6) {
Nico Huber964007a2021-06-17 21:12:47 +02001065 msg_pwarn("\nThe flash descriptor looks like a Skylake/Sunrise Point descriptor.\n"
Nico Huberd2d39932019-01-18 16:49:37 +01001066 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
1067 "Please report this message, the output of `ich_descriptors_tool` for\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +02001068 "your descriptor and the output of `lspci -nn` to flashprog@flashprog.org\n\n");
Nico Huberd2d39932019-01-18 16:49:37 +01001069 }
Nico Huber72a9dc02021-06-17 22:47:00 +02001070 break;
Nico Huberd2d39932019-01-18 16:49:37 +01001071 default:
1072 if (component->modes.freq_read == 6) {
Nico Huber964007a2021-06-17 21:12:47 +02001073 msg_pwarn("\nThe flash descriptor has the read frequency set to 17MHz. However,\n"
Nico Huber1dc3d422017-06-17 00:09:31 +02001074 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
1075 "Please report this message, the output of `ich_descriptors_tool` for\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +02001076 "your descriptor and the output of `lspci -nn` to flashprog@flashprog.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -07001077 }
Nico Huber1dc3d422017-06-17 00:09:31 +02001078 }
Nico Huber72a9dc02021-06-17 22:47:00 +02001079 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +02001080}
1081
Stefan Taunerb3850962011-12-24 00:00:32 +00001082/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +01001083int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
1084 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +00001085{
Nico Huber519be662018-12-23 20:03:35 +01001086 ssize_t i, max_count;
1087 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +00001088
1089 if (dump == NULL || desc == NULL)
1090 return ICH_RET_PARAM;
1091
1092 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1093 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1094 pch_bug_offset = 4;
1095 else
1096 return ICH_RET_ERR;
1097 }
1098
1099 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001100 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001101 return ICH_RET_OOB;
1102 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1103 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1104 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1105 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1106
1107 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001108 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001109 return ICH_RET_OOB;
1110 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1111 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1112 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1113
Nico Huber8a03c902021-06-17 21:23:29 +02001114 /* upper map */
1115 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1116
1117 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1118 * "Identifies the 1s based number of DWORDS contained in the VSCC
1119 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1120 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1121 * check ensures that the maximum offset actually accessed is available.
1122 */
1123 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
1124 return ICH_RET_OOB;
1125
1126 for (i = 0; i < desc->upper.VTL/2; i++) {
1127 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1128 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
1129 }
1130
Nico Huber67d71792017-06-17 03:10:15 +02001131 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huber3ad9aad2021-06-17 22:05:00 +02001132 *cs = guess_ich_chipset(&desc->content, &desc->component, &desc->upper);
Nico Huber67d71792017-06-17 03:10:15 +02001133 prettyprint_ich_chipset(*cs);
1134 }
Nico Huberfa622942017-03-24 17:25:37 +01001135
Stefan Taunerb3850962011-12-24 00:00:32 +00001136 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001137 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001138 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001139 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001140 for (i = 0; i < nr; i++)
1141 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001142
1143 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001144 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001145 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001146 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001147 for (i = 0; i < nm; i++)
1148 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001149
Stefan Taunerb3850962011-12-24 00:00:32 +00001150 /* MCH/PROC (aka. North) straps */
1151 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1152 return ICH_RET_OOB;
1153
1154 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001155 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001156 for (i = 0; i < max_count; i++)
1157 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001158
1159 /* ICH/PCH (aka. South) straps */
1160 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1161 return ICH_RET_OOB;
1162
1163 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001164 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001165 for (i = 0; i < max_count; i++)
1166 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001167
1168 return ICH_RET_OK;
1169}
1170
Nico Huberad186312016-05-02 15:15:29 +02001171#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001172
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001173/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001174\em idx in bytes or -1 if the correct size can not be determined. */
1175int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001176{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001177 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001178 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001179 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001180 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001181
1182 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001183 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001184
1185 uint8_t size_enc;
1186 uint8_t size_max;
1187
1188 switch (cs) {
1189 case CHIPSET_ICH8:
1190 case CHIPSET_ICH9:
1191 case CHIPSET_ICH10:
1192 case CHIPSET_5_SERIES_IBEX_PEAK:
1193 case CHIPSET_6_SERIES_COUGAR_POINT:
1194 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001195 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001196 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001197 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001198 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001199 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001200 }
1201 size_max = 5;
1202 break;
1203 case CHIPSET_8_SERIES_LYNX_POINT:
1204 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1205 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001206 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001207 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001208 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001209 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001210 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001211 case CHIPSET_500_SERIES_TIGER_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001212 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001213 case CHIPSET_GEMINI_LAKE:
Werner Zehe57d4e42022-01-03 09:44:29 +01001214 case CHIPSET_ELKHART_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001215 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001216 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001217 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001218 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001219 }
1220 size_max = 7;
1221 break;
1222 case CHIPSET_ICH_UNKNOWN:
1223 default:
1224 msg_pwarn("Density encoding is unknown on this chipset.\n");
1225 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001226 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001227
1228 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001229 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001230 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1231 idx, size_enc, size_max);
1232 return -1;
1233 }
1234
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001235 return (1 << (19 + size_enc));
1236}
1237
Nico Huber8d494992017-06-19 12:18:33 +02001238/* Only used by ichspi.c */
1239#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001240static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001241{
1242 uint32_t control = 0;
1243 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1244 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberb2ad9fd2024-07-14 23:18:53 +02001245
1246 if (cs >= SPI_ENGINE_PCH100) {
Nico Huberd54e4f42017-03-23 23:45:47 +01001247 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1248 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberb2ad9fd2024-07-14 23:18:53 +02001249 } else {
Nico Huberd54e4f42017-03-23 23:45:47 +01001250 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1251 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1252 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001253}
1254
Nico Huberd54e4f42017-03-23 23:45:47 +01001255int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001256{
Nico Huber519be662018-12-23 20:03:35 +01001257 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001258 struct ich_desc_region *r = &desc->region;
1259
1260 /* Test if bit-fields are working as expected.
1261 * FIXME: Replace this with dynamic bitfield fixup
1262 */
1263 for (i = 0; i < 4; i++)
1264 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001265 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1266 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1267 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1268 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001269 msg_pdbg("The combination of compiler and CPU architecture used"
1270 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001271 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1272 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1273 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1274 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1275 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1276 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1277 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1278 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001279 return ICH_RET_ERR;
1280 }
1281
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001282 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001283 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001284 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1285 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1286 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1287 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001288
1289 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001290 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1291 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1292 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001293
1294 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001295 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1296 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001297 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001298 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001299 return ICH_RET_ERR;
1300 }
Nico Huberfa622942017-03-24 17:25:37 +01001301 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001302 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001303
1304 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001305 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1306 if (nm < 0) {
1307 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1308 __func__, desc->content.NM + 1);
1309 return ICH_RET_ERR;
1310 }
1311 for (i = 0; i < nm; i++)
1312 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001313
1314 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1315 * reading the upper map is impossible on all chipsets, so don't bother.
1316 */
1317
1318 msg_pdbg2(" done.\n");
1319 return ICH_RET_OK;
1320}
Nico Huber8d494992017-06-19 12:18:33 +02001321#endif
Nico Huber305f4172013-06-14 11:55:26 +02001322
1323/**
1324 * @brief Read a layout from the dump of an Intel ICH descriptor.
1325 *
1326 * @param layout Pointer where to store the layout.
1327 * @param dump The descriptor dump to read from.
1328 * @param len The length of the descriptor dump.
1329 *
1330 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001331 * 1 if the descriptor couldn't be parsed,
1332 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001333 */
Nico Huber5bd990c2019-06-16 19:46:46 +02001334int layout_from_ich_descriptors(
Nico Huberc3b02dc2023-08-12 01:13:45 +02001335 struct flashprog_layout **const layout,
Nico Huber5bd990c2019-06-16 19:46:46 +02001336 const void *const dump, const size_t len)
Nico Huber305f4172013-06-14 11:55:26 +02001337{
Nico Huberfa622942017-03-24 17:25:37 +01001338 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001339 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1340 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001341 };
Nico Huber305f4172013-06-14 11:55:26 +02001342
1343 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001344 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1345 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001346 return 1;
1347
Nico Huberc3b02dc2023-08-12 01:13:45 +02001348 if (flashprog_layout_new(layout))
Nico Huber5bd990c2019-06-16 19:46:46 +02001349 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001350
Nico Huber92e0b622019-06-15 15:55:11 +02001351 ssize_t i;
Nico Huber519be662018-12-23 20:03:35 +01001352 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
Nico Huber92e0b622019-06-15 15:55:11 +02001353 for (i = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001354 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001355 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001356 if (limit <= base)
1357 continue;
Nico Huberc3b02dc2023-08-12 01:13:45 +02001358 if (flashprog_layout_add_region(*layout, base, limit, regions[i])) {
1359 flashprog_layout_release(*layout);
Nico Huber5bd990c2019-06-16 19:46:46 +02001360 *layout = NULL;
Nico Huber70461a92019-06-15 14:56:19 +02001361 return 2;
Nico Huber5bd990c2019-06-16 19:46:46 +02001362 }
Nico Huber305f4172013-06-14 11:55:26 +02001363 }
Nico Huber305f4172013-06-14 11:55:26 +02001364 return 0;
1365}
1366
Nico Huberad186312016-05-02 15:15:29 +02001367#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */