blob: 1e975fa135f67647450b93e9db63ef692901b441 [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
David Hendricks66565a72021-09-20 21:56:40 -0700910static inline void warn_peculiar_desc(const char *const name)
Nico Huber964007a2021-06-17 21:12:47 +0200911{
Nico Huber964007a2021-06-17 21:12:47 +0200912 msg_pwarn("Peculiar flash descriptor, assuming %s compatibility.\n", name);
913}
914
Nico Huber1dc3d422017-06-17 00:09:31 +0200915/*
916 * Guesses a minimum chipset version based on the maximum number of
Nico Huber3ad9aad2021-06-17 22:05:00 +0200917 * soft straps per generation and presence of the MIP base (MDTBA).
Nico Huber1dc3d422017-06-17 00:09:31 +0200918 */
Nico Huber3ad9aad2021-06-17 22:05:00 +0200919static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content,
920 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +0200921{
922 if (content->ICCRIBA == 0x00) {
923 if (content->MSL == 0 && content->ISL <= 2)
924 return CHIPSET_ICH8;
Nico Huber83b01c82021-06-17 21:20:09 +0200925 if (content->ISL <= 2)
Nico Huber1dc3d422017-06-17 00:09:31 +0200926 return CHIPSET_ICH9;
Nico Huber83b01c82021-06-17 21:20:09 +0200927 if (content->ISL <= 10)
Nico Huber1dc3d422017-06-17 00:09:31 +0200928 return CHIPSET_ICH10;
David Hendricks66565a72021-09-20 21:56:40 -0700929 if (content->ISL <= 16)
930 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber83b01c82021-06-17 21:20:09 +0200931 if (content->FLMAP2 == 0) {
Nico Huber81965f32021-06-17 23:25:35 +0200932 if (content->ISL == 19)
933 return CHIPSET_APOLLO_LAKE;
David Hendricks66565a72021-09-20 21:56:40 -0700934 if (content->ISL == 23)
935 return CHIPSET_GEMINI_LAKE;
936 warn_peculiar_desc("Gemini Lake");
Nico Huber81965f32021-06-17 23:25:35 +0200937 return CHIPSET_GEMINI_LAKE;
Nico Huberd2d39932019-01-18 16:49:37 +0100938 }
Jonathan Zhang3bf7cfb2021-08-30 23:25:06 -0700939 if (content->ISL <= 80)
940 return CHIPSET_C620_SERIES_LEWISBURG;
David Hendricks66565a72021-09-20 21:56:40 -0700941 warn_peculiar_desc("Ibex Peak");
Nico Huber1dc3d422017-06-17 00:09:31 +0200942 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huber3ad9aad2021-06-17 22:05:00 +0200943 } else if (upper->MDTBA == 0x00) {
944 if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
945 if (content->MSL == 0 && content->ISL <= 17)
946 return CHIPSET_BAYTRAIL;
947 if (content->MSL <= 1 && content->ISL <= 18)
948 return CHIPSET_6_SERIES_COUGAR_POINT;
David Hendricks66565a72021-09-20 21:56:40 -0700949 if (content->MSL <= 1 && content->ISL <= 21)
950 return CHIPSET_8_SERIES_LYNX_POINT;
951 warn_peculiar_desc("Lynx Point");
Nico Huber81965f32021-06-17 23:25:35 +0200952 return CHIPSET_8_SERIES_LYNX_POINT;
Nico Huber3ad9aad2021-06-17 22:05:00 +0200953 }
954 if (content->NM == 6) {
David Hendricks66565a72021-09-20 21:56:40 -0700955 if (content->ICCRIBA <= 0x34)
956 return CHIPSET_C620_SERIES_LEWISBURG;
957 warn_peculiar_desc("C620 series");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200958 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber3ad9aad2021-06-17 22:05:00 +0200959 }
David Hendricks66565a72021-09-20 21:56:40 -0700960 if (content->ICCRIBA == 0x31)
961 return CHIPSET_100_SERIES_SUNRISE_POINT;
962 warn_peculiar_desc("100 series");
Nico Huber83b01c82021-06-17 21:20:09 +0200963 return CHIPSET_100_SERIES_SUNRISE_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200964 } else {
David Hendricks66565a72021-09-20 21:56:40 -0700965 if (content->ICCRIBA == 0x34)
966 return CHIPSET_300_SERIES_CANNON_POINT;
967 msg_pwarn("Unknown flash descriptor, assuming 300 series compatibility.\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200968 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200969 }
970}
971
972/*
973 * As an additional measure, we check the read frequency like `ifdtool`.
974 * The frequency value 6 (17MHz) was reserved before Skylake and is the
975 * only valid value since. Skylake is currently the most important dis-
976 * tinction because of the dropped number of regions field (NR).
977 */
Nico Huberfa622942017-03-24 17:25:37 +0100978static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
Nico Huber3ad9aad2021-06-17 22:05:00 +0200979 const struct ich_desc_component *const component,
980 const struct ich_desc_upper_map *const upper)
Nico Huber1dc3d422017-06-17 00:09:31 +0200981{
Nico Huber3ad9aad2021-06-17 22:05:00 +0200982 const enum ich_chipset guess = guess_ich_chipset_from_content(content, upper);
Nico Huber1dc3d422017-06-17 00:09:31 +0200983
Nico Huberd2d39932019-01-18 16:49:37 +0100984 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200985 case CHIPSET_300_SERIES_CANNON_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200986 case CHIPSET_GEMINI_LAKE:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200987 /* `freq_read` was repurposed, so can't check on it any more. */
Nico Huber72a9dc02021-06-17 22:47:00 +0200988 break;
Nico Huberd2d39932019-01-18 16:49:37 +0100989 case CHIPSET_100_SERIES_SUNRISE_POINT:
990 case CHIPSET_C620_SERIES_LEWISBURG:
991 case CHIPSET_APOLLO_LAKE:
992 if (component->modes.freq_read != 6) {
Nico Huber964007a2021-06-17 21:12:47 +0200993 msg_pwarn("\nThe flash descriptor looks like a Skylake/Sunrise Point descriptor.\n"
Nico Huberd2d39932019-01-18 16:49:37 +0100994 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
995 "Please report this message, the output of `ich_descriptors_tool` for\n"
996 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
Nico Huberd2d39932019-01-18 16:49:37 +0100997 }
Nico Huber72a9dc02021-06-17 22:47:00 +0200998 break;
Nico Huberd2d39932019-01-18 16:49:37 +0100999 default:
1000 if (component->modes.freq_read == 6) {
Nico Huber964007a2021-06-17 21:12:47 +02001001 msg_pwarn("\nThe flash descriptor has the read frequency set to 17MHz. However,\n"
Nico Huber1dc3d422017-06-17 00:09:31 +02001002 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
1003 "Please report this message, the output of `ich_descriptors_tool` for\n"
1004 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -07001005 }
Nico Huber1dc3d422017-06-17 00:09:31 +02001006 }
Nico Huber72a9dc02021-06-17 22:47:00 +02001007 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +02001008}
1009
Stefan Taunerb3850962011-12-24 00:00:32 +00001010/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +01001011int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
1012 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +00001013{
Nico Huber519be662018-12-23 20:03:35 +01001014 ssize_t i, max_count;
1015 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +00001016
1017 if (dump == NULL || desc == NULL)
1018 return ICH_RET_PARAM;
1019
1020 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1021 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1022 pch_bug_offset = 4;
1023 else
1024 return ICH_RET_ERR;
1025 }
1026
1027 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001028 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001029 return ICH_RET_OOB;
1030 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1031 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1032 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1033 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1034
1035 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001036 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001037 return ICH_RET_OOB;
1038 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1039 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1040 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1041
Nico Huber8a03c902021-06-17 21:23:29 +02001042 /* upper map */
1043 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1044
1045 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1046 * "Identifies the 1s based number of DWORDS contained in the VSCC
1047 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1048 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1049 * check ensures that the maximum offset actually accessed is available.
1050 */
1051 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
1052 return ICH_RET_OOB;
1053
1054 for (i = 0; i < desc->upper.VTL/2; i++) {
1055 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1056 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
1057 }
1058
Nico Huber67d71792017-06-17 03:10:15 +02001059 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huber3ad9aad2021-06-17 22:05:00 +02001060 *cs = guess_ich_chipset(&desc->content, &desc->component, &desc->upper);
Nico Huber67d71792017-06-17 03:10:15 +02001061 prettyprint_ich_chipset(*cs);
1062 }
Nico Huberfa622942017-03-24 17:25:37 +01001063
Stefan Taunerb3850962011-12-24 00:00:32 +00001064 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001065 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001066 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001067 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001068 for (i = 0; i < nr; i++)
1069 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001070
1071 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001072 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001073 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001074 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001075 for (i = 0; i < nm; i++)
1076 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001077
Stefan Taunerb3850962011-12-24 00:00:32 +00001078 /* MCH/PROC (aka. North) straps */
1079 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1080 return ICH_RET_OOB;
1081
1082 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001083 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001084 for (i = 0; i < max_count; i++)
1085 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001086
1087 /* ICH/PCH (aka. South) straps */
1088 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1089 return ICH_RET_OOB;
1090
1091 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001092 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001093 for (i = 0; i < max_count; i++)
1094 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001095
1096 return ICH_RET_OK;
1097}
1098
Nico Huberad186312016-05-02 15:15:29 +02001099#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001100
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001101/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001102\em idx in bytes or -1 if the correct size can not be determined. */
1103int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001104{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001105 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001106 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001107 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001108 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001109
1110 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001111 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001112
1113 uint8_t size_enc;
1114 uint8_t size_max;
1115
1116 switch (cs) {
1117 case CHIPSET_ICH8:
1118 case CHIPSET_ICH9:
1119 case CHIPSET_ICH10:
1120 case CHIPSET_5_SERIES_IBEX_PEAK:
1121 case CHIPSET_6_SERIES_COUGAR_POINT:
1122 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001123 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001124 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001125 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001126 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001127 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001128 }
1129 size_max = 5;
1130 break;
1131 case CHIPSET_8_SERIES_LYNX_POINT:
1132 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1133 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001134 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001135 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001136 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001137 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001138 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001139 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001140 case CHIPSET_GEMINI_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001141 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001142 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001143 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001144 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001145 }
1146 size_max = 7;
1147 break;
1148 case CHIPSET_ICH_UNKNOWN:
1149 default:
1150 msg_pwarn("Density encoding is unknown on this chipset.\n");
1151 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001152 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001153
1154 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001155 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001156 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1157 idx, size_enc, size_max);
1158 return -1;
1159 }
1160
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001161 return (1 << (19 + size_enc));
1162}
1163
Nico Huber8d494992017-06-19 12:18:33 +02001164/* Only used by ichspi.c */
1165#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001166static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001167{
1168 uint32_t control = 0;
1169 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1170 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001171 switch (cs) {
1172 case CHIPSET_100_SERIES_SUNRISE_POINT:
1173 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001174 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001175 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001176 case CHIPSET_GEMINI_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001177 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1178 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001179 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001180 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1181 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1182 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001183}
1184
Nico Huberd54e4f42017-03-23 23:45:47 +01001185int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001186{
Nico Huber519be662018-12-23 20:03:35 +01001187 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001188 struct ich_desc_region *r = &desc->region;
1189
1190 /* Test if bit-fields are working as expected.
1191 * FIXME: Replace this with dynamic bitfield fixup
1192 */
1193 for (i = 0; i < 4; i++)
1194 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001195 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1196 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1197 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1198 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001199 msg_pdbg("The combination of compiler and CPU architecture used"
1200 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001201 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1202 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1203 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1204 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1205 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1206 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1207 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1208 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001209 return ICH_RET_ERR;
1210 }
1211
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001212 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001213 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001214 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1215 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1216 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1217 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001218
1219 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001220 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1221 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1222 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001223
1224 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001225 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1226 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001227 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001228 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001229 return ICH_RET_ERR;
1230 }
Nico Huberfa622942017-03-24 17:25:37 +01001231 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001232 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001233
1234 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001235 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1236 if (nm < 0) {
1237 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1238 __func__, desc->content.NM + 1);
1239 return ICH_RET_ERR;
1240 }
1241 for (i = 0; i < nm; i++)
1242 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001243
1244 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1245 * reading the upper map is impossible on all chipsets, so don't bother.
1246 */
1247
1248 msg_pdbg2(" done.\n");
1249 return ICH_RET_OK;
1250}
Nico Huber8d494992017-06-19 12:18:33 +02001251#endif
Nico Huber305f4172013-06-14 11:55:26 +02001252
1253/**
1254 * @brief Read a layout from the dump of an Intel ICH descriptor.
1255 *
1256 * @param layout Pointer where to store the layout.
1257 * @param dump The descriptor dump to read from.
1258 * @param len The length of the descriptor dump.
1259 *
1260 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001261 * 1 if the descriptor couldn't be parsed,
1262 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001263 */
1264int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1265{
Nico Huberfa622942017-03-24 17:25:37 +01001266 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001267 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1268 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001269 };
Nico Huber305f4172013-06-14 11:55:26 +02001270
1271 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001272 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1273 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001274 return 1;
1275
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 */