blob: 5d08717b97fbc6a5fb956f06debf7812446ab370 [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 Pons4db0fdf2020-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:
David Hendricksa5216362017-08-08 20:02:22 -070046 return 16;
Nico Huberfa622942017-03-24 17:25:37 +010047 case CHIPSET_100_SERIES_SUNRISE_POINT:
48 return 10;
49 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
50 case CHIPSET_9_SERIES_WILDCAT_POINT:
51 case CHIPSET_8_SERIES_LYNX_POINT_LP:
52 case CHIPSET_8_SERIES_LYNX_POINT:
53 case CHIPSET_8_SERIES_WELLSBURG:
54 if (cont->NR <= 6)
55 return cont->NR + 1;
56 else
57 return -1;
58 default:
59 if (cont->NR <= 4)
60 return cont->NR + 1;
61 else
62 return -1;
63 }
64}
65
66ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
67{
David Hendricksa5216362017-08-08 20:02:22 -070068 switch (cs) {
69 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberd2d39932019-01-18 16:49:37 +010070 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +020071 case CHIPSET_GEMINI_LAKE:
David Hendricksa5216362017-08-08 20:02:22 -070072 if (cont->NM <= MAX_NUM_MASTERS)
73 return cont->NM;
Richard Hughesdb7482b2018-12-19 12:04:30 +000074 break;
David Hendricksa5216362017-08-08 20:02:22 -070075 default:
76 if (cont->NM < MAX_NUM_MASTERS)
77 return cont->NM + 1;
78 }
79
80 return -1;
Nico Huberfa622942017-03-24 17:25:37 +010081}
82
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000083void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000084{
85 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
86 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
87 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
88 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000089 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
90 if (print_vcl)
91 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
92 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000093}
94
95#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
96#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
97#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
98#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
99#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
100
Nico Huber67d71792017-06-17 03:10:15 +0200101void prettyprint_ich_chipset(enum ich_chipset cs)
102{
103 static const char *const chipset_names[] = {
104 "Unknown ICH", "ICH8", "ICH9", "ICH10",
105 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
106 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
107 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
Angel Pons4db0fdf2020-07-10 17:04:10 +0200108 "C620 series Lewisburg", "300/400 series Cannon/Comet Point",
109 "Apollo Lake", "Gemini Lake",
Nico Huber67d71792017-06-17 03:10:15 +0200110 };
111 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
112 cs = 0;
113 else
114 cs = cs - CHIPSET_ICH8 + 1;
115 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
116}
117
Stefan Tauner1e146392011-09-15 23:52:55 +0000118void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
119{
Nico Huberfa622942017-03-24 17:25:37 +0100120 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000121 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100122 prettyprint_ich_descriptor_region(cs, desc);
123 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200124#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000125 if (cs >= CHIPSET_ICH8) {
126 prettyprint_ich_descriptor_upper_map(&desc->upper);
127 prettyprint_ich_descriptor_straps(cs, desc);
128 }
Nico Huberad186312016-05-02 15:15:29 +0200129#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000130}
131
Nico Huberfa622942017-03-24 17:25:37 +0100132void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000133{
134 msg_pdbg2("=== Content Section ===\n");
135 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
136 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
137 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
138 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
139 msg_pdbg2("\n");
140
141 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100142 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
143 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
144 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
145 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
Nico Huberd2d39932019-01-18 16:49:37 +0100146 msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL);
147 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont));
Nico Huberfa622942017-03-24 17:25:37 +0100148 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
149 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
150 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
151 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000152 msg_pdbg2("\n");
153}
154
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000155static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
156{
157 if (idx > 1) {
158 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
159 return NULL;
160 }
161
162 if (desc->content.NC == 0 && idx > 0)
163 return "unused";
164
165 static const char * const size_str[] = {
166 "512 kB", /* 0000 */
167 "1 MB", /* 0001 */
168 "2 MB", /* 0010 */
169 "4 MB", /* 0011 */
170 "8 MB", /* 0100 */
171 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
172 "32 MB", /* 0110 */
173 "64 MB", /* 0111 */
174 };
175
176 switch (cs) {
177 case CHIPSET_ICH8:
178 case CHIPSET_ICH9:
179 case CHIPSET_ICH10:
180 case CHIPSET_5_SERIES_IBEX_PEAK:
181 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000182 case CHIPSET_7_SERIES_PANTHER_POINT:
183 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000184 uint8_t size_enc;
185 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000186 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000187 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000188 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000189 }
190 if (size_enc > 5)
191 return "reserved";
192 return size_str[size_enc];
193 }
194 case CHIPSET_8_SERIES_LYNX_POINT:
195 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000196 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100197 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100198 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
David Hendricksa5216362017-08-08 20:02:22 -0700199 case CHIPSET_100_SERIES_SUNRISE_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100200 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200201 case CHIPSET_300_SERIES_CANNON_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200202 case CHIPSET_APOLLO_LAKE:
203 case CHIPSET_GEMINI_LAKE: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000204 uint8_t size_enc;
205 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000206 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000207 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000208 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000209 }
210 if (size_enc > 7)
211 return "reserved";
212 return size_str[size_enc];
213 }
214 case CHIPSET_ICH_UNKNOWN:
215 default:
216 return "unknown";
217 }
218}
219
220static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000221{
Nico Huberd2d39932019-01-18 16:49:37 +0100222 static const char *const freq_str[3][8] = { {
Nico Huber129e9382019-06-06 15:43:27 +0200223 "20 MHz",
224 "33 MHz",
225 "reserved",
226 "reserved",
227 "50 MHz", /* New since Ibex Peak */
228 "reserved",
229 "reserved",
230 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100231 }, {
Nico Huber129e9382019-06-06 15:43:27 +0200232 "reserved",
233 "reserved",
234 "48 MHz",
235 "reserved",
236 "30 MHz",
237 "reserved",
238 "17 MHz",
239 "reserved"
Nico Huberd2d39932019-01-18 16:49:37 +0100240 }, {
241 "reserved",
242 "50 MHz",
243 "40 MHz",
244 "reserved",
245 "25 MHz",
246 "reserved",
247 "14 MHz / 17 MHz",
248 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100249 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000250
251 switch (cs) {
252 case CHIPSET_ICH8:
253 case CHIPSET_ICH9:
254 case CHIPSET_ICH10:
255 if (value > 1)
256 return "reserved";
Richard Hughesdb7482b2018-12-19 12:04:30 +0000257 /* Fall through. */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000258 case CHIPSET_5_SERIES_IBEX_PEAK:
259 case CHIPSET_6_SERIES_COUGAR_POINT:
260 case CHIPSET_7_SERIES_PANTHER_POINT:
261 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000262 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000263 case CHIPSET_8_SERIES_LYNX_POINT_LP:
264 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000265 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100266 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100267 return freq_str[0][value];
268 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700269 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200270 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100271 return freq_str[1][value];
Nico Huberd2d39932019-01-18 16:49:37 +0100272 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200273 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100274 return freq_str[2][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000275 case CHIPSET_ICH_UNKNOWN:
276 default:
277 return "unknown";
278 }
279}
280
281void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
282{
Nico Huberd2d39932019-01-18 16:49:37 +0100283 bool has_flill1;
284
285 switch (cs) {
286 case CHIPSET_100_SERIES_SUNRISE_POINT:
287 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200288 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100289 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200290 case CHIPSET_GEMINI_LAKE:
Nico Huberd2d39932019-01-18 16:49:37 +0100291 has_flill1 = true;
292 break;
293 default:
294 has_flill1 = false;
295 break;
296 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000297
298 msg_pdbg2("=== Component Section ===\n");
299 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
300 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberd2d39932019-01-18 16:49:37 +0100301 if (has_flill1)
Nico Huberfa622942017-03-24 17:25:37 +0100302 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000303 msg_pdbg2("\n");
304
305 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000306 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000307 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000308 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000309 else
310 msg_pdbg2("Component 2 is not used.\n");
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000311 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
312 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
313 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
314 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
315 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000316 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000317 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000318 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
319 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000320 desc->component.modes.dual_output ? "dis" : "en");
David Hendricksa5216362017-08-08 20:02:22 -0700321
322 int has_forbidden_opcode = 0;
323 if (desc->component.FLILL != 0) {
324 has_forbidden_opcode = 1;
Stefan Tauner1e146392011-09-15 23:52:55 +0000325 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
326 desc->component.invalid_instr0);
327 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
328 desc->component.invalid_instr1);
329 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
330 desc->component.invalid_instr2);
331 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
332 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700333 }
Nico Huberd2d39932019-01-18 16:49:37 +0100334 if (has_flill1) {
David Hendricksa5216362017-08-08 20:02:22 -0700335 if (desc->component.FLILL1 != 0) {
336 has_forbidden_opcode = 1;
Nico Huberfa622942017-03-24 17:25:37 +0100337 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
338 desc->component.invalid_instr4);
339 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
340 desc->component.invalid_instr5);
341 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
342 desc->component.invalid_instr6);
343 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
344 desc->component.invalid_instr7);
345 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000346 }
David Hendricksa5216362017-08-08 20:02:22 -0700347 if (!has_forbidden_opcode)
348 msg_pdbg2("No forbidden opcodes.\n");
349
Stefan Tauner1e146392011-09-15 23:52:55 +0000350 msg_pdbg2("\n");
351}
352
353static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
354{
Nico Huberfa622942017-03-24 17:25:37 +0100355 static const char *const region_names[] = {
Nico Huberd2d39932019-01-18 16:49:37 +0100356 "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown",
David Hendricksa5216362017-08-08 20:02:22 -0700357 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000358 };
Nico Huberfa622942017-03-24 17:25:37 +0100359 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000360 msg_pdbg2("%s: region index too high.\n", __func__);
361 return;
362 }
363 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
364 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100365 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000366 if (base > limit)
367 msg_pdbg2("is unused.\n");
368 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200369 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000370}
371
Nico Huberfa622942017-03-24 17:25:37 +0100372void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000373{
Nico Huber519be662018-12-23 20:03:35 +0100374 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100375 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000376 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100377 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000378 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100379 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000380 return;
381 }
Nico Huberfa622942017-03-24 17:25:37 +0100382 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100383 msg_pdbg2("FLREG%zd 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000384 msg_pdbg2("\n");
385
386 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100387 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100388 pprint_freg(&desc->region, (uint32_t)i);
Stefan Tauner1e146392011-09-15 23:52:55 +0000389 msg_pdbg2("\n");
390}
391
Nico Huberfa622942017-03-24 17:25:37 +0100392void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000393{
Nico Huber519be662018-12-23 20:03:35 +0100394 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100395 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000396 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100397 if (nm < 0) {
398 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
399 desc->content.NM + 1);
400 return;
401 }
402 for (i = 0; i < nm; i++)
Nico Huber519be662018-12-23 20:03:35 +0100403 msg_pdbg2("FLMSTR%zd 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000404 msg_pdbg2("\n");
405
406 msg_pdbg2("--- Details ---\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200407 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT ||
408 cs == CHIPSET_300_SERIES_CANNON_POINT) {
Nico Huberfa622942017-03-24 17:25:37 +0100409 const char *const master_names[] = {
410 "BIOS", "ME", "GbE", "unknown", "EC",
411 };
Nico Huber519be662018-12-23 20:03:35 +0100412 if (nm >= (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberfa622942017-03-24 17:25:37 +0100413 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
414 desc->content.NM + 1);
415 return;
416 }
417
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200418 size_t num_regions;
419 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9");
420 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
421 num_regions = 10;
422 msg_pdbg2("\n");
423 } else {
424 num_regions = 16;
425 msg_pdbg2(" RegA RegB RegC RegD RegE RegF\n");
426 }
Nico Huberfa622942017-03-24 17:25:37 +0100427 for (i = 0; i < nm; i++) {
428 size_t j;
429 msg_pdbg2("%-4s", master_names[i]);
Nico Huber961f4a12019-10-04 17:34:22 +0200430 for (j = 0; j < (size_t)min(num_regions, 12); j++)
Nico Huberfa622942017-03-24 17:25:37 +0100431 msg_pdbg2(" %c%c ",
432 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
433 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200434 for (; j < num_regions; j++)
435 msg_pdbg2(" %c%c ",
436 desc->master.mstr[i].ext_read & (1 << (j - 12)) ? 'r' : ' ',
437 desc->master.mstr[i].ext_write & (1 << (j - 12)) ? 'w' : ' ');
Nico Huberfa622942017-03-24 17:25:37 +0100438 msg_pdbg2("\n");
439 }
David Hendricksa5216362017-08-08 20:02:22 -0700440 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
441 const char *const master_names[] = {
442 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
443 };
444 /* NM starts at 1 instead of 0 for LBG */
Nico Huber519be662018-12-23 20:03:35 +0100445 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
David Hendricksa5216362017-08-08 20:02:22 -0700446 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
447 desc->content.NM);
448 return;
449 }
450
451 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
452 " ", /* width of master name (4 chars minimum) */
453 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
454 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
455 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
456 "Reg15");
457 for (i = 0; i < nm; i++) {
458 size_t j;
459 msg_pdbg2("%-4s", master_names[i]);
460 for (j = 0; j < 16; j++)
461 msg_pdbg2(" %c%c ",
462 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
463 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
464 msg_pdbg2("\n");
465 }
Angel Pons4db0fdf2020-07-10 17:04:10 +0200466 } else if (cs == CHIPSET_APOLLO_LAKE || cs == CHIPSET_GEMINI_LAKE) {
Nico Huberd2d39932019-01-18 16:49:37 +0100467 const char *const master_names[] = { "BIOS", "TXE", };
Nico Huber519be662018-12-23 20:03:35 +0100468 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberd2d39932019-01-18 16:49:37 +0100469 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
470 return;
471 }
472
473 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
474 for (i = 0; i < nm; i++) {
Nico Huber519be662018-12-23 20:03:35 +0100475 ssize_t j;
Nico Huberd2d39932019-01-18 16:49:37 +0100476 msg_pdbg2("%-4s", master_names[i]);
477 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
478 msg_pdbg2(" %c%c ",
479 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
480 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
481 msg_pdbg2("\n");
482 }
Nico Huberfa622942017-03-24 17:25:37 +0100483 } else {
484 const struct ich_desc_master *const mstr = &desc->master;
485 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
486 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
487 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
488 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
489 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
490 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
491 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
492 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
493 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
494 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
495 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
496 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
497 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
498 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
499 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
500 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
501 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
502 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
503 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
504 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000505 msg_pdbg2("\n");
506}
507
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600508static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000509{
510 static const char * const str_GPIO12[4] = {
511 "GPIO12",
512 "LAN PHY Power Control Function (Native Output)",
513 "GLAN_DOCK# (Native Input)",
514 "invalid configuration",
515 };
516
517 msg_pdbg2("--- MCH details ---\n");
518 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
519 msg_pdbg2("\n");
520
521 msg_pdbg2("--- ICH details ---\n");
522 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
523 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
524 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
525 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
526 msg_pdbg2("SPI CS1 is used for %s.\n",
527 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
528 "LAN PHY Power Control Function" :
529 "SPI Chip Select");
530 msg_pdbg2("GPIO12 is used as %s.\n",
531 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
532 msg_pdbg2("PCIe Port 6 is used for %s.\n",
533 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
534 msg_pdbg2("%sn BMC Mode: "
535 "Intel AMT SMBus Controller 1 is connected to %s.\n",
536 desc->south.ich8.BMCMODE ? "I" : "Not i",
537 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
538 msg_pdbg2("TCO is in %s Mode.\n",
539 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
540 msg_pdbg2("ME A is %sabled.\n",
541 desc->south.ich8.ME_DISABLE ? "dis" : "en");
542 msg_pdbg2("\n");
543}
544
545static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
546{
547 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
548
549 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000550 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000551 case 0:
552 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
553 break;
554 case 1:
555 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
556 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
557 break;
558 case 2:
559 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
560 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
561 break;
562 case 3:
563 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
564 1+off, 2+off, 4+off);
565 break;
566 }
567 msg_pdbg2("\n");
568}
569
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600570static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000571{
572 /* PCHSTRP4 */
573 msg_pdbg2("Intel PHY is %s.\n",
574 (s->ibex.PHYCON == 2) ? "connected" :
575 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
576 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
577 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
578 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
579 s->ibex.GBEMAC_SMBUS_ADDR);
580 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
581 s->ibex.GBEPHY_SMBUS_ADDR);
582
583 /* PCHSTRP5 */
584 /* PCHSTRP6 */
585 /* PCHSTRP7 */
586 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
587 s->ibex.MESMA2UDID_VENDOR);
588 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
589 s->ibex.MESMA2UDID_VENDOR);
590
591 /* PCHSTRP8 */
592}
593
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600594static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000595{
596 /* PCHSTRP11 */
597 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
598 s->ibex.SML1GPAEN ? "en" : "dis");
599 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
600 s->ibex.SML1GPA);
601 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
602 s->ibex.SML1I2CAEN ? "en" : "dis");
603 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
604 s->ibex.SML1I2CA);
605
606 /* PCHSTRP12 */
607 /* PCHSTRP13 */
608}
609
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600610static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000611{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000612 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000613 100,
614 50,
615 5,
616 1
617 };
618
619 msg_pdbg2("--- PCH ---\n");
620
621 /* PCHSTRP0 */
622 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
623 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
624 s->ibex.SMB_EN ? "en" : "dis");
625 msg_pdbg2("SMLink0 segment is %sabled.\n",
626 s->ibex.SML0_EN ? "en" : "dis");
627 msg_pdbg2("SMLink1 segment is %sabled.\n",
628 s->ibex.SML1_EN ? "en" : "dis");
629 msg_pdbg2("SMLink1 Frequency: %s\n",
630 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
631 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
632 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
633 msg_pdbg2("SMLink0 Frequency: %s\n",
634 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
635 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
636 "LAN_PHY_PWR_CTRL" : "general purpose output");
637 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
638 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
639 s->ibex.DMI_REQID_DIS ? "en" : "dis");
640 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
641 1 << (6 + s->ibex.BBBS));
642
643 /* PCHSTRP1 */
644 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
645
646 /* PCHSTRP2 */
647 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
648 s->ibex.MESMASDEN ? "en" : "dis");
649 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
650 s->ibex.MESMASDA);
651 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
652 s->ibex.MESMI2CEN ? "en" : "dis");
653 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
654 s->ibex.MESMI2CA);
655
656 /* PCHSTRP3 */
657 prettyprint_ich_descriptor_pchstraps45678_56(s);
658 /* PCHSTRP9 */
659 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
660 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
661 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
662 s->ibex.PCIELR1 ? "" : "not ");
663 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
664 s->ibex.PCIELR2 ? "" : "not ");
665 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
666 s->ibex.DMILR ? "" : "not ");
667 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
668 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
669 s->ibex.PHY_PCIE_EN ? "en" : "dis");
670
671 /* PCHSTRP10 */
672 msg_pdbg2("Management Engine will boot from %sflash.\n",
673 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
674 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
675 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
676 s->ibex.VE_EN ? "en" : "dis");
677 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
678 s->ibex.MMDDE ? "en" : "dis");
679 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
680 s->ibex.MMADDR);
681 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
682 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
683 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
684 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
685 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
686
687 prettyprint_ich_descriptor_pchstraps111213_56(s);
688
689 /* PCHSTRP14 */
690 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
691 s->ibex.VE_EN2 ? "en" : "dis");
692 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
693 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
694 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
695 s->ibex.BW_SSD ? "en" : "dis");
696 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
697 s->ibex.NVMHCI_EN ? "en" : "dis");
698
699 /* PCHSTRP15 */
700 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
701 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
702 s->ibex.IWL_EN ? "en" : "dis");
703 msg_pdbg2("t209 min Timing: %d ms\n",
704 dec_t209min[s->ibex.t209min]);
705 msg_pdbg2("\n");
706}
707
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600708static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000709{
710 msg_pdbg2("--- PCH ---\n");
711
712 /* PCHSTRP0 */
713 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
714 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
715 s->ibex.SMB_EN ? "en" : "dis");
716 msg_pdbg2("SMLink0 segment is %sabled.\n",
717 s->ibex.SML0_EN ? "en" : "dis");
718 msg_pdbg2("SMLink1 segment is %sabled.\n",
719 s->ibex.SML1_EN ? "en" : "dis");
720 msg_pdbg2("SMLink1 Frequency: %s\n",
721 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
722 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
723 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
724 msg_pdbg2("SMLink0 Frequency: %s\n",
725 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
726 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
727 "LAN_PHY_PWR_CTRL" : "general purpose output");
728 msg_pdbg2("LinkSec is %sabled.\n",
729 s->cougar.LINKSEC_DIS ? "en" : "dis");
730 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
731 s->ibex.DMI_REQID_DIS ? "en" : "dis");
732 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
733 1 << (6 + s->ibex.BBBS));
734
735 /* PCHSTRP1 */
736 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
737 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
738
739 /* PCHSTRP2 */
740 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
741 s->ibex.MESMASDEN ? "en" : "dis");
742 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
743 s->ibex.MESMASDA);
744 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
745 s->cougar.MESMMCTPAEN ? "en" : "dis");
746 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
747 s->cougar.MESMMCTPA);
748 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
749 s->ibex.MESMI2CEN ? "en" : "dis");
750 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
751 s->ibex.MESMI2CA);
752
753 /* PCHSTRP3 */
754 prettyprint_ich_descriptor_pchstraps45678_56(s);
755 /* PCHSTRP9 */
756 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
757 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
758 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
759 s->ibex.PCIELR1 ? "" : "not ");
760 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
761 s->ibex.PCIELR2 ? "" : "not ");
762 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
763 s->ibex.DMILR ? "" : "not ");
764 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
765 s->cougar.MDSMBE_EN ? "en" : "dis");
766 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
767 s->cougar.MDSMBE_ADD);
768 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
769 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
770 s->ibex.PHY_PCIE_EN ? "en" : "dis");
771 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
772 s->cougar.SUB_DECODE_EN ? "en" : "dis");
773 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
774 "PCHHOT#" : "SML1ALERT#");
775
776 /* PCHSTRP10 */
777 msg_pdbg2("Management Engine will boot from %sflash.\n",
778 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
779
780 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
781 s->cougar.MDSMBE_EN ? "en" : "dis");
782 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
783 s->cougar.MDSMBE_ADD);
784
785 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
786 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000787 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
788 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000789 msg_pdbg2("ICC Profile is selected by %s.\n",
790 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
791 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
792 s->cougar.Deep_SX_EN ? "not " : "");
793 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
794 s->cougar.ME_DBG_LAN ? "en" : "dis");
795
796 prettyprint_ich_descriptor_pchstraps111213_56(s);
797
798 /* PCHSTRP14 */
799 /* PCHSTRP15 */
800 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
801 msg_pdbg2("Integrated wired LAN is %sabled.\n",
802 s->cougar.IWL_EN ? "en" : "dis");
803 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
804 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000805 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000806 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
807 "general purpose output" : "SLP_LAN#");
808
809 /* PCHSTRP16 */
810 /* PCHSTRP17 */
811 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
812 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
813 msg_pdbg2("\n");
814}
815
816void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
817{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000818 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000819 msg_pdbg2("=== Softstraps ===\n");
820
Nico Huber519be662018-12-23 20:03:35 +0100821 max_count = MIN(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
Nico Huberd7c75522017-03-29 16:31:49 +0200822 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000823 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200824 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000825 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200826 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000827
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000828 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
829 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000830 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
831 msg_pdbg2("\n");
832
Nico Huber519be662018-12-23 20:03:35 +0100833 max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
Nico Huberd7c75522017-03-29 16:31:49 +0200834 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000835 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
836 desc->content.ISL, max_count);
837 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200838 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000839
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000840 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
841 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000842 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
843 msg_pdbg2("\n");
844
845 switch (cs) {
846 case CHIPSET_ICH8:
847 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
848 msg_pdbg2("Detailed North/MCH/PROC information is "
849 "probably not reliable, printing anyway.\n");
850 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
851 msg_pdbg2("Detailed South/ICH/PCH information is "
852 "probably not reliable, printing anyway.\n");
853 prettyprint_ich_descriptor_straps_ich8(desc);
854 break;
855 case CHIPSET_5_SERIES_IBEX_PEAK:
856 /* PCH straps only. PROCSTRPs are unknown. */
857 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
858 msg_pdbg2("Detailed South/ICH/PCH information is "
859 "probably not reliable, printing anyway.\n");
860 prettyprint_ich_descriptor_straps_ibex(&desc->south);
861 break;
862 case CHIPSET_6_SERIES_COUGAR_POINT:
863 /* PCH straps only. PROCSTRP0 is "reserved". */
864 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
865 msg_pdbg2("Detailed South/ICH/PCH information is "
866 "probably not reliable, printing anyway.\n");
867 prettyprint_ich_descriptor_straps_cougar(&desc->south);
868 break;
869 case CHIPSET_ICH_UNKNOWN:
870 break;
871 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000872 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000873 break;
874 }
875}
876
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600877static void prettyprint_rdid(uint32_t reg_val)
Stefan Taunerb3850962011-12-24 00:00:32 +0000878{
879 uint8_t mid = reg_val & 0xFF;
880 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
881 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
882}
883
884void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
885{
886 int i;
887 msg_pdbg2("=== Upper Map Section ===\n");
888 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
889 msg_pdbg2("\n");
890
891 msg_pdbg2("--- Details ---\n");
892 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
893 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
894 msg_pdbg2("\n");
895
896 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000897 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000898 uint32_t jid = umap->vscc_table[i].JID;
899 uint32_t vscc = umap->vscc_table[i].VSCC;
900 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
901 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
902 msg_pdbg2(" "); /* indention */
903 prettyprint_rdid(jid);
904 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000905 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000906 }
907 msg_pdbg2("\n");
908}
909
Nico Huber964007a2021-06-17 21:12:47 +0200910static inline void warn_peculiar_desc(const bool warn_if, const char *const name)
911{
912 if (!warn_if)
913 return;
914 msg_pwarn("Peculiar flash descriptor, assuming %s compatibility.\n", name);
915}
916
Nico Huber1dc3d422017-06-17 00:09:31 +0200917/*
918 * Guesses a minimum chipset version based on the maximum number of
919 * soft straps per generation.
920 */
921static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
922{
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;
Nico Huber83b01c82021-06-17 21:20:09 +0200930 if (content->ISL <= 16)
Nico Huber1dc3d422017-06-17 00:09:31 +0200931 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber83b01c82021-06-17 21:20:09 +0200932 if (content->FLMAP2 == 0) {
Angel Pons4db0fdf2020-07-10 17:04:10 +0200933 if (content->ISL == 23)
934 return CHIPSET_GEMINI_LAKE;
Nico Huber964007a2021-06-17 21:12:47 +0200935 warn_peculiar_desc(content->ISL != 19, "Apollo Lake");
Nico Huberd2d39932019-01-18 16:49:37 +0100936 return CHIPSET_APOLLO_LAKE;
937 }
Nico Huber964007a2021-06-17 21:12:47 +0200938 warn_peculiar_desc(true, "Ibex Peak");
Nico Huber1dc3d422017-06-17 00:09:31 +0200939 return CHIPSET_5_SERIES_IBEX_PEAK;
940 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
941 if (content->MSL == 0 && content->ISL <= 17)
942 return CHIPSET_BAYTRAIL;
Nico Huber83b01c82021-06-17 21:20:09 +0200943 if (content->MSL <= 1 && content->ISL <= 18)
Nico Huber1dc3d422017-06-17 00:09:31 +0200944 return CHIPSET_6_SERIES_COUGAR_POINT;
Nico Huber83b01c82021-06-17 21:20:09 +0200945 if (content->MSL <= 1 && content->ISL <= 21)
Nico Huber1dc3d422017-06-17 00:09:31 +0200946 return CHIPSET_8_SERIES_LYNX_POINT;
Nico Huber964007a2021-06-17 21:12:47 +0200947 warn_peculiar_desc(true, "Wildcat Point");
Nico Huber1dc3d422017-06-17 00:09:31 +0200948 return CHIPSET_9_SERIES_WILDCAT_POINT;
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200949 } else if (content->ICCRIBA < 0x34) {
950 if (content->NM == 6)
951 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber83b01c82021-06-17 21:20:09 +0200952 return CHIPSET_100_SERIES_SUNRISE_POINT;
Jonathan Zhange19a41b2020-08-19 12:19:06 -0700953 } else if (content->ICCRIBA == 0x34) {
954 if (content->NM == 6)
955 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber83b01c82021-06-17 21:20:09 +0200956 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200957 } else {
Nico Huber964007a2021-06-17 21:12:47 +0200958 msg_pwarn("Unknown flash descriptor, assuming 300 series compatibility.\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200959 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200960 }
961}
962
963/*
964 * As an additional measure, we check the read frequency like `ifdtool`.
965 * The frequency value 6 (17MHz) was reserved before Skylake and is the
966 * only valid value since. Skylake is currently the most important dis-
967 * tinction because of the dropped number of regions field (NR).
968 */
Nico Huberfa622942017-03-24 17:25:37 +0100969static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
970 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200971{
972 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
973
Nico Huberd2d39932019-01-18 16:49:37 +0100974 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200975 case CHIPSET_300_SERIES_CANNON_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200976 case CHIPSET_GEMINI_LAKE:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200977 /* `freq_read` was repurposed, so can't check on it any more. */
978 return guess;
Nico Huberd2d39932019-01-18 16:49:37 +0100979 case CHIPSET_100_SERIES_SUNRISE_POINT:
980 case CHIPSET_C620_SERIES_LEWISBURG:
981 case CHIPSET_APOLLO_LAKE:
982 if (component->modes.freq_read != 6) {
Nico Huber964007a2021-06-17 21:12:47 +0200983 msg_pwarn("\nThe flash descriptor looks like a Skylake/Sunrise Point descriptor.\n"
Nico Huberd2d39932019-01-18 16:49:37 +0100984 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
985 "Please report this message, the output of `ich_descriptors_tool` for\n"
986 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
987 return CHIPSET_9_SERIES_WILDCAT_POINT;
988 }
989 return guess;
990 default:
991 if (component->modes.freq_read == 6) {
Nico Huber964007a2021-06-17 21:12:47 +0200992 msg_pwarn("\nThe flash descriptor has the read frequency set to 17MHz. However,\n"
Nico Huber1dc3d422017-06-17 00:09:31 +0200993 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
994 "Please report this message, the output of `ich_descriptors_tool` for\n"
995 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -0700996 return CHIPSET_100_SERIES_SUNRISE_POINT;
997 }
998 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +0200999 }
Nico Huber1dc3d422017-06-17 00:09:31 +02001000}
1001
Stefan Taunerb3850962011-12-24 00:00:32 +00001002/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +01001003int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
1004 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +00001005{
Nico Huber519be662018-12-23 20:03:35 +01001006 ssize_t i, max_count;
1007 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +00001008
1009 if (dump == NULL || desc == NULL)
1010 return ICH_RET_PARAM;
1011
1012 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1013 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1014 pch_bug_offset = 4;
1015 else
1016 return ICH_RET_ERR;
1017 }
1018
1019 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001020 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001021 return ICH_RET_OOB;
1022 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1023 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1024 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1025 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1026
1027 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001028 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001029 return ICH_RET_OOB;
1030 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1031 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1032 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1033
Nico Huber8a03c902021-06-17 21:23:29 +02001034 /* upper map */
1035 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1036
1037 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1038 * "Identifies the 1s based number of DWORDS contained in the VSCC
1039 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1040 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1041 * check ensures that the maximum offset actually accessed is available.
1042 */
1043 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
1044 return ICH_RET_OOB;
1045
1046 for (i = 0; i < desc->upper.VTL/2; i++) {
1047 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1048 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
1049 }
1050
Nico Huber67d71792017-06-17 03:10:15 +02001051 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +01001052 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +02001053 prettyprint_ich_chipset(*cs);
1054 }
Nico Huberfa622942017-03-24 17:25:37 +01001055
Stefan Taunerb3850962011-12-24 00:00:32 +00001056 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001057 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001058 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001059 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001060 for (i = 0; i < nr; i++)
1061 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001062
1063 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001064 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001065 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001066 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001067 for (i = 0; i < nm; i++)
1068 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001069
Stefan Taunerb3850962011-12-24 00:00:32 +00001070 /* MCH/PROC (aka. North) straps */
1071 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1072 return ICH_RET_OOB;
1073
1074 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001075 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001076 for (i = 0; i < max_count; i++)
1077 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001078
1079 /* ICH/PCH (aka. South) straps */
1080 if (len < getFISBA(&desc->content) + desc->content.ISL * 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->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001085 for (i = 0; i < max_count; i++)
1086 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001087
1088 return ICH_RET_OK;
1089}
1090
Nico Huberad186312016-05-02 15:15:29 +02001091#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001092
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001093/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001094\em idx in bytes or -1 if the correct size can not be determined. */
1095int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001096{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001097 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001098 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001099 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001100 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001101
1102 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001103 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001104
1105 uint8_t size_enc;
1106 uint8_t size_max;
1107
1108 switch (cs) {
1109 case CHIPSET_ICH8:
1110 case CHIPSET_ICH9:
1111 case CHIPSET_ICH10:
1112 case CHIPSET_5_SERIES_IBEX_PEAK:
1113 case CHIPSET_6_SERIES_COUGAR_POINT:
1114 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001115 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001116 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001117 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001118 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001119 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001120 }
1121 size_max = 5;
1122 break;
1123 case CHIPSET_8_SERIES_LYNX_POINT:
1124 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1125 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001126 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001127 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001128 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001129 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001130 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001131 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001132 case CHIPSET_GEMINI_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001133 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001134 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001135 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001136 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001137 }
1138 size_max = 7;
1139 break;
1140 case CHIPSET_ICH_UNKNOWN:
1141 default:
1142 msg_pwarn("Density encoding is unknown on this chipset.\n");
1143 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001144 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001145
1146 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001147 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001148 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1149 idx, size_enc, size_max);
1150 return -1;
1151 }
1152
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001153 return (1 << (19 + size_enc));
1154}
1155
Nico Huber8d494992017-06-19 12:18:33 +02001156/* Only used by ichspi.c */
1157#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001158static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001159{
1160 uint32_t control = 0;
1161 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1162 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001163 switch (cs) {
1164 case CHIPSET_100_SERIES_SUNRISE_POINT:
1165 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001166 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001167 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001168 case CHIPSET_GEMINI_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001169 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1170 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001171 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001172 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1173 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1174 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001175}
1176
Nico Huberd54e4f42017-03-23 23:45:47 +01001177int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001178{
Nico Huber519be662018-12-23 20:03:35 +01001179 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001180 struct ich_desc_region *r = &desc->region;
1181
1182 /* Test if bit-fields are working as expected.
1183 * FIXME: Replace this with dynamic bitfield fixup
1184 */
1185 for (i = 0; i < 4; i++)
1186 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001187 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1188 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1189 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1190 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001191 msg_pdbg("The combination of compiler and CPU architecture used"
1192 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001193 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1194 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1195 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1196 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1197 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1198 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1199 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1200 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001201 return ICH_RET_ERR;
1202 }
1203
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001204 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001205 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001206 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1207 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1208 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1209 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001210
1211 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001212 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1213 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1214 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001215
1216 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001217 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1218 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001219 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001220 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001221 return ICH_RET_ERR;
1222 }
Nico Huberfa622942017-03-24 17:25:37 +01001223 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001224 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001225
1226 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001227 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1228 if (nm < 0) {
1229 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1230 __func__, desc->content.NM + 1);
1231 return ICH_RET_ERR;
1232 }
1233 for (i = 0; i < nm; i++)
1234 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001235
1236 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1237 * reading the upper map is impossible on all chipsets, so don't bother.
1238 */
1239
1240 msg_pdbg2(" done.\n");
1241 return ICH_RET_OK;
1242}
Nico Huber8d494992017-06-19 12:18:33 +02001243#endif
Nico Huber305f4172013-06-14 11:55:26 +02001244
1245/**
1246 * @brief Read a layout from the dump of an Intel ICH descriptor.
1247 *
1248 * @param layout Pointer where to store the layout.
1249 * @param dump The descriptor dump to read from.
1250 * @param len The length of the descriptor dump.
1251 *
1252 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001253 * 1 if the descriptor couldn't be parsed,
1254 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001255 */
1256int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1257{
Nico Huberfa622942017-03-24 17:25:37 +01001258 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001259 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1260 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001261 };
Nico Huber305f4172013-06-14 11:55:26 +02001262
1263 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001264 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1265 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001266 return 1;
1267
1268 memset(layout, 0x00, sizeof(*layout));
1269
Nico Huberfa622942017-03-24 17:25:37 +01001270 ssize_t i, j;
Nico Huber519be662018-12-23 20:03:35 +01001271 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
1272 for (i = 0, j = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001273 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001274 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001275 if (limit <= base)
1276 continue;
1277 layout->entries[j].start = base;
1278 layout->entries[j].end = limit;
1279 layout->entries[j].included = false;
Nico Huber70461a92019-06-15 14:56:19 +02001280 layout->entries[j].name = strdup(regions[i]);
1281 if (!layout->entries[j].name)
1282 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001283 ++j;
1284 }
1285 layout->base.entries = layout->entries;
1286 layout->base.num_entries = j;
1287 return 0;
1288}
1289
Nico Huberad186312016-05-02 15:15:29 +02001290#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */