blob: a6ac88146154e3b24138ec7d63ab72ee9a4f3025 [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"
Stefan Taunerb3850962011-12-24 00:00:32 +000019
Nico Huberad186312016-05-02 15:15:29 +020020#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +000021#include <stdio.h>
Nico Huber305f4172013-06-14 11:55:26 +020022#include <string.h>
Stefan Taunerb3850962011-12-24 00:00:32 +000023#define print(t, ...) printf(__VA_ARGS__)
Nico Huberad186312016-05-02 15:15:29 +020024#endif
25
Stefan Taunerb3850962011-12-24 00:00:32 +000026#define DESCRIPTOR_MODE_SIGNATURE 0x0ff0a55a
27/* The upper map is located in the word before the 256B-long OEM section at the
28 * end of the 4kB-long flash descriptor.
29 */
30#define UPPER_MAP_OFFSET (4096 - 256 - 4)
31#define getVTBA(flumap) (((flumap)->FLUMAP1 << 4) & 0x00000ff0)
32
Nico Huber4d440a72017-08-15 11:26:48 +020033#include <sys/types.h>
Nico Huberad186312016-05-02 15:15:29 +020034#include <string.h>
Stefan Tauner1e146392011-09-15 23:52:55 +000035#include "flash.h" /* for msg_* */
36#include "programmer.h"
37
Nico Huberfa622942017-03-24 17:25:37 +010038ssize_t ich_number_of_regions(const enum ich_chipset cs, const struct ich_desc_content *const cont)
39{
40 switch (cs) {
Nico Huberd2d39932019-01-18 16:49:37 +010041 case CHIPSET_APOLLO_LAKE:
Angel Pons11a35982020-07-10 17:04:10 +020042 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +010043 return 6;
David Hendricksa5216362017-08-08 20:02:22 -070044 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +020045 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -050046 case CHIPSET_400_SERIES_COMET_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 Pons11a35982020-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 Pons59e344e2021-05-17 19:08:32 +0200109 "C620 series Lewisburg", "300 series Cannon Point", "400 series 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:
Matt DeVillierb1f858f2020-08-12 12:48:06 -0500203 case CHIPSET_400_SERIES_COMET_POINT:
Angel Pons11a35982020-07-10 17:04:10 +0200204 case CHIPSET_APOLLO_LAKE:
205 case CHIPSET_GEMINI_LAKE: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000206 uint8_t size_enc;
207 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000208 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000209 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000210 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000211 }
212 if (size_enc > 7)
213 return "reserved";
214 return size_str[size_enc];
215 }
216 case CHIPSET_ICH_UNKNOWN:
217 default:
218 return "unknown";
219 }
220}
221
222static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000223{
Nico Huberd2d39932019-01-18 16:49:37 +0100224 static const char *const freq_str[3][8] = { {
Nico Huber129e9382019-06-06 15:43:27 +0200225 "20 MHz",
226 "33 MHz",
227 "reserved",
228 "reserved",
229 "50 MHz", /* New since Ibex Peak */
230 "reserved",
231 "reserved",
232 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100233 }, {
Nico Huber129e9382019-06-06 15:43:27 +0200234 "reserved",
235 "reserved",
236 "48 MHz",
237 "reserved",
238 "30 MHz",
239 "reserved",
240 "17 MHz",
241 "reserved"
Nico Huberd2d39932019-01-18 16:49:37 +0100242 }, {
243 "reserved",
244 "50 MHz",
245 "40 MHz",
246 "reserved",
247 "25 MHz",
248 "reserved",
249 "14 MHz / 17 MHz",
250 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100251 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000252
253 switch (cs) {
254 case CHIPSET_ICH8:
255 case CHIPSET_ICH9:
256 case CHIPSET_ICH10:
257 if (value > 1)
258 return "reserved";
Richard Hughesdb7482b2018-12-19 12:04:30 +0000259 /* Fall through. */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000260 case CHIPSET_5_SERIES_IBEX_PEAK:
261 case CHIPSET_6_SERIES_COUGAR_POINT:
262 case CHIPSET_7_SERIES_PANTHER_POINT:
263 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000264 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000265 case CHIPSET_8_SERIES_LYNX_POINT_LP:
266 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000267 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100268 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100269 return freq_str[0][value];
270 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700271 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200272 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -0500273 case CHIPSET_400_SERIES_COMET_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100274 return freq_str[1][value];
Nico Huberd2d39932019-01-18 16:49:37 +0100275 case CHIPSET_APOLLO_LAKE:
Angel Pons11a35982020-07-10 17:04:10 +0200276 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100277 return freq_str[2][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000278 case CHIPSET_ICH_UNKNOWN:
279 default:
280 return "unknown";
281 }
282}
283
284void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
285{
Nico Huberd2d39932019-01-18 16:49:37 +0100286 bool has_flill1;
287
288 switch (cs) {
289 case CHIPSET_100_SERIES_SUNRISE_POINT:
290 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200291 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -0500292 case CHIPSET_400_SERIES_COMET_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100293 case CHIPSET_APOLLO_LAKE:
Angel Pons11a35982020-07-10 17:04:10 +0200294 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100295 has_flill1 = true;
296 break;
297 default:
298 has_flill1 = false;
299 break;
300 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000301
302 msg_pdbg2("=== Component Section ===\n");
303 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
304 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberd2d39932019-01-18 16:49:37 +0100305 if (has_flill1)
Nico Huberfa622942017-03-24 17:25:37 +0100306 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000307 msg_pdbg2("\n");
308
309 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000310 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000311 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000312 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000313 else
314 msg_pdbg2("Component 2 is not used.\n");
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000315 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
316 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
317 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
318 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
319 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000320 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000321 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000322 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
323 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000324 desc->component.modes.dual_output ? "dis" : "en");
David Hendricksa5216362017-08-08 20:02:22 -0700325
326 int has_forbidden_opcode = 0;
327 if (desc->component.FLILL != 0) {
328 has_forbidden_opcode = 1;
Stefan Tauner1e146392011-09-15 23:52:55 +0000329 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
330 desc->component.invalid_instr0);
331 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
332 desc->component.invalid_instr1);
333 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
334 desc->component.invalid_instr2);
335 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
336 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700337 }
Nico Huberd2d39932019-01-18 16:49:37 +0100338 if (has_flill1) {
David Hendricksa5216362017-08-08 20:02:22 -0700339 if (desc->component.FLILL1 != 0) {
340 has_forbidden_opcode = 1;
Nico Huberfa622942017-03-24 17:25:37 +0100341 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
342 desc->component.invalid_instr4);
343 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
344 desc->component.invalid_instr5);
345 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
346 desc->component.invalid_instr6);
347 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
348 desc->component.invalid_instr7);
349 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000350 }
David Hendricksa5216362017-08-08 20:02:22 -0700351 if (!has_forbidden_opcode)
352 msg_pdbg2("No forbidden opcodes.\n");
353
Stefan Tauner1e146392011-09-15 23:52:55 +0000354 msg_pdbg2("\n");
355}
356
357static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
358{
Nico Huberfa622942017-03-24 17:25:37 +0100359 static const char *const region_names[] = {
Nico Huberd2d39932019-01-18 16:49:37 +0100360 "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown",
David Hendricksa5216362017-08-08 20:02:22 -0700361 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000362 };
Nico Huberfa622942017-03-24 17:25:37 +0100363 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000364 msg_pdbg2("%s: region index too high.\n", __func__);
365 return;
366 }
367 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
368 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100369 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000370 if (base > limit)
371 msg_pdbg2("is unused.\n");
372 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200373 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000374}
375
Nico Huberfa622942017-03-24 17:25:37 +0100376void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000377{
Nico Huber519be662018-12-23 20:03:35 +0100378 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100379 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000380 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100381 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000382 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100383 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000384 return;
385 }
Nico Huberfa622942017-03-24 17:25:37 +0100386 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100387 msg_pdbg2("FLREG%zd 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000388 msg_pdbg2("\n");
389
390 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100391 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100392 pprint_freg(&desc->region, (uint32_t)i);
Stefan Tauner1e146392011-09-15 23:52:55 +0000393 msg_pdbg2("\n");
394}
395
Nico Huberfa622942017-03-24 17:25:37 +0100396void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000397{
Nico Huber519be662018-12-23 20:03:35 +0100398 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100399 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000400 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100401 if (nm < 0) {
402 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
403 desc->content.NM + 1);
404 return;
405 }
406 for (i = 0; i < nm; i++)
Nico Huber519be662018-12-23 20:03:35 +0100407 msg_pdbg2("FLMSTR%zd 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000408 msg_pdbg2("\n");
409
410 msg_pdbg2("--- Details ---\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200411 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT ||
Matt DeVillierb1f858f2020-08-12 12:48:06 -0500412 cs == CHIPSET_300_SERIES_CANNON_POINT ||
413 cs == CHIPSET_400_SERIES_COMET_POINT) {
Nico Huberfa622942017-03-24 17:25:37 +0100414 const char *const master_names[] = {
415 "BIOS", "ME", "GbE", "unknown", "EC",
416 };
Nico Huber519be662018-12-23 20:03:35 +0100417 if (nm >= (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberfa622942017-03-24 17:25:37 +0100418 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
419 desc->content.NM + 1);
420 return;
421 }
422
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200423 size_t num_regions;
424 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9");
425 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
426 num_regions = 10;
427 msg_pdbg2("\n");
428 } else {
429 num_regions = 16;
430 msg_pdbg2(" RegA RegB RegC RegD RegE RegF\n");
431 }
Nico Huberfa622942017-03-24 17:25:37 +0100432 for (i = 0; i < nm; i++) {
433 size_t j;
434 msg_pdbg2("%-4s", master_names[i]);
Nico Huber961f4a12019-10-04 17:34:22 +0200435 for (j = 0; j < (size_t)min(num_regions, 12); j++)
Nico Huberfa622942017-03-24 17:25:37 +0100436 msg_pdbg2(" %c%c ",
437 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
438 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200439 for (; j < num_regions; j++)
440 msg_pdbg2(" %c%c ",
441 desc->master.mstr[i].ext_read & (1 << (j - 12)) ? 'r' : ' ',
442 desc->master.mstr[i].ext_write & (1 << (j - 12)) ? 'w' : ' ');
Nico Huberfa622942017-03-24 17:25:37 +0100443 msg_pdbg2("\n");
444 }
David Hendricksa5216362017-08-08 20:02:22 -0700445 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
446 const char *const master_names[] = {
447 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
448 };
449 /* NM starts at 1 instead of 0 for LBG */
Nico Huber519be662018-12-23 20:03:35 +0100450 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
David Hendricksa5216362017-08-08 20:02:22 -0700451 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
452 desc->content.NM);
453 return;
454 }
455
456 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
457 " ", /* width of master name (4 chars minimum) */
458 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
459 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
460 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
461 "Reg15");
462 for (i = 0; i < nm; i++) {
463 size_t j;
464 msg_pdbg2("%-4s", master_names[i]);
465 for (j = 0; j < 16; j++)
466 msg_pdbg2(" %c%c ",
467 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
468 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
469 msg_pdbg2("\n");
470 }
Angel Pons11a35982020-07-10 17:04:10 +0200471 } else if (cs == CHIPSET_APOLLO_LAKE || cs == CHIPSET_GEMINI_LAKE) {
Nico Huberd2d39932019-01-18 16:49:37 +0100472 const char *const master_names[] = { "BIOS", "TXE", };
Nico Huber519be662018-12-23 20:03:35 +0100473 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberd2d39932019-01-18 16:49:37 +0100474 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
475 return;
476 }
477
478 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
479 for (i = 0; i < nm; i++) {
Nico Huber519be662018-12-23 20:03:35 +0100480 ssize_t j;
Nico Huberd2d39932019-01-18 16:49:37 +0100481 msg_pdbg2("%-4s", master_names[i]);
482 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
483 msg_pdbg2(" %c%c ",
484 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
485 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
486 msg_pdbg2("\n");
487 }
Nico Huberfa622942017-03-24 17:25:37 +0100488 } else {
489 const struct ich_desc_master *const mstr = &desc->master;
490 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
491 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
492 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
493 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
494 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
495 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
496 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
497 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
498 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
499 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
500 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
501 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
502 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
503 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
504 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
505 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
506 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
507 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
508 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
509 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000510 msg_pdbg2("\n");
511}
512
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600513static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000514{
515 static const char * const str_GPIO12[4] = {
516 "GPIO12",
517 "LAN PHY Power Control Function (Native Output)",
518 "GLAN_DOCK# (Native Input)",
519 "invalid configuration",
520 };
521
522 msg_pdbg2("--- MCH details ---\n");
523 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
524 msg_pdbg2("\n");
525
526 msg_pdbg2("--- ICH details ---\n");
527 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
528 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
529 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
530 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
531 msg_pdbg2("SPI CS1 is used for %s.\n",
532 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
533 "LAN PHY Power Control Function" :
534 "SPI Chip Select");
535 msg_pdbg2("GPIO12 is used as %s.\n",
536 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
537 msg_pdbg2("PCIe Port 6 is used for %s.\n",
538 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
539 msg_pdbg2("%sn BMC Mode: "
540 "Intel AMT SMBus Controller 1 is connected to %s.\n",
541 desc->south.ich8.BMCMODE ? "I" : "Not i",
542 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
543 msg_pdbg2("TCO is in %s Mode.\n",
544 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
545 msg_pdbg2("ME A is %sabled.\n",
546 desc->south.ich8.ME_DISABLE ? "dis" : "en");
547 msg_pdbg2("\n");
548}
549
550static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
551{
552 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
553
554 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000555 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000556 case 0:
557 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
558 break;
559 case 1:
560 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
561 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
562 break;
563 case 2:
564 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
565 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
566 break;
567 case 3:
568 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
569 1+off, 2+off, 4+off);
570 break;
571 }
572 msg_pdbg2("\n");
573}
574
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600575static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000576{
577 /* PCHSTRP4 */
578 msg_pdbg2("Intel PHY is %s.\n",
579 (s->ibex.PHYCON == 2) ? "connected" :
580 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
581 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
582 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
583 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
584 s->ibex.GBEMAC_SMBUS_ADDR);
585 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
586 s->ibex.GBEPHY_SMBUS_ADDR);
587
588 /* PCHSTRP5 */
589 /* PCHSTRP6 */
590 /* PCHSTRP7 */
591 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
592 s->ibex.MESMA2UDID_VENDOR);
593 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
594 s->ibex.MESMA2UDID_VENDOR);
595
596 /* PCHSTRP8 */
597}
598
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600599static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000600{
601 /* PCHSTRP11 */
602 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
603 s->ibex.SML1GPAEN ? "en" : "dis");
604 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
605 s->ibex.SML1GPA);
606 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
607 s->ibex.SML1I2CAEN ? "en" : "dis");
608 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
609 s->ibex.SML1I2CA);
610
611 /* PCHSTRP12 */
612 /* PCHSTRP13 */
613}
614
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600615static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000616{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000617 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000618 100,
619 50,
620 5,
621 1
622 };
623
624 msg_pdbg2("--- PCH ---\n");
625
626 /* PCHSTRP0 */
627 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
628 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
629 s->ibex.SMB_EN ? "en" : "dis");
630 msg_pdbg2("SMLink0 segment is %sabled.\n",
631 s->ibex.SML0_EN ? "en" : "dis");
632 msg_pdbg2("SMLink1 segment is %sabled.\n",
633 s->ibex.SML1_EN ? "en" : "dis");
634 msg_pdbg2("SMLink1 Frequency: %s\n",
635 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
636 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
637 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
638 msg_pdbg2("SMLink0 Frequency: %s\n",
639 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
640 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
641 "LAN_PHY_PWR_CTRL" : "general purpose output");
642 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
643 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
644 s->ibex.DMI_REQID_DIS ? "en" : "dis");
645 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
646 1 << (6 + s->ibex.BBBS));
647
648 /* PCHSTRP1 */
649 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
650
651 /* PCHSTRP2 */
652 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
653 s->ibex.MESMASDEN ? "en" : "dis");
654 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
655 s->ibex.MESMASDA);
656 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
657 s->ibex.MESMI2CEN ? "en" : "dis");
658 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
659 s->ibex.MESMI2CA);
660
661 /* PCHSTRP3 */
662 prettyprint_ich_descriptor_pchstraps45678_56(s);
663 /* PCHSTRP9 */
664 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
665 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
666 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
667 s->ibex.PCIELR1 ? "" : "not ");
668 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
669 s->ibex.PCIELR2 ? "" : "not ");
670 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
671 s->ibex.DMILR ? "" : "not ");
672 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
673 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
674 s->ibex.PHY_PCIE_EN ? "en" : "dis");
675
676 /* PCHSTRP10 */
677 msg_pdbg2("Management Engine will boot from %sflash.\n",
678 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
679 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
680 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
681 s->ibex.VE_EN ? "en" : "dis");
682 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
683 s->ibex.MMDDE ? "en" : "dis");
684 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
685 s->ibex.MMADDR);
686 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
687 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
688 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
689 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
690 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
691
692 prettyprint_ich_descriptor_pchstraps111213_56(s);
693
694 /* PCHSTRP14 */
695 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
696 s->ibex.VE_EN2 ? "en" : "dis");
697 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
698 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
699 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
700 s->ibex.BW_SSD ? "en" : "dis");
701 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
702 s->ibex.NVMHCI_EN ? "en" : "dis");
703
704 /* PCHSTRP15 */
705 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
706 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
707 s->ibex.IWL_EN ? "en" : "dis");
708 msg_pdbg2("t209 min Timing: %d ms\n",
709 dec_t209min[s->ibex.t209min]);
710 msg_pdbg2("\n");
711}
712
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600713static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000714{
715 msg_pdbg2("--- PCH ---\n");
716
717 /* PCHSTRP0 */
718 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
719 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
720 s->ibex.SMB_EN ? "en" : "dis");
721 msg_pdbg2("SMLink0 segment is %sabled.\n",
722 s->ibex.SML0_EN ? "en" : "dis");
723 msg_pdbg2("SMLink1 segment is %sabled.\n",
724 s->ibex.SML1_EN ? "en" : "dis");
725 msg_pdbg2("SMLink1 Frequency: %s\n",
726 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
727 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
728 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
729 msg_pdbg2("SMLink0 Frequency: %s\n",
730 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
731 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
732 "LAN_PHY_PWR_CTRL" : "general purpose output");
733 msg_pdbg2("LinkSec is %sabled.\n",
734 s->cougar.LINKSEC_DIS ? "en" : "dis");
735 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
736 s->ibex.DMI_REQID_DIS ? "en" : "dis");
737 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
738 1 << (6 + s->ibex.BBBS));
739
740 /* PCHSTRP1 */
741 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
742 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
743
744 /* PCHSTRP2 */
745 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
746 s->ibex.MESMASDEN ? "en" : "dis");
747 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
748 s->ibex.MESMASDA);
749 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
750 s->cougar.MESMMCTPAEN ? "en" : "dis");
751 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
752 s->cougar.MESMMCTPA);
753 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
754 s->ibex.MESMI2CEN ? "en" : "dis");
755 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
756 s->ibex.MESMI2CA);
757
758 /* PCHSTRP3 */
759 prettyprint_ich_descriptor_pchstraps45678_56(s);
760 /* PCHSTRP9 */
761 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
762 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
763 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
764 s->ibex.PCIELR1 ? "" : "not ");
765 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
766 s->ibex.PCIELR2 ? "" : "not ");
767 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
768 s->ibex.DMILR ? "" : "not ");
769 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
770 s->cougar.MDSMBE_EN ? "en" : "dis");
771 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
772 s->cougar.MDSMBE_ADD);
773 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
774 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
775 s->ibex.PHY_PCIE_EN ? "en" : "dis");
776 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
777 s->cougar.SUB_DECODE_EN ? "en" : "dis");
778 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
779 "PCHHOT#" : "SML1ALERT#");
780
781 /* PCHSTRP10 */
782 msg_pdbg2("Management Engine will boot from %sflash.\n",
783 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
784
785 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
786 s->cougar.MDSMBE_EN ? "en" : "dis");
787 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
788 s->cougar.MDSMBE_ADD);
789
790 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
791 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000792 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
793 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000794 msg_pdbg2("ICC Profile is selected by %s.\n",
795 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
796 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
797 s->cougar.Deep_SX_EN ? "not " : "");
798 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
799 s->cougar.ME_DBG_LAN ? "en" : "dis");
800
801 prettyprint_ich_descriptor_pchstraps111213_56(s);
802
803 /* PCHSTRP14 */
804 /* PCHSTRP15 */
805 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
806 msg_pdbg2("Integrated wired LAN is %sabled.\n",
807 s->cougar.IWL_EN ? "en" : "dis");
808 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
809 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000810 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000811 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
812 "general purpose output" : "SLP_LAN#");
813
814 /* PCHSTRP16 */
815 /* PCHSTRP17 */
816 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
817 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
818 msg_pdbg2("\n");
819}
820
821void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
822{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000823 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000824 msg_pdbg2("=== Softstraps ===\n");
825
Nico Huber519be662018-12-23 20:03:35 +0100826 max_count = MIN(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
Nico Huberd7c75522017-03-29 16:31:49 +0200827 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000828 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200829 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000830 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200831 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000832
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000833 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
834 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000835 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
836 msg_pdbg2("\n");
837
Nico Huber519be662018-12-23 20:03:35 +0100838 max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
Nico Huberd7c75522017-03-29 16:31:49 +0200839 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000840 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
841 desc->content.ISL, max_count);
842 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200843 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000844
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000845 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
846 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000847 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
848 msg_pdbg2("\n");
849
850 switch (cs) {
851 case CHIPSET_ICH8:
852 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
853 msg_pdbg2("Detailed North/MCH/PROC information is "
854 "probably not reliable, printing anyway.\n");
855 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
856 msg_pdbg2("Detailed South/ICH/PCH information is "
857 "probably not reliable, printing anyway.\n");
858 prettyprint_ich_descriptor_straps_ich8(desc);
859 break;
860 case CHIPSET_5_SERIES_IBEX_PEAK:
861 /* PCH straps only. PROCSTRPs are unknown. */
862 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
863 msg_pdbg2("Detailed South/ICH/PCH information is "
864 "probably not reliable, printing anyway.\n");
865 prettyprint_ich_descriptor_straps_ibex(&desc->south);
866 break;
867 case CHIPSET_6_SERIES_COUGAR_POINT:
868 /* PCH straps only. PROCSTRP0 is "reserved". */
869 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
870 msg_pdbg2("Detailed South/ICH/PCH information is "
871 "probably not reliable, printing anyway.\n");
872 prettyprint_ich_descriptor_straps_cougar(&desc->south);
873 break;
874 case CHIPSET_ICH_UNKNOWN:
875 break;
876 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000877 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000878 break;
879 }
880}
881
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600882static void prettyprint_rdid(uint32_t reg_val)
Stefan Taunerb3850962011-12-24 00:00:32 +0000883{
884 uint8_t mid = reg_val & 0xFF;
885 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
886 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
887}
888
889void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
890{
891 int i;
892 msg_pdbg2("=== Upper Map Section ===\n");
893 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
894 msg_pdbg2("\n");
895
896 msg_pdbg2("--- Details ---\n");
897 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
898 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
899 msg_pdbg2("\n");
900
901 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000902 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000903 uint32_t jid = umap->vscc_table[i].JID;
904 uint32_t vscc = umap->vscc_table[i].VSCC;
905 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
906 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
907 msg_pdbg2(" "); /* indention */
908 prettyprint_rdid(jid);
909 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000910 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000911 }
912 msg_pdbg2("\n");
913}
914
Nico Huber1dc3d422017-06-17 00:09:31 +0200915/*
916 * Guesses a minimum chipset version based on the maximum number of
917 * soft straps per generation.
918 */
919static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
920{
921 if (content->ICCRIBA == 0x00) {
922 if (content->MSL == 0 && content->ISL <= 2)
923 return CHIPSET_ICH8;
924 else if (content->ISL <= 2)
925 return CHIPSET_ICH9;
926 else if (content->ISL <= 10)
927 return CHIPSET_ICH10;
928 else if (content->ISL <= 16)
929 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huberd2d39932019-01-18 16:49:37 +0100930 else if (content->FLMAP2 == 0) {
Angel Pons11a35982020-07-10 17:04:10 +0200931 if (content->ISL == 23)
932 return CHIPSET_GEMINI_LAKE;
933 else if (content->ISL != 19)
Nico Huberd2d39932019-01-18 16:49:37 +0100934 msg_pwarn("Peculiar firmware descriptor, assuming Apollo Lake compatibility.\n");
935 return CHIPSET_APOLLO_LAKE;
936 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200937 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
938 return CHIPSET_5_SERIES_IBEX_PEAK;
939 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
940 if (content->MSL == 0 && content->ISL <= 17)
941 return CHIPSET_BAYTRAIL;
942 else if (content->MSL <= 1 && content->ISL <= 18)
943 return CHIPSET_6_SERIES_COUGAR_POINT;
944 else if (content->MSL <= 1 && content->ISL <= 21)
945 return CHIPSET_8_SERIES_LYNX_POINT;
946 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
947 return CHIPSET_9_SERIES_WILDCAT_POINT;
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200948 } else if (content->ICCRIBA < 0x34) {
949 if (content->NM == 6)
950 return CHIPSET_C620_SERIES_LEWISBURG;
951 else
952 return CHIPSET_100_SERIES_SUNRISE_POINT;
Jonathan Zhang95d822e2020-08-19 12:19:06 -0700953 } else if (content->ICCRIBA == 0x34) {
954 if (content->NM == 6)
955 return CHIPSET_C620_SERIES_LEWISBURG;
956 else
957 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200958 } else {
Jonathan Zhang95d822e2020-08-19 12:19:06 -0700959 msg_pwarn("Unknown firmware descriptor, assuming 300 series compatibility.\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200960 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200961 }
962}
963
964/*
965 * As an additional measure, we check the read frequency like `ifdtool`.
966 * The frequency value 6 (17MHz) was reserved before Skylake and is the
967 * only valid value since. Skylake is currently the most important dis-
968 * tinction because of the dropped number of regions field (NR).
969 */
Nico Huberfa622942017-03-24 17:25:37 +0100970static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
971 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200972{
973 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
974
Nico Huberd2d39932019-01-18 16:49:37 +0100975 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200976 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -0500977 case CHIPSET_400_SERIES_COMET_POINT:
Angel Pons11a35982020-07-10 17:04:10 +0200978 case CHIPSET_GEMINI_LAKE:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200979 /* `freq_read` was repurposed, so can't check on it any more. */
980 return guess;
Nico Huberd2d39932019-01-18 16:49:37 +0100981 case CHIPSET_100_SERIES_SUNRISE_POINT:
982 case CHIPSET_C620_SERIES_LEWISBURG:
983 case CHIPSET_APOLLO_LAKE:
984 if (component->modes.freq_read != 6) {
985 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
986 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
987 "Please report this message, the output of `ich_descriptors_tool` for\n"
988 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
989 return CHIPSET_9_SERIES_WILDCAT_POINT;
990 }
991 return guess;
992 default:
993 if (component->modes.freq_read == 6) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200994 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
995 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\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");
David Hendricksa5216362017-08-08 20:02:22 -0700998 return CHIPSET_100_SERIES_SUNRISE_POINT;
999 }
1000 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +02001001 }
Nico Huber1dc3d422017-06-17 00:09:31 +02001002}
1003
Stefan Taunerb3850962011-12-24 00:00:32 +00001004/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +01001005int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
1006 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +00001007{
Nico Huber519be662018-12-23 20:03:35 +01001008 ssize_t i, max_count;
1009 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +00001010
1011 if (dump == NULL || desc == NULL)
1012 return ICH_RET_PARAM;
1013
1014 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1015 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1016 pch_bug_offset = 4;
1017 else
1018 return ICH_RET_ERR;
1019 }
1020
1021 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001022 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001023 return ICH_RET_OOB;
1024 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1025 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1026 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1027 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1028
1029 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001030 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001031 return ICH_RET_OOB;
1032 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1033 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1034 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1035
Nico Huber67d71792017-06-17 03:10:15 +02001036 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +01001037 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +02001038 prettyprint_ich_chipset(*cs);
1039 }
Nico Huberfa622942017-03-24 17:25:37 +01001040
Stefan Taunerb3850962011-12-24 00:00:32 +00001041 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001042 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001043 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001044 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001045 for (i = 0; i < nr; i++)
1046 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001047
1048 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001049 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001050 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001051 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001052 for (i = 0; i < nm; i++)
1053 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001054
1055 /* upper map */
1056 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1057
1058 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1059 * "Identifies the 1s based number of DWORDS contained in the VSCC
1060 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1061 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1062 * check ensures that the maximum offset actually accessed is available.
1063 */
Nico Huber9e14aed2017-03-28 17:08:46 +02001064 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +00001065 return ICH_RET_OOB;
1066
1067 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001068 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1069 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +00001070 }
1071
1072 /* MCH/PROC (aka. North) straps */
1073 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1074 return ICH_RET_OOB;
1075
1076 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001077 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001078 for (i = 0; i < max_count; i++)
1079 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001080
1081 /* ICH/PCH (aka. South) straps */
1082 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1083 return ICH_RET_OOB;
1084
1085 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001086 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001087 for (i = 0; i < max_count; i++)
1088 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001089
1090 return ICH_RET_OK;
1091}
1092
Nico Huberad186312016-05-02 15:15:29 +02001093#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001094
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001095/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001096\em idx in bytes or -1 if the correct size can not be determined. */
1097int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001098{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001099 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001100 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001101 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001102 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001103
1104 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001105 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001106
1107 uint8_t size_enc;
1108 uint8_t size_max;
1109
1110 switch (cs) {
1111 case CHIPSET_ICH8:
1112 case CHIPSET_ICH9:
1113 case CHIPSET_ICH10:
1114 case CHIPSET_5_SERIES_IBEX_PEAK:
1115 case CHIPSET_6_SERIES_COUGAR_POINT:
1116 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001117 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001118 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001119 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001120 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001121 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001122 }
1123 size_max = 5;
1124 break;
1125 case CHIPSET_8_SERIES_LYNX_POINT:
1126 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1127 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001128 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001129 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001130 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001131 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001132 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -05001133 case CHIPSET_400_SERIES_COMET_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001134 case CHIPSET_APOLLO_LAKE:
Angel Pons11a35982020-07-10 17:04:10 +02001135 case CHIPSET_GEMINI_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001136 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001137 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001138 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001139 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001140 }
1141 size_max = 7;
1142 break;
1143 case CHIPSET_ICH_UNKNOWN:
1144 default:
1145 msg_pwarn("Density encoding is unknown on this chipset.\n");
1146 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001147 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001148
1149 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001150 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001151 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1152 idx, size_enc, size_max);
1153 return -1;
1154 }
1155
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001156 return (1 << (19 + size_enc));
1157}
1158
Nico Huber8d494992017-06-19 12:18:33 +02001159/* Only used by ichspi.c */
1160#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001161static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001162{
1163 uint32_t control = 0;
1164 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1165 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001166 switch (cs) {
1167 case CHIPSET_100_SERIES_SUNRISE_POINT:
1168 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001169 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -05001170 case CHIPSET_400_SERIES_COMET_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001171 case CHIPSET_APOLLO_LAKE:
Angel Pons11a35982020-07-10 17:04:10 +02001172 case CHIPSET_GEMINI_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001173 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1174 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001175 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001176 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1177 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1178 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001179}
1180
Nico Huberd54e4f42017-03-23 23:45:47 +01001181int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001182{
Nico Huber519be662018-12-23 20:03:35 +01001183 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001184 struct ich_desc_region *r = &desc->region;
1185
1186 /* Test if bit-fields are working as expected.
1187 * FIXME: Replace this with dynamic bitfield fixup
1188 */
1189 for (i = 0; i < 4; i++)
1190 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001191 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1192 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1193 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1194 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001195 msg_pdbg("The combination of compiler and CPU architecture used"
1196 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001197 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1198 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1199 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1200 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1201 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1202 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1203 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1204 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001205 return ICH_RET_ERR;
1206 }
1207
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001208 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001209 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001210 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1211 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1212 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1213 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001214
1215 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001216 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1217 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1218 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001219
1220 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001221 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1222 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001223 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001224 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001225 return ICH_RET_ERR;
1226 }
Nico Huberfa622942017-03-24 17:25:37 +01001227 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001228 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001229
1230 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001231 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1232 if (nm < 0) {
1233 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1234 __func__, desc->content.NM + 1);
1235 return ICH_RET_ERR;
1236 }
1237 for (i = 0; i < nm; i++)
1238 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001239
1240 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1241 * reading the upper map is impossible on all chipsets, so don't bother.
1242 */
1243
1244 msg_pdbg2(" done.\n");
1245 return ICH_RET_OK;
1246}
Nico Huber8d494992017-06-19 12:18:33 +02001247#endif
Nico Huber305f4172013-06-14 11:55:26 +02001248
1249/**
1250 * @brief Read a layout from the dump of an Intel ICH descriptor.
1251 *
1252 * @param layout Pointer where to store the layout.
1253 * @param dump The descriptor dump to read from.
1254 * @param len The length of the descriptor dump.
1255 *
1256 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001257 * 1 if the descriptor couldn't be parsed,
1258 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001259 */
1260int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1261{
Nico Huberfa622942017-03-24 17:25:37 +01001262 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001263 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1264 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001265 };
Nico Huber305f4172013-06-14 11:55:26 +02001266
1267 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001268 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
Jonathan Zhang95d822e2020-08-19 12:19:06 -07001269 int ret = read_ich_descriptors_from_dump(dump, len, &cs, &desc);
1270 if (ret) {
1271 msg_pdbg("%s():%d, returned with value %d.\n",
1272 __func__, __LINE__, ret);
Nico Huber305f4172013-06-14 11:55:26 +02001273 return 1;
Jonathan Zhang95d822e2020-08-19 12:19:06 -07001274 }
Nico Huber305f4172013-06-14 11:55:26 +02001275
1276 memset(layout, 0x00, sizeof(*layout));
1277
Nico Huberfa622942017-03-24 17:25:37 +01001278 ssize_t i, j;
Nico Huber519be662018-12-23 20:03:35 +01001279 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
1280 for (i = 0, j = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001281 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001282 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001283 if (limit <= base)
1284 continue;
1285 layout->entries[j].start = base;
1286 layout->entries[j].end = limit;
1287 layout->entries[j].included = false;
Nico Huber70461a92019-06-15 14:56:19 +02001288 layout->entries[j].name = strdup(regions[i]);
1289 if (!layout->entries[j].name)
1290 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001291 ++j;
1292 }
1293 layout->base.entries = layout->entries;
1294 layout->base.num_entries = j;
1295 return 0;
1296}
1297
Nico Huberad186312016-05-02 15:15:29 +02001298#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */