blob: ac3602b174c51dd10281440fac0484df1214bff4 [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:
David Hendricksa5216362017-08-08 20:02:22 -070048 return 16;
Nico Huberfa622942017-03-24 17:25:37 +010049 case CHIPSET_100_SERIES_SUNRISE_POINT:
50 return 10;
51 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
52 case CHIPSET_9_SERIES_WILDCAT_POINT:
53 case CHIPSET_8_SERIES_LYNX_POINT_LP:
54 case CHIPSET_8_SERIES_LYNX_POINT:
55 case CHIPSET_8_SERIES_WELLSBURG:
56 if (cont->NR <= 6)
57 return cont->NR + 1;
58 else
59 return -1;
60 default:
61 if (cont->NR <= 4)
62 return cont->NR + 1;
63 else
64 return -1;
65 }
66}
67
68ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
69{
David Hendricksa5216362017-08-08 20:02:22 -070070 switch (cs) {
71 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberd2d39932019-01-18 16:49:37 +010072 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +020073 case CHIPSET_GEMINI_LAKE:
David Hendricksa5216362017-08-08 20:02:22 -070074 if (cont->NM <= MAX_NUM_MASTERS)
75 return cont->NM;
Richard Hughesdb7482b2018-12-19 12:04:30 +000076 break;
David Hendricksa5216362017-08-08 20:02:22 -070077 default:
78 if (cont->NM < MAX_NUM_MASTERS)
79 return cont->NM + 1;
80 }
81
82 return -1;
Nico Huberfa622942017-03-24 17:25:37 +010083}
84
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000085void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000086{
87 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
88 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
89 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
90 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000091 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
92 if (print_vcl)
93 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
94 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000095}
96
97#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
98#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
99#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
100#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
101#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
102
Nico Huber67d71792017-06-17 03:10:15 +0200103void prettyprint_ich_chipset(enum ich_chipset cs)
104{
105 static const char *const chipset_names[] = {
106 "Unknown ICH", "ICH8", "ICH9", "ICH10",
107 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
108 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
109 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
Angel Pons4db0fdf2020-07-10 17:04:10 +0200110 "C620 series Lewisburg", "300/400 series Cannon/Comet Point",
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200111 "500 series Tiger Point", "Apollo Lake", "Gemini Lake",
Nico Huber67d71792017-06-17 03:10:15 +0200112 };
113 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
114 cs = 0;
115 else
116 cs = cs - CHIPSET_ICH8 + 1;
117 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
118}
119
Stefan Tauner1e146392011-09-15 23:52:55 +0000120void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
121{
Nico Huberfa622942017-03-24 17:25:37 +0100122 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000123 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100124 prettyprint_ich_descriptor_region(cs, desc);
125 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200126#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000127 if (cs >= CHIPSET_ICH8) {
128 prettyprint_ich_descriptor_upper_map(&desc->upper);
129 prettyprint_ich_descriptor_straps(cs, desc);
130 }
Nico Huberad186312016-05-02 15:15:29 +0200131#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000132}
133
Nico Huberfa622942017-03-24 17:25:37 +0100134void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000135{
136 msg_pdbg2("=== Content Section ===\n");
137 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
138 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
139 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
140 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
141 msg_pdbg2("\n");
142
143 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100144 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
145 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
146 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
147 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
Nico Huberd2d39932019-01-18 16:49:37 +0100148 msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL);
149 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont));
Nico Huberfa622942017-03-24 17:25:37 +0100150 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
151 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
152 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
153 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000154 msg_pdbg2("\n");
155}
156
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000157static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
158{
159 if (idx > 1) {
160 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
161 return NULL;
162 }
163
164 if (desc->content.NC == 0 && idx > 0)
165 return "unused";
166
167 static const char * const size_str[] = {
168 "512 kB", /* 0000 */
169 "1 MB", /* 0001 */
170 "2 MB", /* 0010 */
171 "4 MB", /* 0011 */
172 "8 MB", /* 0100 */
173 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
174 "32 MB", /* 0110 */
175 "64 MB", /* 0111 */
176 };
177
178 switch (cs) {
179 case CHIPSET_ICH8:
180 case CHIPSET_ICH9:
181 case CHIPSET_ICH10:
182 case CHIPSET_5_SERIES_IBEX_PEAK:
183 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000184 case CHIPSET_7_SERIES_PANTHER_POINT:
185 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000186 uint8_t size_enc;
187 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000188 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000189 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000190 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000191 }
192 if (size_enc > 5)
193 return "reserved";
194 return size_str[size_enc];
195 }
196 case CHIPSET_8_SERIES_LYNX_POINT:
197 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000198 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100199 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100200 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
David Hendricksa5216362017-08-08 20:02:22 -0700201 case CHIPSET_100_SERIES_SUNRISE_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100202 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200203 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200204 case CHIPSET_500_SERIES_TIGER_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200205 case CHIPSET_APOLLO_LAKE:
206 case CHIPSET_GEMINI_LAKE: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000207 uint8_t size_enc;
208 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000209 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000210 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000211 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000212 }
213 if (size_enc > 7)
214 return "reserved";
215 return size_str[size_enc];
216 }
217 case CHIPSET_ICH_UNKNOWN:
218 default:
219 return "unknown";
220 }
221}
222
223static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000224{
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200225 static const char *const freq_str[4][8] = { {
Nico Huber129e9382019-06-06 15:43:27 +0200226 "20 MHz",
227 "33 MHz",
228 "reserved",
229 "reserved",
230 "50 MHz", /* New since Ibex Peak */
231 "reserved",
232 "reserved",
233 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100234 }, {
Nico Huber129e9382019-06-06 15:43:27 +0200235 "reserved",
236 "reserved",
237 "48 MHz",
238 "reserved",
239 "30 MHz",
240 "reserved",
241 "17 MHz",
242 "reserved"
Nico Huberd2d39932019-01-18 16:49:37 +0100243 }, {
244 "reserved",
245 "50 MHz",
246 "40 MHz",
247 "reserved",
248 "25 MHz",
249 "reserved",
250 "14 MHz / 17 MHz",
251 "reserved"
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200252 }, {
253 "100 MHz",
254 "50 MHz",
255 "reserved",
256 "33 MHz",
257 "25 MHz",
258 "reserved",
259 "14 MHz",
260 "reserved"
261 }};
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000262
263 switch (cs) {
264 case CHIPSET_ICH8:
265 case CHIPSET_ICH9:
266 case CHIPSET_ICH10:
267 if (value > 1)
268 return "reserved";
Richard Hughesdb7482b2018-12-19 12:04:30 +0000269 /* Fall through. */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000270 case CHIPSET_5_SERIES_IBEX_PEAK:
271 case CHIPSET_6_SERIES_COUGAR_POINT:
272 case CHIPSET_7_SERIES_PANTHER_POINT:
273 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000274 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000275 case CHIPSET_8_SERIES_LYNX_POINT_LP:
276 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000277 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100278 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100279 return freq_str[0][value];
280 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700281 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200282 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100283 return freq_str[1][value];
Nico Huberd2d39932019-01-18 16:49:37 +0100284 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200285 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100286 return freq_str[2][value];
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200287 case CHIPSET_500_SERIES_TIGER_POINT:
288 return freq_str[3][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000289 case CHIPSET_ICH_UNKNOWN:
290 default:
291 return "unknown";
292 }
293}
294
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200295static void pprint_read_freq(enum ich_chipset cs, uint8_t value)
296{
297 static const char *const freq_str[1][8] = { {
298 "20 MHz",
299 "24 MHz",
300 "30 MHz",
301 "48 MHz",
302 "60 MHz",
303 "reserved",
304 "reserved",
305 "reserved"
306 }};
307
308 switch (cs) {
309 case CHIPSET_300_SERIES_CANNON_POINT:
310 msg_pdbg2("eSPI/EC Bus Clock Frequency: %s\n", freq_str[0][value]);
311 return;
312 case CHIPSET_500_SERIES_TIGER_POINT:
313 msg_pdbg2("Read Clock Frequency: %s\n", "reserved");
314 return;
315 default:
316 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, value));
317 return;
318 }
319}
320
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000321void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
322{
Nico Huberd2d39932019-01-18 16:49:37 +0100323 bool has_flill1;
324
325 switch (cs) {
326 case CHIPSET_100_SERIES_SUNRISE_POINT:
327 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200328 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200329 case CHIPSET_500_SERIES_TIGER_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100330 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200331 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100332 has_flill1 = true;
333 break;
334 default:
335 has_flill1 = false;
336 break;
337 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000338
339 msg_pdbg2("=== Component Section ===\n");
340 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
341 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberd2d39932019-01-18 16:49:37 +0100342 if (has_flill1)
Nico Huberfa622942017-03-24 17:25:37 +0100343 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000344 msg_pdbg2("\n");
345
346 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000347 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000348 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000349 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000350 else
351 msg_pdbg2("Component 2 is not used.\n");
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200352
353 pprint_read_freq(cs, desc->component.modes.freq_read);
354
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000355 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
356 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
357 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
358 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000359 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000360 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000361 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
362 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000363 desc->component.modes.dual_output ? "dis" : "en");
David Hendricksa5216362017-08-08 20:02:22 -0700364
365 int has_forbidden_opcode = 0;
366 if (desc->component.FLILL != 0) {
367 has_forbidden_opcode = 1;
Stefan Tauner1e146392011-09-15 23:52:55 +0000368 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
369 desc->component.invalid_instr0);
370 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
371 desc->component.invalid_instr1);
372 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
373 desc->component.invalid_instr2);
374 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
375 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700376 }
Nico Huberd2d39932019-01-18 16:49:37 +0100377 if (has_flill1) {
David Hendricksa5216362017-08-08 20:02:22 -0700378 if (desc->component.FLILL1 != 0) {
379 has_forbidden_opcode = 1;
Nico Huberfa622942017-03-24 17:25:37 +0100380 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
381 desc->component.invalid_instr4);
382 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
383 desc->component.invalid_instr5);
384 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
385 desc->component.invalid_instr6);
386 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
387 desc->component.invalid_instr7);
388 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000389 }
David Hendricksa5216362017-08-08 20:02:22 -0700390 if (!has_forbidden_opcode)
391 msg_pdbg2("No forbidden opcodes.\n");
392
Stefan Tauner1e146392011-09-15 23:52:55 +0000393 msg_pdbg2("\n");
394}
395
396static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
397{
Nico Huberfa622942017-03-24 17:25:37 +0100398 static const char *const region_names[] = {
Nico Huberd2d39932019-01-18 16:49:37 +0100399 "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown",
David Hendricksa5216362017-08-08 20:02:22 -0700400 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000401 };
Nico Huberfa622942017-03-24 17:25:37 +0100402 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000403 msg_pdbg2("%s: region index too high.\n", __func__);
404 return;
405 }
406 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
407 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100408 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000409 if (base > limit)
410 msg_pdbg2("is unused.\n");
411 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200412 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000413}
414
Nico Huberfa622942017-03-24 17:25:37 +0100415void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000416{
Nico Huber519be662018-12-23 20:03:35 +0100417 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100418 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000419 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100420 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000421 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100422 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000423 return;
424 }
Nico Huberfa622942017-03-24 17:25:37 +0100425 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100426 msg_pdbg2("FLREG%zd 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000427 msg_pdbg2("\n");
428
429 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100430 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100431 pprint_freg(&desc->region, (uint32_t)i);
Stefan Tauner1e146392011-09-15 23:52:55 +0000432 msg_pdbg2("\n");
433}
434
Nico Huberfa622942017-03-24 17:25:37 +0100435void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000436{
Nico Huber519be662018-12-23 20:03:35 +0100437 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100438 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000439 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100440 if (nm < 0) {
441 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
442 desc->content.NM + 1);
443 return;
444 }
445 for (i = 0; i < nm; i++)
Nico Huber519be662018-12-23 20:03:35 +0100446 msg_pdbg2("FLMSTR%zd 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000447 msg_pdbg2("\n");
448
449 msg_pdbg2("--- Details ---\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200450 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT ||
Michał Żygowski5c9f5422021-06-16 15:13:54 +0200451 cs == CHIPSET_300_SERIES_CANNON_POINT ||
452 cs == CHIPSET_500_SERIES_TIGER_POINT) {
Nico Huberfa622942017-03-24 17:25:37 +0100453 const char *const master_names[] = {
454 "BIOS", "ME", "GbE", "unknown", "EC",
455 };
Nico Huber519be662018-12-23 20:03:35 +0100456 if (nm >= (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberfa622942017-03-24 17:25:37 +0100457 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
458 desc->content.NM + 1);
459 return;
460 }
461
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200462 size_t num_regions;
463 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9");
464 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
465 num_regions = 10;
466 msg_pdbg2("\n");
467 } else {
468 num_regions = 16;
469 msg_pdbg2(" RegA RegB RegC RegD RegE RegF\n");
470 }
Nico Huberfa622942017-03-24 17:25:37 +0100471 for (i = 0; i < nm; i++) {
472 size_t j;
473 msg_pdbg2("%-4s", master_names[i]);
Nico Huber961f4a12019-10-04 17:34:22 +0200474 for (j = 0; j < (size_t)min(num_regions, 12); j++)
Nico Huberfa622942017-03-24 17:25:37 +0100475 msg_pdbg2(" %c%c ",
476 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
477 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200478 for (; j < num_regions; j++)
479 msg_pdbg2(" %c%c ",
480 desc->master.mstr[i].ext_read & (1 << (j - 12)) ? 'r' : ' ',
481 desc->master.mstr[i].ext_write & (1 << (j - 12)) ? 'w' : ' ');
Nico Huberfa622942017-03-24 17:25:37 +0100482 msg_pdbg2("\n");
483 }
David Hendricksa5216362017-08-08 20:02:22 -0700484 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
485 const char *const master_names[] = {
486 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
487 };
488 /* NM starts at 1 instead of 0 for LBG */
Nico Huber519be662018-12-23 20:03:35 +0100489 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
David Hendricksa5216362017-08-08 20:02:22 -0700490 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
491 desc->content.NM);
492 return;
493 }
494
495 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
496 " ", /* width of master name (4 chars minimum) */
497 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
498 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
499 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
500 "Reg15");
501 for (i = 0; i < nm; i++) {
502 size_t j;
503 msg_pdbg2("%-4s", master_names[i]);
504 for (j = 0; j < 16; j++)
505 msg_pdbg2(" %c%c ",
506 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
507 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
508 msg_pdbg2("\n");
509 }
Angel Pons4db0fdf2020-07-10 17:04:10 +0200510 } else if (cs == CHIPSET_APOLLO_LAKE || cs == CHIPSET_GEMINI_LAKE) {
Nico Huberd2d39932019-01-18 16:49:37 +0100511 const char *const master_names[] = { "BIOS", "TXE", };
Nico Huber519be662018-12-23 20:03:35 +0100512 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberd2d39932019-01-18 16:49:37 +0100513 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
514 return;
515 }
516
517 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
518 for (i = 0; i < nm; i++) {
Nico Huber519be662018-12-23 20:03:35 +0100519 ssize_t j;
Nico Huberd2d39932019-01-18 16:49:37 +0100520 msg_pdbg2("%-4s", master_names[i]);
521 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
522 msg_pdbg2(" %c%c ",
523 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
524 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
525 msg_pdbg2("\n");
526 }
Nico Huberfa622942017-03-24 17:25:37 +0100527 } else {
528 const struct ich_desc_master *const mstr = &desc->master;
529 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
530 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
531 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
532 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
533 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
534 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
535 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
536 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
537 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
538 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
539 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
540 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
541 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
542 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
543 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
544 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
545 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
546 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
547 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
548 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000549 msg_pdbg2("\n");
550}
551
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600552static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000553{
554 static const char * const str_GPIO12[4] = {
555 "GPIO12",
556 "LAN PHY Power Control Function (Native Output)",
557 "GLAN_DOCK# (Native Input)",
558 "invalid configuration",
559 };
560
561 msg_pdbg2("--- MCH details ---\n");
562 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
563 msg_pdbg2("\n");
564
565 msg_pdbg2("--- ICH details ---\n");
566 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
567 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
568 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
569 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
570 msg_pdbg2("SPI CS1 is used for %s.\n",
571 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
572 "LAN PHY Power Control Function" :
573 "SPI Chip Select");
574 msg_pdbg2("GPIO12 is used as %s.\n",
575 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
576 msg_pdbg2("PCIe Port 6 is used for %s.\n",
577 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
578 msg_pdbg2("%sn BMC Mode: "
579 "Intel AMT SMBus Controller 1 is connected to %s.\n",
580 desc->south.ich8.BMCMODE ? "I" : "Not i",
581 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
582 msg_pdbg2("TCO is in %s Mode.\n",
583 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
584 msg_pdbg2("ME A is %sabled.\n",
585 desc->south.ich8.ME_DISABLE ? "dis" : "en");
586 msg_pdbg2("\n");
587}
588
589static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
590{
591 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
592
593 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000594 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000595 case 0:
596 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
597 break;
598 case 1:
599 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
600 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
601 break;
602 case 2:
603 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
604 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
605 break;
606 case 3:
607 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
608 1+off, 2+off, 4+off);
609 break;
610 }
611 msg_pdbg2("\n");
612}
613
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600614static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000615{
616 /* PCHSTRP4 */
617 msg_pdbg2("Intel PHY is %s.\n",
618 (s->ibex.PHYCON == 2) ? "connected" :
619 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
620 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
621 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
622 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
623 s->ibex.GBEMAC_SMBUS_ADDR);
624 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
625 s->ibex.GBEPHY_SMBUS_ADDR);
626
627 /* PCHSTRP5 */
628 /* PCHSTRP6 */
629 /* PCHSTRP7 */
630 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
631 s->ibex.MESMA2UDID_VENDOR);
632 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
633 s->ibex.MESMA2UDID_VENDOR);
634
635 /* PCHSTRP8 */
636}
637
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600638static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000639{
640 /* PCHSTRP11 */
641 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
642 s->ibex.SML1GPAEN ? "en" : "dis");
643 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
644 s->ibex.SML1GPA);
645 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
646 s->ibex.SML1I2CAEN ? "en" : "dis");
647 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
648 s->ibex.SML1I2CA);
649
650 /* PCHSTRP12 */
651 /* PCHSTRP13 */
652}
653
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600654static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000655{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000656 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000657 100,
658 50,
659 5,
660 1
661 };
662
663 msg_pdbg2("--- PCH ---\n");
664
665 /* PCHSTRP0 */
666 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
667 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
668 s->ibex.SMB_EN ? "en" : "dis");
669 msg_pdbg2("SMLink0 segment is %sabled.\n",
670 s->ibex.SML0_EN ? "en" : "dis");
671 msg_pdbg2("SMLink1 segment is %sabled.\n",
672 s->ibex.SML1_EN ? "en" : "dis");
673 msg_pdbg2("SMLink1 Frequency: %s\n",
674 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
675 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
676 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
677 msg_pdbg2("SMLink0 Frequency: %s\n",
678 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
679 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
680 "LAN_PHY_PWR_CTRL" : "general purpose output");
681 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
682 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
683 s->ibex.DMI_REQID_DIS ? "en" : "dis");
684 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
685 1 << (6 + s->ibex.BBBS));
686
687 /* PCHSTRP1 */
688 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
689
690 /* PCHSTRP2 */
691 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
692 s->ibex.MESMASDEN ? "en" : "dis");
693 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
694 s->ibex.MESMASDA);
695 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
696 s->ibex.MESMI2CEN ? "en" : "dis");
697 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
698 s->ibex.MESMI2CA);
699
700 /* PCHSTRP3 */
701 prettyprint_ich_descriptor_pchstraps45678_56(s);
702 /* PCHSTRP9 */
703 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
704 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
705 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
706 s->ibex.PCIELR1 ? "" : "not ");
707 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
708 s->ibex.PCIELR2 ? "" : "not ");
709 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
710 s->ibex.DMILR ? "" : "not ");
711 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
712 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
713 s->ibex.PHY_PCIE_EN ? "en" : "dis");
714
715 /* PCHSTRP10 */
716 msg_pdbg2("Management Engine will boot from %sflash.\n",
717 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
718 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
719 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
720 s->ibex.VE_EN ? "en" : "dis");
721 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
722 s->ibex.MMDDE ? "en" : "dis");
723 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
724 s->ibex.MMADDR);
725 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
726 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
727 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
728 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
729 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
730
731 prettyprint_ich_descriptor_pchstraps111213_56(s);
732
733 /* PCHSTRP14 */
734 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
735 s->ibex.VE_EN2 ? "en" : "dis");
736 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
737 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
738 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
739 s->ibex.BW_SSD ? "en" : "dis");
740 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
741 s->ibex.NVMHCI_EN ? "en" : "dis");
742
743 /* PCHSTRP15 */
744 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
745 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
746 s->ibex.IWL_EN ? "en" : "dis");
747 msg_pdbg2("t209 min Timing: %d ms\n",
748 dec_t209min[s->ibex.t209min]);
749 msg_pdbg2("\n");
750}
751
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600752static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000753{
754 msg_pdbg2("--- PCH ---\n");
755
756 /* PCHSTRP0 */
757 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
758 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
759 s->ibex.SMB_EN ? "en" : "dis");
760 msg_pdbg2("SMLink0 segment is %sabled.\n",
761 s->ibex.SML0_EN ? "en" : "dis");
762 msg_pdbg2("SMLink1 segment is %sabled.\n",
763 s->ibex.SML1_EN ? "en" : "dis");
764 msg_pdbg2("SMLink1 Frequency: %s\n",
765 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
766 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
767 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
768 msg_pdbg2("SMLink0 Frequency: %s\n",
769 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
770 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
771 "LAN_PHY_PWR_CTRL" : "general purpose output");
772 msg_pdbg2("LinkSec is %sabled.\n",
773 s->cougar.LINKSEC_DIS ? "en" : "dis");
774 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
775 s->ibex.DMI_REQID_DIS ? "en" : "dis");
776 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
777 1 << (6 + s->ibex.BBBS));
778
779 /* PCHSTRP1 */
780 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
781 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
782
783 /* PCHSTRP2 */
784 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
785 s->ibex.MESMASDEN ? "en" : "dis");
786 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
787 s->ibex.MESMASDA);
788 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
789 s->cougar.MESMMCTPAEN ? "en" : "dis");
790 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
791 s->cougar.MESMMCTPA);
792 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
793 s->ibex.MESMI2CEN ? "en" : "dis");
794 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
795 s->ibex.MESMI2CA);
796
797 /* PCHSTRP3 */
798 prettyprint_ich_descriptor_pchstraps45678_56(s);
799 /* PCHSTRP9 */
800 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
801 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
802 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
803 s->ibex.PCIELR1 ? "" : "not ");
804 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
805 s->ibex.PCIELR2 ? "" : "not ");
806 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
807 s->ibex.DMILR ? "" : "not ");
808 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
809 s->cougar.MDSMBE_EN ? "en" : "dis");
810 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
811 s->cougar.MDSMBE_ADD);
812 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
813 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
814 s->ibex.PHY_PCIE_EN ? "en" : "dis");
815 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
816 s->cougar.SUB_DECODE_EN ? "en" : "dis");
817 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
818 "PCHHOT#" : "SML1ALERT#");
819
820 /* PCHSTRP10 */
821 msg_pdbg2("Management Engine will boot from %sflash.\n",
822 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
823
824 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
825 s->cougar.MDSMBE_EN ? "en" : "dis");
826 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
827 s->cougar.MDSMBE_ADD);
828
829 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
830 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000831 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
832 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000833 msg_pdbg2("ICC Profile is selected by %s.\n",
834 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
835 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
836 s->cougar.Deep_SX_EN ? "not " : "");
837 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
838 s->cougar.ME_DBG_LAN ? "en" : "dis");
839
840 prettyprint_ich_descriptor_pchstraps111213_56(s);
841
842 /* PCHSTRP14 */
843 /* PCHSTRP15 */
844 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
845 msg_pdbg2("Integrated wired LAN is %sabled.\n",
846 s->cougar.IWL_EN ? "en" : "dis");
847 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
848 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000849 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000850 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
851 "general purpose output" : "SLP_LAN#");
852
853 /* PCHSTRP16 */
854 /* PCHSTRP17 */
855 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
856 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
857 msg_pdbg2("\n");
858}
859
860void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
861{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000862 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000863 msg_pdbg2("=== Softstraps ===\n");
864
Nico Huber519be662018-12-23 20:03:35 +0100865 max_count = MIN(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
Nico Huberd7c75522017-03-29 16:31:49 +0200866 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000867 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200868 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000869 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200870 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000871
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000872 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
873 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000874 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
875 msg_pdbg2("\n");
876
Nico Huber519be662018-12-23 20:03:35 +0100877 max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
Nico Huberd7c75522017-03-29 16:31:49 +0200878 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000879 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
880 desc->content.ISL, max_count);
881 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200882 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000883
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000884 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
885 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000886 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
887 msg_pdbg2("\n");
888
889 switch (cs) {
890 case CHIPSET_ICH8:
891 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
892 msg_pdbg2("Detailed North/MCH/PROC information is "
893 "probably not reliable, printing anyway.\n");
894 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
895 msg_pdbg2("Detailed South/ICH/PCH information is "
896 "probably not reliable, printing anyway.\n");
897 prettyprint_ich_descriptor_straps_ich8(desc);
898 break;
899 case CHIPSET_5_SERIES_IBEX_PEAK:
900 /* PCH straps only. PROCSTRPs are unknown. */
901 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
902 msg_pdbg2("Detailed South/ICH/PCH information is "
903 "probably not reliable, printing anyway.\n");
904 prettyprint_ich_descriptor_straps_ibex(&desc->south);
905 break;
906 case CHIPSET_6_SERIES_COUGAR_POINT:
907 /* PCH straps only. PROCSTRP0 is "reserved". */
908 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
909 msg_pdbg2("Detailed South/ICH/PCH information is "
910 "probably not reliable, printing anyway.\n");
911 prettyprint_ich_descriptor_straps_cougar(&desc->south);
912 break;
913 case CHIPSET_ICH_UNKNOWN:
914 break;
915 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000916 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000917 break;
918 }
919}
920
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600921static void prettyprint_rdid(uint32_t reg_val)
Stefan Taunerb3850962011-12-24 00:00:32 +0000922{
923 uint8_t mid = reg_val & 0xFF;
924 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
925 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
926}
927
928void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
929{
930 int i;
931 msg_pdbg2("=== Upper Map Section ===\n");
932 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
933 msg_pdbg2("\n");
934
935 msg_pdbg2("--- Details ---\n");
936 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
937 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
938 msg_pdbg2("\n");
939
940 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000941 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000942 uint32_t jid = umap->vscc_table[i].JID;
943 uint32_t vscc = umap->vscc_table[i].VSCC;
944 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
945 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
946 msg_pdbg2(" "); /* indention */
947 prettyprint_rdid(jid);
948 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000949 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000950 }
951 msg_pdbg2("\n");
952}
953
David Hendricks66565a72021-09-20 21:56:40 -0700954static inline void warn_peculiar_desc(const char *const name)
Nico Huber964007a2021-06-17 21:12:47 +0200955{
Nico Huber964007a2021-06-17 21:12:47 +0200956 msg_pwarn("Peculiar flash descriptor, assuming %s compatibility.\n", name);
957}
958
Nico Huber1dc3d422017-06-17 00:09:31 +0200959/*
960 * Guesses a minimum chipset version based on the maximum number of
Nico Huber3ad9aad2021-06-17 22:05:00 +0200961 * soft straps per generation and presence of the MIP base (MDTBA).
Nico Huber1dc3d422017-06-17 00:09:31 +0200962 */
Nico Huber3ad9aad2021-06-17 22:05:00 +0200963static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content,
964 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +0200965{
966 if (content->ICCRIBA == 0x00) {
967 if (content->MSL == 0 && content->ISL <= 2)
968 return CHIPSET_ICH8;
Nico Huber83b01c82021-06-17 21:20:09 +0200969 if (content->ISL <= 2)
Nico Huber1dc3d422017-06-17 00:09:31 +0200970 return CHIPSET_ICH9;
Nico Huber83b01c82021-06-17 21:20:09 +0200971 if (content->ISL <= 10)
Nico Huber1dc3d422017-06-17 00:09:31 +0200972 return CHIPSET_ICH10;
David Hendricks66565a72021-09-20 21:56:40 -0700973 if (content->ISL <= 16)
974 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber83b01c82021-06-17 21:20:09 +0200975 if (content->FLMAP2 == 0) {
Nico Huber81965f32021-06-17 23:25:35 +0200976 if (content->ISL == 19)
977 return CHIPSET_APOLLO_LAKE;
David Hendricks66565a72021-09-20 21:56:40 -0700978 if (content->ISL == 23)
979 return CHIPSET_GEMINI_LAKE;
980 warn_peculiar_desc("Gemini Lake");
Nico Huber81965f32021-06-17 23:25:35 +0200981 return CHIPSET_GEMINI_LAKE;
Nico Huberd2d39932019-01-18 16:49:37 +0100982 }
Jonathan Zhang3bf7cfb2021-08-30 23:25:06 -0700983 if (content->ISL <= 80)
984 return CHIPSET_C620_SERIES_LEWISBURG;
David Hendricks66565a72021-09-20 21:56:40 -0700985 warn_peculiar_desc("Ibex Peak");
Nico Huber1dc3d422017-06-17 00:09:31 +0200986 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber3ad9aad2021-06-17 22:05:00 +0200987 } else if (upper->MDTBA == 0x00) {
988 if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
989 if (content->MSL == 0 && content->ISL <= 17)
990 return CHIPSET_BAYTRAIL;
991 if (content->MSL <= 1 && content->ISL <= 18)
992 return CHIPSET_6_SERIES_COUGAR_POINT;
David Hendricks66565a72021-09-20 21:56:40 -0700993 if (content->MSL <= 1 && content->ISL <= 21)
994 return CHIPSET_8_SERIES_LYNX_POINT;
995 warn_peculiar_desc("Lynx Point");
Nico Huber81965f32021-06-17 23:25:35 +0200996 return CHIPSET_8_SERIES_LYNX_POINT;
Nico Huber3ad9aad2021-06-17 22:05:00 +0200997 }
998 if (content->NM == 6) {
David Hendricks66565a72021-09-20 21:56:40 -0700999 if (content->ICCRIBA <= 0x34)
1000 return CHIPSET_C620_SERIES_LEWISBURG;
1001 warn_peculiar_desc("C620 series");
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001002 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber3ad9aad2021-06-17 22:05:00 +02001003 }
David Hendricks66565a72021-09-20 21:56:40 -07001004 if (content->ICCRIBA == 0x31)
1005 return CHIPSET_100_SERIES_SUNRISE_POINT;
1006 warn_peculiar_desc("100 series");
Nico Huber83b01c82021-06-17 21:20:09 +02001007 return CHIPSET_100_SERIES_SUNRISE_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +02001008 } else {
David Hendricks66565a72021-09-20 21:56:40 -07001009 if (content->ICCRIBA == 0x34)
1010 return CHIPSET_300_SERIES_CANNON_POINT;
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001011 if (content->CSSL == 0x11)
1012 return CHIPSET_500_SERIES_TIGER_POINT;
1013 msg_pwarn("Unknown flash descriptor, assuming 500 series compatibility.\n");
1014 return CHIPSET_500_SERIES_TIGER_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +02001015 }
1016}
1017
1018/*
1019 * As an additional measure, we check the read frequency like `ifdtool`.
1020 * The frequency value 6 (17MHz) was reserved before Skylake and is the
1021 * only valid value since. Skylake is currently the most important dis-
1022 * tinction because of the dropped number of regions field (NR).
1023 */
Nico Huberfa622942017-03-24 17:25:37 +01001024static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
Nico Huber3ad9aad2021-06-17 22:05:00 +02001025 const struct ich_desc_component *const component,
1026 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +02001027{
Nico Huber3ad9aad2021-06-17 22:05:00 +02001028 const enum ich_chipset guess = guess_ich_chipset_from_content(content, upper);
Nico Huber1dc3d422017-06-17 00:09:31 +02001029
Nico Huberd2d39932019-01-18 16:49:37 +01001030 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001031 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001032 case CHIPSET_500_SERIES_TIGER_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001033 case CHIPSET_GEMINI_LAKE:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001034 /* `freq_read` was repurposed, so can't check on it any more. */
Nico Huber72a9dc02021-06-17 22:47:00 +02001035 break;
Nico Huberd2d39932019-01-18 16:49:37 +01001036 case CHIPSET_100_SERIES_SUNRISE_POINT:
1037 case CHIPSET_C620_SERIES_LEWISBURG:
1038 case CHIPSET_APOLLO_LAKE:
1039 if (component->modes.freq_read != 6) {
Nico Huber964007a2021-06-17 21:12:47 +02001040 msg_pwarn("\nThe flash descriptor looks like a Skylake/Sunrise Point descriptor.\n"
Nico Huberd2d39932019-01-18 16:49:37 +01001041 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
1042 "Please report this message, the output of `ich_descriptors_tool` for\n"
1043 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
Nico Huberd2d39932019-01-18 16:49:37 +01001044 }
Nico Huber72a9dc02021-06-17 22:47:00 +02001045 break;
Nico Huberd2d39932019-01-18 16:49:37 +01001046 default:
1047 if (component->modes.freq_read == 6) {
Nico Huber964007a2021-06-17 21:12:47 +02001048 msg_pwarn("\nThe flash descriptor has the read frequency set to 17MHz. However,\n"
Nico Huber1dc3d422017-06-17 00:09:31 +02001049 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
1050 "Please report this message, the output of `ich_descriptors_tool` for\n"
1051 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -07001052 }
Nico Huber1dc3d422017-06-17 00:09:31 +02001053 }
Nico Huber72a9dc02021-06-17 22:47:00 +02001054 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +02001055}
1056
Stefan Taunerb3850962011-12-24 00:00:32 +00001057/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +01001058int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
1059 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +00001060{
Nico Huber519be662018-12-23 20:03:35 +01001061 ssize_t i, max_count;
1062 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +00001063
1064 if (dump == NULL || desc == NULL)
1065 return ICH_RET_PARAM;
1066
1067 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1068 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1069 pch_bug_offset = 4;
1070 else
1071 return ICH_RET_ERR;
1072 }
1073
1074 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001075 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001076 return ICH_RET_OOB;
1077 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1078 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1079 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1080 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1081
1082 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001083 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001084 return ICH_RET_OOB;
1085 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1086 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1087 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1088
Nico Huber8a03c902021-06-17 21:23:29 +02001089 /* upper map */
1090 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1091
1092 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1093 * "Identifies the 1s based number of DWORDS contained in the VSCC
1094 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1095 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1096 * check ensures that the maximum offset actually accessed is available.
1097 */
1098 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
1099 return ICH_RET_OOB;
1100
1101 for (i = 0; i < desc->upper.VTL/2; i++) {
1102 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1103 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
1104 }
1105
Nico Huber67d71792017-06-17 03:10:15 +02001106 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huber3ad9aad2021-06-17 22:05:00 +02001107 *cs = guess_ich_chipset(&desc->content, &desc->component, &desc->upper);
Nico Huber67d71792017-06-17 03:10:15 +02001108 prettyprint_ich_chipset(*cs);
1109 }
Nico Huberfa622942017-03-24 17:25:37 +01001110
Stefan Taunerb3850962011-12-24 00:00:32 +00001111 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001112 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001113 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001114 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001115 for (i = 0; i < nr; i++)
1116 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001117
1118 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001119 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001120 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001121 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001122 for (i = 0; i < nm; i++)
1123 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001124
Stefan Taunerb3850962011-12-24 00:00:32 +00001125 /* MCH/PROC (aka. North) straps */
1126 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1127 return ICH_RET_OOB;
1128
1129 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001130 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001131 for (i = 0; i < max_count; i++)
1132 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001133
1134 /* ICH/PCH (aka. South) straps */
1135 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1136 return ICH_RET_OOB;
1137
1138 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001139 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001140 for (i = 0; i < max_count; i++)
1141 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001142
1143 return ICH_RET_OK;
1144}
1145
Nico Huberad186312016-05-02 15:15:29 +02001146#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001147
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001148/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001149\em idx in bytes or -1 if the correct size can not be determined. */
1150int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001151{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001152 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001153 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001154 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001155 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001156
1157 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001158 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001159
1160 uint8_t size_enc;
1161 uint8_t size_max;
1162
1163 switch (cs) {
1164 case CHIPSET_ICH8:
1165 case CHIPSET_ICH9:
1166 case CHIPSET_ICH10:
1167 case CHIPSET_5_SERIES_IBEX_PEAK:
1168 case CHIPSET_6_SERIES_COUGAR_POINT:
1169 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001170 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001171 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001172 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001173 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001174 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001175 }
1176 size_max = 5;
1177 break;
1178 case CHIPSET_8_SERIES_LYNX_POINT:
1179 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1180 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001181 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001182 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001183 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001184 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001185 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001186 case CHIPSET_500_SERIES_TIGER_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001187 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001188 case CHIPSET_GEMINI_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001189 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001190 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001191 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001192 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001193 }
1194 size_max = 7;
1195 break;
1196 case CHIPSET_ICH_UNKNOWN:
1197 default:
1198 msg_pwarn("Density encoding is unknown on this chipset.\n");
1199 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001200 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001201
1202 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001203 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001204 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1205 idx, size_enc, size_max);
1206 return -1;
1207 }
1208
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001209 return (1 << (19 + size_enc));
1210}
1211
Nico Huber8d494992017-06-19 12:18:33 +02001212/* Only used by ichspi.c */
1213#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001214static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001215{
1216 uint32_t control = 0;
1217 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1218 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001219 switch (cs) {
1220 case CHIPSET_100_SERIES_SUNRISE_POINT:
1221 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001222 case CHIPSET_300_SERIES_CANNON_POINT:
Michał Żygowski5c9f5422021-06-16 15:13:54 +02001223 case CHIPSET_500_SERIES_TIGER_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001224 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001225 case CHIPSET_GEMINI_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001226 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1227 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001228 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001229 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1230 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1231 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001232}
1233
Nico Huberd54e4f42017-03-23 23:45:47 +01001234int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001235{
Nico Huber519be662018-12-23 20:03:35 +01001236 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001237 struct ich_desc_region *r = &desc->region;
1238
1239 /* Test if bit-fields are working as expected.
1240 * FIXME: Replace this with dynamic bitfield fixup
1241 */
1242 for (i = 0; i < 4; i++)
1243 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001244 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1245 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1246 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1247 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001248 msg_pdbg("The combination of compiler and CPU architecture used"
1249 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001250 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1251 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1252 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1253 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1254 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1255 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1256 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1257 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001258 return ICH_RET_ERR;
1259 }
1260
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001261 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001262 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001263 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1264 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1265 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1266 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001267
1268 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001269 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1270 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1271 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001272
1273 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001274 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1275 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001276 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001277 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001278 return ICH_RET_ERR;
1279 }
Nico Huberfa622942017-03-24 17:25:37 +01001280 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001281 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001282
1283 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001284 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1285 if (nm < 0) {
1286 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1287 __func__, desc->content.NM + 1);
1288 return ICH_RET_ERR;
1289 }
1290 for (i = 0; i < nm; i++)
1291 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001292
1293 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1294 * reading the upper map is impossible on all chipsets, so don't bother.
1295 */
1296
1297 msg_pdbg2(" done.\n");
1298 return ICH_RET_OK;
1299}
Nico Huber8d494992017-06-19 12:18:33 +02001300#endif
Nico Huber305f4172013-06-14 11:55:26 +02001301
1302/**
1303 * @brief Read a layout from the dump of an Intel ICH descriptor.
1304 *
1305 * @param layout Pointer where to store the layout.
1306 * @param dump The descriptor dump to read from.
1307 * @param len The length of the descriptor dump.
1308 *
1309 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001310 * 1 if the descriptor couldn't be parsed,
1311 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001312 */
1313int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1314{
Nico Huberfa622942017-03-24 17:25:37 +01001315 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001316 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1317 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001318 };
Nico Huber305f4172013-06-14 11:55:26 +02001319
1320 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001321 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1322 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001323 return 1;
1324
1325 memset(layout, 0x00, sizeof(*layout));
1326
Nico Huberfa622942017-03-24 17:25:37 +01001327 ssize_t i, j;
Nico Huber519be662018-12-23 20:03:35 +01001328 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
1329 for (i = 0, j = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001330 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001331 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001332 if (limit <= base)
1333 continue;
1334 layout->entries[j].start = base;
1335 layout->entries[j].end = limit;
1336 layout->entries[j].included = false;
Nico Huber70461a92019-06-15 14:56:19 +02001337 layout->entries[j].name = strdup(regions[i]);
1338 if (!layout->entries[j].name)
1339 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001340 ++j;
1341 }
1342 layout->base.entries = layout->entries;
1343 layout->base.num_entries = j;
1344 return 0;
1345}
1346
Nico Huberad186312016-05-02 15:15:29 +02001347#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */