blob: 63d4580aa76a60c326e0182b2f9751e42a9967ee [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:
David Hendricksa5216362017-08-08 20:02:22 -070047 return 16;
Nico Huberfa622942017-03-24 17:25:37 +010048 case CHIPSET_100_SERIES_SUNRISE_POINT:
49 return 10;
50 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
51 case CHIPSET_9_SERIES_WILDCAT_POINT:
52 case CHIPSET_8_SERIES_LYNX_POINT_LP:
53 case CHIPSET_8_SERIES_LYNX_POINT:
54 case CHIPSET_8_SERIES_WELLSBURG:
55 if (cont->NR <= 6)
56 return cont->NR + 1;
57 else
58 return -1;
59 default:
60 if (cont->NR <= 4)
61 return cont->NR + 1;
62 else
63 return -1;
64 }
65}
66
67ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
68{
David Hendricksa5216362017-08-08 20:02:22 -070069 switch (cs) {
70 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberd2d39932019-01-18 16:49:37 +010071 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +020072 case CHIPSET_GEMINI_LAKE:
David Hendricksa5216362017-08-08 20:02:22 -070073 if (cont->NM <= MAX_NUM_MASTERS)
74 return cont->NM;
Richard Hughesdb7482b2018-12-19 12:04:30 +000075 break;
David Hendricksa5216362017-08-08 20:02:22 -070076 default:
77 if (cont->NM < MAX_NUM_MASTERS)
78 return cont->NM + 1;
79 }
80
81 return -1;
Nico Huberfa622942017-03-24 17:25:37 +010082}
83
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000084void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000085{
86 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
87 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
88 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
89 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000090 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
91 if (print_vcl)
92 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
93 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000094}
95
96#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
97#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
98#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
99#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
100#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
101
Nico Huber67d71792017-06-17 03:10:15 +0200102void prettyprint_ich_chipset(enum ich_chipset cs)
103{
104 static const char *const chipset_names[] = {
105 "Unknown ICH", "ICH8", "ICH9", "ICH10",
106 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
107 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
108 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
Angel Pons4db0fdf2020-07-10 17:04:10 +0200109 "C620 series Lewisburg", "300/400 series Cannon/Comet Point",
110 "Apollo Lake", "Gemini Lake",
Nico Huber67d71792017-06-17 03:10:15 +0200111 };
112 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
113 cs = 0;
114 else
115 cs = cs - CHIPSET_ICH8 + 1;
116 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
117}
118
Stefan Tauner1e146392011-09-15 23:52:55 +0000119void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
120{
Nico Huberfa622942017-03-24 17:25:37 +0100121 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000122 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100123 prettyprint_ich_descriptor_region(cs, desc);
124 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200125#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000126 if (cs >= CHIPSET_ICH8) {
127 prettyprint_ich_descriptor_upper_map(&desc->upper);
128 prettyprint_ich_descriptor_straps(cs, desc);
129 }
Nico Huberad186312016-05-02 15:15:29 +0200130#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000131}
132
Nico Huberfa622942017-03-24 17:25:37 +0100133void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000134{
135 msg_pdbg2("=== Content Section ===\n");
136 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
137 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
138 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
139 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
140 msg_pdbg2("\n");
141
142 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100143 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
144 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
145 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
146 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
Nico Huberd2d39932019-01-18 16:49:37 +0100147 msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL);
148 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont));
Nico Huberfa622942017-03-24 17:25:37 +0100149 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
150 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
151 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
152 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000153 msg_pdbg2("\n");
154}
155
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000156static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
157{
158 if (idx > 1) {
159 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
160 return NULL;
161 }
162
163 if (desc->content.NC == 0 && idx > 0)
164 return "unused";
165
166 static const char * const size_str[] = {
167 "512 kB", /* 0000 */
168 "1 MB", /* 0001 */
169 "2 MB", /* 0010 */
170 "4 MB", /* 0011 */
171 "8 MB", /* 0100 */
172 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
173 "32 MB", /* 0110 */
174 "64 MB", /* 0111 */
175 };
176
177 switch (cs) {
178 case CHIPSET_ICH8:
179 case CHIPSET_ICH9:
180 case CHIPSET_ICH10:
181 case CHIPSET_5_SERIES_IBEX_PEAK:
182 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000183 case CHIPSET_7_SERIES_PANTHER_POINT:
184 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000185 uint8_t size_enc;
186 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000187 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000188 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000189 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000190 }
191 if (size_enc > 5)
192 return "reserved";
193 return size_str[size_enc];
194 }
195 case CHIPSET_8_SERIES_LYNX_POINT:
196 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000197 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100198 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100199 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
David Hendricksa5216362017-08-08 20:02:22 -0700200 case CHIPSET_100_SERIES_SUNRISE_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100201 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200202 case CHIPSET_300_SERIES_CANNON_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200203 case CHIPSET_APOLLO_LAKE:
204 case CHIPSET_GEMINI_LAKE: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000205 uint8_t size_enc;
206 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000207 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000208 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000209 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000210 }
211 if (size_enc > 7)
212 return "reserved";
213 return size_str[size_enc];
214 }
215 case CHIPSET_ICH_UNKNOWN:
216 default:
217 return "unknown";
218 }
219}
220
221static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000222{
Nico Huberd2d39932019-01-18 16:49:37 +0100223 static const char *const freq_str[3][8] = { {
Nico Huber129e9382019-06-06 15:43:27 +0200224 "20 MHz",
225 "33 MHz",
226 "reserved",
227 "reserved",
228 "50 MHz", /* New since Ibex Peak */
229 "reserved",
230 "reserved",
231 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100232 }, {
Nico Huber129e9382019-06-06 15:43:27 +0200233 "reserved",
234 "reserved",
235 "48 MHz",
236 "reserved",
237 "30 MHz",
238 "reserved",
239 "17 MHz",
240 "reserved"
Nico Huberd2d39932019-01-18 16:49:37 +0100241 }, {
242 "reserved",
243 "50 MHz",
244 "40 MHz",
245 "reserved",
246 "25 MHz",
247 "reserved",
248 "14 MHz / 17 MHz",
249 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100250 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000251
252 switch (cs) {
253 case CHIPSET_ICH8:
254 case CHIPSET_ICH9:
255 case CHIPSET_ICH10:
256 if (value > 1)
257 return "reserved";
Richard Hughesdb7482b2018-12-19 12:04:30 +0000258 /* Fall through. */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000259 case CHIPSET_5_SERIES_IBEX_PEAK:
260 case CHIPSET_6_SERIES_COUGAR_POINT:
261 case CHIPSET_7_SERIES_PANTHER_POINT:
262 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000263 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000264 case CHIPSET_8_SERIES_LYNX_POINT_LP:
265 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000266 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100267 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100268 return freq_str[0][value];
269 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700270 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200271 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100272 return freq_str[1][value];
Nico Huberd2d39932019-01-18 16:49:37 +0100273 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200274 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100275 return freq_str[2][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000276 case CHIPSET_ICH_UNKNOWN:
277 default:
278 return "unknown";
279 }
280}
281
282void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
283{
Nico Huberd2d39932019-01-18 16:49:37 +0100284 bool has_flill1;
285
286 switch (cs) {
287 case CHIPSET_100_SERIES_SUNRISE_POINT:
288 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200289 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100290 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200291 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100292 has_flill1 = true;
293 break;
294 default:
295 has_flill1 = false;
296 break;
297 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000298
299 msg_pdbg2("=== Component Section ===\n");
300 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
301 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberd2d39932019-01-18 16:49:37 +0100302 if (has_flill1)
Nico Huberfa622942017-03-24 17:25:37 +0100303 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000304 msg_pdbg2("\n");
305
306 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000307 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000308 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000309 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000310 else
311 msg_pdbg2("Component 2 is not used.\n");
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000312 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
313 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
314 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
315 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
316 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000317 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000318 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000319 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
320 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000321 desc->component.modes.dual_output ? "dis" : "en");
David Hendricksa5216362017-08-08 20:02:22 -0700322
323 int has_forbidden_opcode = 0;
324 if (desc->component.FLILL != 0) {
325 has_forbidden_opcode = 1;
Stefan Tauner1e146392011-09-15 23:52:55 +0000326 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
327 desc->component.invalid_instr0);
328 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
329 desc->component.invalid_instr1);
330 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
331 desc->component.invalid_instr2);
332 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
333 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700334 }
Nico Huberd2d39932019-01-18 16:49:37 +0100335 if (has_flill1) {
David Hendricksa5216362017-08-08 20:02:22 -0700336 if (desc->component.FLILL1 != 0) {
337 has_forbidden_opcode = 1;
Nico Huberfa622942017-03-24 17:25:37 +0100338 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
339 desc->component.invalid_instr4);
340 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
341 desc->component.invalid_instr5);
342 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
343 desc->component.invalid_instr6);
344 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
345 desc->component.invalid_instr7);
346 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000347 }
David Hendricksa5216362017-08-08 20:02:22 -0700348 if (!has_forbidden_opcode)
349 msg_pdbg2("No forbidden opcodes.\n");
350
Stefan Tauner1e146392011-09-15 23:52:55 +0000351 msg_pdbg2("\n");
352}
353
354static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
355{
Nico Huberfa622942017-03-24 17:25:37 +0100356 static const char *const region_names[] = {
Nico Huberd2d39932019-01-18 16:49:37 +0100357 "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown",
David Hendricksa5216362017-08-08 20:02:22 -0700358 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000359 };
Nico Huberfa622942017-03-24 17:25:37 +0100360 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000361 msg_pdbg2("%s: region index too high.\n", __func__);
362 return;
363 }
364 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
365 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100366 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000367 if (base > limit)
368 msg_pdbg2("is unused.\n");
369 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200370 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000371}
372
Nico Huberfa622942017-03-24 17:25:37 +0100373void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000374{
Nico Huber519be662018-12-23 20:03:35 +0100375 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100376 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000377 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100378 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000379 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100380 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000381 return;
382 }
Nico Huberfa622942017-03-24 17:25:37 +0100383 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100384 msg_pdbg2("FLREG%zd 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000385 msg_pdbg2("\n");
386
387 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100388 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100389 pprint_freg(&desc->region, (uint32_t)i);
Stefan Tauner1e146392011-09-15 23:52:55 +0000390 msg_pdbg2("\n");
391}
392
Nico Huberfa622942017-03-24 17:25:37 +0100393void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000394{
Nico Huber519be662018-12-23 20:03:35 +0100395 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100396 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000397 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100398 if (nm < 0) {
399 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
400 desc->content.NM + 1);
401 return;
402 }
403 for (i = 0; i < nm; i++)
Nico Huber519be662018-12-23 20:03:35 +0100404 msg_pdbg2("FLMSTR%zd 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000405 msg_pdbg2("\n");
406
407 msg_pdbg2("--- Details ---\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200408 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT ||
409 cs == CHIPSET_300_SERIES_CANNON_POINT) {
Nico Huberfa622942017-03-24 17:25:37 +0100410 const char *const master_names[] = {
411 "BIOS", "ME", "GbE", "unknown", "EC",
412 };
Nico Huber519be662018-12-23 20:03:35 +0100413 if (nm >= (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberfa622942017-03-24 17:25:37 +0100414 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
415 desc->content.NM + 1);
416 return;
417 }
418
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200419 size_t num_regions;
420 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9");
421 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
422 num_regions = 10;
423 msg_pdbg2("\n");
424 } else {
425 num_regions = 16;
426 msg_pdbg2(" RegA RegB RegC RegD RegE RegF\n");
427 }
Nico Huberfa622942017-03-24 17:25:37 +0100428 for (i = 0; i < nm; i++) {
429 size_t j;
430 msg_pdbg2("%-4s", master_names[i]);
Nico Huber961f4a12019-10-04 17:34:22 +0200431 for (j = 0; j < (size_t)min(num_regions, 12); j++)
Nico Huberfa622942017-03-24 17:25:37 +0100432 msg_pdbg2(" %c%c ",
433 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
434 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200435 for (; j < num_regions; j++)
436 msg_pdbg2(" %c%c ",
437 desc->master.mstr[i].ext_read & (1 << (j - 12)) ? 'r' : ' ',
438 desc->master.mstr[i].ext_write & (1 << (j - 12)) ? 'w' : ' ');
Nico Huberfa622942017-03-24 17:25:37 +0100439 msg_pdbg2("\n");
440 }
David Hendricksa5216362017-08-08 20:02:22 -0700441 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
442 const char *const master_names[] = {
443 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
444 };
445 /* NM starts at 1 instead of 0 for LBG */
Nico Huber519be662018-12-23 20:03:35 +0100446 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
David Hendricksa5216362017-08-08 20:02:22 -0700447 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
448 desc->content.NM);
449 return;
450 }
451
452 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
453 " ", /* width of master name (4 chars minimum) */
454 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
455 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
456 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
457 "Reg15");
458 for (i = 0; i < nm; i++) {
459 size_t j;
460 msg_pdbg2("%-4s", master_names[i]);
461 for (j = 0; j < 16; j++)
462 msg_pdbg2(" %c%c ",
463 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
464 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
465 msg_pdbg2("\n");
466 }
Angel Pons4db0fdf2020-07-10 17:04:10 +0200467 } else if (cs == CHIPSET_APOLLO_LAKE || cs == CHIPSET_GEMINI_LAKE) {
Nico Huberd2d39932019-01-18 16:49:37 +0100468 const char *const master_names[] = { "BIOS", "TXE", };
Nico Huber519be662018-12-23 20:03:35 +0100469 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberd2d39932019-01-18 16:49:37 +0100470 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
471 return;
472 }
473
474 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
475 for (i = 0; i < nm; i++) {
Nico Huber519be662018-12-23 20:03:35 +0100476 ssize_t j;
Nico Huberd2d39932019-01-18 16:49:37 +0100477 msg_pdbg2("%-4s", master_names[i]);
478 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
479 msg_pdbg2(" %c%c ",
480 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
481 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
482 msg_pdbg2("\n");
483 }
Nico Huberfa622942017-03-24 17:25:37 +0100484 } else {
485 const struct ich_desc_master *const mstr = &desc->master;
486 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
487 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
488 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
489 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
490 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
491 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
492 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
493 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
494 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
495 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
496 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
497 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
498 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
499 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
500 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
501 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
502 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
503 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
504 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
505 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000506 msg_pdbg2("\n");
507}
508
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600509static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000510{
511 static const char * const str_GPIO12[4] = {
512 "GPIO12",
513 "LAN PHY Power Control Function (Native Output)",
514 "GLAN_DOCK# (Native Input)",
515 "invalid configuration",
516 };
517
518 msg_pdbg2("--- MCH details ---\n");
519 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
520 msg_pdbg2("\n");
521
522 msg_pdbg2("--- ICH details ---\n");
523 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
524 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
525 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
526 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
527 msg_pdbg2("SPI CS1 is used for %s.\n",
528 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
529 "LAN PHY Power Control Function" :
530 "SPI Chip Select");
531 msg_pdbg2("GPIO12 is used as %s.\n",
532 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
533 msg_pdbg2("PCIe Port 6 is used for %s.\n",
534 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
535 msg_pdbg2("%sn BMC Mode: "
536 "Intel AMT SMBus Controller 1 is connected to %s.\n",
537 desc->south.ich8.BMCMODE ? "I" : "Not i",
538 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
539 msg_pdbg2("TCO is in %s Mode.\n",
540 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
541 msg_pdbg2("ME A is %sabled.\n",
542 desc->south.ich8.ME_DISABLE ? "dis" : "en");
543 msg_pdbg2("\n");
544}
545
546static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
547{
548 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
549
550 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000551 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000552 case 0:
553 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
554 break;
555 case 1:
556 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
557 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
558 break;
559 case 2:
560 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
561 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
562 break;
563 case 3:
564 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
565 1+off, 2+off, 4+off);
566 break;
567 }
568 msg_pdbg2("\n");
569}
570
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600571static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000572{
573 /* PCHSTRP4 */
574 msg_pdbg2("Intel PHY is %s.\n",
575 (s->ibex.PHYCON == 2) ? "connected" :
576 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
577 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
578 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
579 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
580 s->ibex.GBEMAC_SMBUS_ADDR);
581 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
582 s->ibex.GBEPHY_SMBUS_ADDR);
583
584 /* PCHSTRP5 */
585 /* PCHSTRP6 */
586 /* PCHSTRP7 */
587 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
588 s->ibex.MESMA2UDID_VENDOR);
589 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
590 s->ibex.MESMA2UDID_VENDOR);
591
592 /* PCHSTRP8 */
593}
594
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600595static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000596{
597 /* PCHSTRP11 */
598 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
599 s->ibex.SML1GPAEN ? "en" : "dis");
600 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
601 s->ibex.SML1GPA);
602 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
603 s->ibex.SML1I2CAEN ? "en" : "dis");
604 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
605 s->ibex.SML1I2CA);
606
607 /* PCHSTRP12 */
608 /* PCHSTRP13 */
609}
610
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600611static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000612{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000613 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000614 100,
615 50,
616 5,
617 1
618 };
619
620 msg_pdbg2("--- PCH ---\n");
621
622 /* PCHSTRP0 */
623 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
624 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
625 s->ibex.SMB_EN ? "en" : "dis");
626 msg_pdbg2("SMLink0 segment is %sabled.\n",
627 s->ibex.SML0_EN ? "en" : "dis");
628 msg_pdbg2("SMLink1 segment is %sabled.\n",
629 s->ibex.SML1_EN ? "en" : "dis");
630 msg_pdbg2("SMLink1 Frequency: %s\n",
631 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
632 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
633 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
634 msg_pdbg2("SMLink0 Frequency: %s\n",
635 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
636 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
637 "LAN_PHY_PWR_CTRL" : "general purpose output");
638 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
639 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
640 s->ibex.DMI_REQID_DIS ? "en" : "dis");
641 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
642 1 << (6 + s->ibex.BBBS));
643
644 /* PCHSTRP1 */
645 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
646
647 /* PCHSTRP2 */
648 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
649 s->ibex.MESMASDEN ? "en" : "dis");
650 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
651 s->ibex.MESMASDA);
652 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
653 s->ibex.MESMI2CEN ? "en" : "dis");
654 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
655 s->ibex.MESMI2CA);
656
657 /* PCHSTRP3 */
658 prettyprint_ich_descriptor_pchstraps45678_56(s);
659 /* PCHSTRP9 */
660 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
661 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
662 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
663 s->ibex.PCIELR1 ? "" : "not ");
664 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
665 s->ibex.PCIELR2 ? "" : "not ");
666 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
667 s->ibex.DMILR ? "" : "not ");
668 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
669 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
670 s->ibex.PHY_PCIE_EN ? "en" : "dis");
671
672 /* PCHSTRP10 */
673 msg_pdbg2("Management Engine will boot from %sflash.\n",
674 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
675 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
676 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
677 s->ibex.VE_EN ? "en" : "dis");
678 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
679 s->ibex.MMDDE ? "en" : "dis");
680 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
681 s->ibex.MMADDR);
682 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
683 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
684 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
685 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
686 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
687
688 prettyprint_ich_descriptor_pchstraps111213_56(s);
689
690 /* PCHSTRP14 */
691 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
692 s->ibex.VE_EN2 ? "en" : "dis");
693 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
694 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
695 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
696 s->ibex.BW_SSD ? "en" : "dis");
697 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
698 s->ibex.NVMHCI_EN ? "en" : "dis");
699
700 /* PCHSTRP15 */
701 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
702 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
703 s->ibex.IWL_EN ? "en" : "dis");
704 msg_pdbg2("t209 min Timing: %d ms\n",
705 dec_t209min[s->ibex.t209min]);
706 msg_pdbg2("\n");
707}
708
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600709static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000710{
711 msg_pdbg2("--- PCH ---\n");
712
713 /* PCHSTRP0 */
714 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
715 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
716 s->ibex.SMB_EN ? "en" : "dis");
717 msg_pdbg2("SMLink0 segment is %sabled.\n",
718 s->ibex.SML0_EN ? "en" : "dis");
719 msg_pdbg2("SMLink1 segment is %sabled.\n",
720 s->ibex.SML1_EN ? "en" : "dis");
721 msg_pdbg2("SMLink1 Frequency: %s\n",
722 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
723 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
724 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
725 msg_pdbg2("SMLink0 Frequency: %s\n",
726 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
727 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
728 "LAN_PHY_PWR_CTRL" : "general purpose output");
729 msg_pdbg2("LinkSec is %sabled.\n",
730 s->cougar.LINKSEC_DIS ? "en" : "dis");
731 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
732 s->ibex.DMI_REQID_DIS ? "en" : "dis");
733 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
734 1 << (6 + s->ibex.BBBS));
735
736 /* PCHSTRP1 */
737 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
738 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
739
740 /* PCHSTRP2 */
741 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
742 s->ibex.MESMASDEN ? "en" : "dis");
743 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
744 s->ibex.MESMASDA);
745 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
746 s->cougar.MESMMCTPAEN ? "en" : "dis");
747 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
748 s->cougar.MESMMCTPA);
749 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
750 s->ibex.MESMI2CEN ? "en" : "dis");
751 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
752 s->ibex.MESMI2CA);
753
754 /* PCHSTRP3 */
755 prettyprint_ich_descriptor_pchstraps45678_56(s);
756 /* PCHSTRP9 */
757 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
758 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
759 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
760 s->ibex.PCIELR1 ? "" : "not ");
761 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
762 s->ibex.PCIELR2 ? "" : "not ");
763 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
764 s->ibex.DMILR ? "" : "not ");
765 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
766 s->cougar.MDSMBE_EN ? "en" : "dis");
767 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
768 s->cougar.MDSMBE_ADD);
769 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
770 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
771 s->ibex.PHY_PCIE_EN ? "en" : "dis");
772 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
773 s->cougar.SUB_DECODE_EN ? "en" : "dis");
774 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
775 "PCHHOT#" : "SML1ALERT#");
776
777 /* PCHSTRP10 */
778 msg_pdbg2("Management Engine will boot from %sflash.\n",
779 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
780
781 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
782 s->cougar.MDSMBE_EN ? "en" : "dis");
783 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
784 s->cougar.MDSMBE_ADD);
785
786 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
787 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000788 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
789 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000790 msg_pdbg2("ICC Profile is selected by %s.\n",
791 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
792 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
793 s->cougar.Deep_SX_EN ? "not " : "");
794 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
795 s->cougar.ME_DBG_LAN ? "en" : "dis");
796
797 prettyprint_ich_descriptor_pchstraps111213_56(s);
798
799 /* PCHSTRP14 */
800 /* PCHSTRP15 */
801 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
802 msg_pdbg2("Integrated wired LAN is %sabled.\n",
803 s->cougar.IWL_EN ? "en" : "dis");
804 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
805 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000806 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000807 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
808 "general purpose output" : "SLP_LAN#");
809
810 /* PCHSTRP16 */
811 /* PCHSTRP17 */
812 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
813 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
814 msg_pdbg2("\n");
815}
816
817void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
818{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000819 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000820 msg_pdbg2("=== Softstraps ===\n");
821
Nico Huber519be662018-12-23 20:03:35 +0100822 max_count = MIN(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
Nico Huberd7c75522017-03-29 16:31:49 +0200823 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000824 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200825 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000826 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200827 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000828
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000829 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
830 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000831 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
832 msg_pdbg2("\n");
833
Nico Huber519be662018-12-23 20:03:35 +0100834 max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
Nico Huberd7c75522017-03-29 16:31:49 +0200835 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000836 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
837 desc->content.ISL, max_count);
838 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200839 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000840
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000841 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
842 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000843 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
844 msg_pdbg2("\n");
845
846 switch (cs) {
847 case CHIPSET_ICH8:
848 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
849 msg_pdbg2("Detailed North/MCH/PROC information is "
850 "probably not reliable, printing anyway.\n");
851 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
852 msg_pdbg2("Detailed South/ICH/PCH information is "
853 "probably not reliable, printing anyway.\n");
854 prettyprint_ich_descriptor_straps_ich8(desc);
855 break;
856 case CHIPSET_5_SERIES_IBEX_PEAK:
857 /* PCH straps only. PROCSTRPs are unknown. */
858 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
859 msg_pdbg2("Detailed South/ICH/PCH information is "
860 "probably not reliable, printing anyway.\n");
861 prettyprint_ich_descriptor_straps_ibex(&desc->south);
862 break;
863 case CHIPSET_6_SERIES_COUGAR_POINT:
864 /* PCH straps only. PROCSTRP0 is "reserved". */
865 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
866 msg_pdbg2("Detailed South/ICH/PCH information is "
867 "probably not reliable, printing anyway.\n");
868 prettyprint_ich_descriptor_straps_cougar(&desc->south);
869 break;
870 case CHIPSET_ICH_UNKNOWN:
871 break;
872 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000873 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000874 break;
875 }
876}
877
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600878static void prettyprint_rdid(uint32_t reg_val)
Stefan Taunerb3850962011-12-24 00:00:32 +0000879{
880 uint8_t mid = reg_val & 0xFF;
881 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
882 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
883}
884
885void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
886{
887 int i;
888 msg_pdbg2("=== Upper Map Section ===\n");
889 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
890 msg_pdbg2("\n");
891
892 msg_pdbg2("--- Details ---\n");
893 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
894 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
895 msg_pdbg2("\n");
896
897 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000898 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000899 uint32_t jid = umap->vscc_table[i].JID;
900 uint32_t vscc = umap->vscc_table[i].VSCC;
901 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
902 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
903 msg_pdbg2(" "); /* indention */
904 prettyprint_rdid(jid);
905 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000906 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000907 }
908 msg_pdbg2("\n");
909}
910
David Hendricks66565a72021-09-20 21:56:40 -0700911static inline void warn_peculiar_desc(const char *const name)
Nico Huber964007a2021-06-17 21:12:47 +0200912{
Nico Huber964007a2021-06-17 21:12:47 +0200913 msg_pwarn("Peculiar flash descriptor, assuming %s compatibility.\n", name);
914}
915
Nico Huber1dc3d422017-06-17 00:09:31 +0200916/*
917 * Guesses a minimum chipset version based on the maximum number of
Nico Huber3ad9aad2021-06-17 22:05:00 +0200918 * soft straps per generation and presence of the MIP base (MDTBA).
Nico Huber1dc3d422017-06-17 00:09:31 +0200919 */
Nico Huber3ad9aad2021-06-17 22:05:00 +0200920static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content,
921 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +0200922{
923 if (content->ICCRIBA == 0x00) {
924 if (content->MSL == 0 && content->ISL <= 2)
925 return CHIPSET_ICH8;
Nico Huber83b01c82021-06-17 21:20:09 +0200926 if (content->ISL <= 2)
Nico Huber1dc3d422017-06-17 00:09:31 +0200927 return CHIPSET_ICH9;
Nico Huber83b01c82021-06-17 21:20:09 +0200928 if (content->ISL <= 10)
Nico Huber1dc3d422017-06-17 00:09:31 +0200929 return CHIPSET_ICH10;
David Hendricks66565a72021-09-20 21:56:40 -0700930 if (content->ISL <= 16)
931 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber83b01c82021-06-17 21:20:09 +0200932 if (content->FLMAP2 == 0) {
Nico Huber81965f32021-06-17 23:25:35 +0200933 if (content->ISL == 19)
934 return CHIPSET_APOLLO_LAKE;
David Hendricks66565a72021-09-20 21:56:40 -0700935 if (content->ISL == 23)
936 return CHIPSET_GEMINI_LAKE;
937 warn_peculiar_desc("Gemini Lake");
Nico Huber81965f32021-06-17 23:25:35 +0200938 return CHIPSET_GEMINI_LAKE;
Nico Huberd2d39932019-01-18 16:49:37 +0100939 }
Jonathan Zhang3bf7cfb2021-08-30 23:25:06 -0700940 if (content->ISL <= 80)
941 return CHIPSET_C620_SERIES_LEWISBURG;
David Hendricks66565a72021-09-20 21:56:40 -0700942 warn_peculiar_desc("Ibex Peak");
Nico Huber1dc3d422017-06-17 00:09:31 +0200943 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber3ad9aad2021-06-17 22:05:00 +0200944 } else if (upper->MDTBA == 0x00) {
945 if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
946 if (content->MSL == 0 && content->ISL <= 17)
947 return CHIPSET_BAYTRAIL;
948 if (content->MSL <= 1 && content->ISL <= 18)
949 return CHIPSET_6_SERIES_COUGAR_POINT;
David Hendricks66565a72021-09-20 21:56:40 -0700950 if (content->MSL <= 1 && content->ISL <= 21)
951 return CHIPSET_8_SERIES_LYNX_POINT;
952 warn_peculiar_desc("Lynx Point");
Nico Huber81965f32021-06-17 23:25:35 +0200953 return CHIPSET_8_SERIES_LYNX_POINT;
Nico Huber3ad9aad2021-06-17 22:05:00 +0200954 }
955 if (content->NM == 6) {
David Hendricks66565a72021-09-20 21:56:40 -0700956 if (content->ICCRIBA <= 0x34)
957 return CHIPSET_C620_SERIES_LEWISBURG;
958 warn_peculiar_desc("C620 series");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200959 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber3ad9aad2021-06-17 22:05:00 +0200960 }
David Hendricks66565a72021-09-20 21:56:40 -0700961 if (content->ICCRIBA == 0x31)
962 return CHIPSET_100_SERIES_SUNRISE_POINT;
963 warn_peculiar_desc("100 series");
Nico Huber83b01c82021-06-17 21:20:09 +0200964 return CHIPSET_100_SERIES_SUNRISE_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200965 } else {
David Hendricks66565a72021-09-20 21:56:40 -0700966 if (content->ICCRIBA == 0x34)
967 return CHIPSET_300_SERIES_CANNON_POINT;
968 msg_pwarn("Unknown flash descriptor, assuming 300 series compatibility.\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200969 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200970 }
971}
972
973/*
974 * As an additional measure, we check the read frequency like `ifdtool`.
975 * The frequency value 6 (17MHz) was reserved before Skylake and is the
976 * only valid value since. Skylake is currently the most important dis-
977 * tinction because of the dropped number of regions field (NR).
978 */
Nico Huberfa622942017-03-24 17:25:37 +0100979static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
Nico Huber3ad9aad2021-06-17 22:05:00 +0200980 const struct ich_desc_component *const component,
981 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +0200982{
Nico Huber3ad9aad2021-06-17 22:05:00 +0200983 const enum ich_chipset guess = guess_ich_chipset_from_content(content, upper);
Nico Huber1dc3d422017-06-17 00:09:31 +0200984
Nico Huberd2d39932019-01-18 16:49:37 +0100985 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200986 case CHIPSET_300_SERIES_CANNON_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200987 case CHIPSET_GEMINI_LAKE:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200988 /* `freq_read` was repurposed, so can't check on it any more. */
Nico Huber72a9dc02021-06-17 22:47:00 +0200989 break;
Nico Huberd2d39932019-01-18 16:49:37 +0100990 case CHIPSET_100_SERIES_SUNRISE_POINT:
991 case CHIPSET_C620_SERIES_LEWISBURG:
992 case CHIPSET_APOLLO_LAKE:
993 if (component->modes.freq_read != 6) {
Nico Huber964007a2021-06-17 21:12:47 +0200994 msg_pwarn("\nThe flash descriptor looks like a Skylake/Sunrise Point descriptor.\n"
Nico Huberd2d39932019-01-18 16:49:37 +0100995 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
996 "Please report this message, the output of `ich_descriptors_tool` for\n"
997 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
Nico Huberd2d39932019-01-18 16:49:37 +0100998 }
Nico Huber72a9dc02021-06-17 22:47:00 +0200999 break;
Nico Huberd2d39932019-01-18 16:49:37 +01001000 default:
1001 if (component->modes.freq_read == 6) {
Nico Huber964007a2021-06-17 21:12:47 +02001002 msg_pwarn("\nThe flash descriptor has the read frequency set to 17MHz. However,\n"
Nico Huber1dc3d422017-06-17 00:09:31 +02001003 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
1004 "Please report this message, the output of `ich_descriptors_tool` for\n"
1005 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -07001006 }
Nico Huber1dc3d422017-06-17 00:09:31 +02001007 }
Nico Huber72a9dc02021-06-17 22:47:00 +02001008 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +02001009}
1010
Stefan Taunerb3850962011-12-24 00:00:32 +00001011/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +01001012int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
1013 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +00001014{
Nico Huber519be662018-12-23 20:03:35 +01001015 ssize_t i, max_count;
1016 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +00001017
1018 if (dump == NULL || desc == NULL)
1019 return ICH_RET_PARAM;
1020
1021 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1022 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1023 pch_bug_offset = 4;
1024 else
1025 return ICH_RET_ERR;
1026 }
1027
1028 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001029 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001030 return ICH_RET_OOB;
1031 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1032 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1033 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1034 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1035
1036 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001037 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001038 return ICH_RET_OOB;
1039 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1040 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1041 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1042
Nico Huber8a03c902021-06-17 21:23:29 +02001043 /* upper map */
1044 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1045
1046 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1047 * "Identifies the 1s based number of DWORDS contained in the VSCC
1048 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1049 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1050 * check ensures that the maximum offset actually accessed is available.
1051 */
1052 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
1053 return ICH_RET_OOB;
1054
1055 for (i = 0; i < desc->upper.VTL/2; i++) {
1056 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1057 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
1058 }
1059
Nico Huber67d71792017-06-17 03:10:15 +02001060 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huber3ad9aad2021-06-17 22:05:00 +02001061 *cs = guess_ich_chipset(&desc->content, &desc->component, &desc->upper);
Nico Huber67d71792017-06-17 03:10:15 +02001062 prettyprint_ich_chipset(*cs);
1063 }
Nico Huberfa622942017-03-24 17:25:37 +01001064
Stefan Taunerb3850962011-12-24 00:00:32 +00001065 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001066 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001067 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001068 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001069 for (i = 0; i < nr; i++)
1070 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001071
1072 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001073 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001074 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001075 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001076 for (i = 0; i < nm; i++)
1077 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001078
Stefan Taunerb3850962011-12-24 00:00:32 +00001079 /* MCH/PROC (aka. North) straps */
1080 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1081 return ICH_RET_OOB;
1082
1083 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001084 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001085 for (i = 0; i < max_count; i++)
1086 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001087
1088 /* ICH/PCH (aka. South) straps */
1089 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1090 return ICH_RET_OOB;
1091
1092 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001093 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001094 for (i = 0; i < max_count; i++)
1095 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001096
1097 return ICH_RET_OK;
1098}
1099
Nico Huberad186312016-05-02 15:15:29 +02001100#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001101
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001102/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001103\em idx in bytes or -1 if the correct size can not be determined. */
1104int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001105{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001106 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001107 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001108 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001109 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001110
1111 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001112 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001113
1114 uint8_t size_enc;
1115 uint8_t size_max;
1116
1117 switch (cs) {
1118 case CHIPSET_ICH8:
1119 case CHIPSET_ICH9:
1120 case CHIPSET_ICH10:
1121 case CHIPSET_5_SERIES_IBEX_PEAK:
1122 case CHIPSET_6_SERIES_COUGAR_POINT:
1123 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001124 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001125 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001126 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001127 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001128 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001129 }
1130 size_max = 5;
1131 break;
1132 case CHIPSET_8_SERIES_LYNX_POINT:
1133 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1134 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001135 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001136 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001137 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001138 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001139 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001140 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001141 case CHIPSET_GEMINI_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001142 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001143 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001144 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001145 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001146 }
1147 size_max = 7;
1148 break;
1149 case CHIPSET_ICH_UNKNOWN:
1150 default:
1151 msg_pwarn("Density encoding is unknown on this chipset.\n");
1152 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001153 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001154
1155 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001156 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001157 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1158 idx, size_enc, size_max);
1159 return -1;
1160 }
1161
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001162 return (1 << (19 + size_enc));
1163}
1164
Nico Huber8d494992017-06-19 12:18:33 +02001165/* Only used by ichspi.c */
1166#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001167static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001168{
1169 uint32_t control = 0;
1170 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1171 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001172 switch (cs) {
1173 case CHIPSET_100_SERIES_SUNRISE_POINT:
1174 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001175 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001176 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001177 case CHIPSET_GEMINI_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001178 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1179 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001180 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001181 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1182 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1183 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001184}
1185
Nico Huberd54e4f42017-03-23 23:45:47 +01001186int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001187{
Nico Huber519be662018-12-23 20:03:35 +01001188 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001189 struct ich_desc_region *r = &desc->region;
1190
1191 /* Test if bit-fields are working as expected.
1192 * FIXME: Replace this with dynamic bitfield fixup
1193 */
1194 for (i = 0; i < 4; i++)
1195 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001196 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1197 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1198 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1199 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001200 msg_pdbg("The combination of compiler and CPU architecture used"
1201 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001202 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1203 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1204 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1205 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1206 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1207 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1208 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1209 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001210 return ICH_RET_ERR;
1211 }
1212
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001213 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001214 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001215 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1216 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1217 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1218 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001219
1220 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001221 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1222 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1223 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001224
1225 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001226 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1227 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001228 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001229 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001230 return ICH_RET_ERR;
1231 }
Nico Huberfa622942017-03-24 17:25:37 +01001232 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001233 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001234
1235 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001236 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1237 if (nm < 0) {
1238 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1239 __func__, desc->content.NM + 1);
1240 return ICH_RET_ERR;
1241 }
1242 for (i = 0; i < nm; i++)
1243 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001244
1245 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1246 * reading the upper map is impossible on all chipsets, so don't bother.
1247 */
1248
1249 msg_pdbg2(" done.\n");
1250 return ICH_RET_OK;
1251}
Nico Huber8d494992017-06-19 12:18:33 +02001252#endif
Nico Huber305f4172013-06-14 11:55:26 +02001253
1254/**
1255 * @brief Read a layout from the dump of an Intel ICH descriptor.
1256 *
1257 * @param layout Pointer where to store the layout.
1258 * @param dump The descriptor dump to read from.
1259 * @param len The length of the descriptor dump.
1260 *
1261 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001262 * 1 if the descriptor couldn't be parsed,
1263 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001264 */
1265int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1266{
Nico Huberfa622942017-03-24 17:25:37 +01001267 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001268 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1269 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001270 };
Nico Huber305f4172013-06-14 11:55:26 +02001271
1272 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001273 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1274 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001275 return 1;
1276
1277 memset(layout, 0x00, sizeof(*layout));
1278
Nico Huberfa622942017-03-24 17:25:37 +01001279 ssize_t i, j;
Nico Huber519be662018-12-23 20:03:35 +01001280 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
1281 for (i = 0, j = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001282 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001283 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001284 if (limit <= base)
1285 continue;
1286 layout->entries[j].start = base;
1287 layout->entries[j].end = limit;
1288 layout->entries[j].included = false;
Nico Huber70461a92019-06-15 14:56:19 +02001289 layout->entries[j].name = strdup(regions[i]);
1290 if (!layout->entries[j].name)
1291 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001292 ++j;
1293 }
1294 layout->base.entries = layout->entries;
1295 layout->base.num_entries = j;
1296 return 0;
1297}
1298
Nico Huberad186312016-05-02 15:15:29 +02001299#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */