blob: a1fed0fdf7c1abd712c89c851581edb39b621e52 [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 Huber1dc3d422017-06-17 00:09:31 +0200910/*
911 * Guesses a minimum chipset version based on the maximum number of
912 * soft straps per generation.
913 */
914static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
915{
916 if (content->ICCRIBA == 0x00) {
917 if (content->MSL == 0 && content->ISL <= 2)
918 return CHIPSET_ICH8;
919 else if (content->ISL <= 2)
920 return CHIPSET_ICH9;
921 else if (content->ISL <= 10)
922 return CHIPSET_ICH10;
923 else if (content->ISL <= 16)
924 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huberd2d39932019-01-18 16:49:37 +0100925 else if (content->FLMAP2 == 0) {
Angel Pons4db0fdf2020-07-10 17:04:10 +0200926 if (content->ISL == 23)
927 return CHIPSET_GEMINI_LAKE;
928 else if (content->ISL != 19)
Nico Huberd2d39932019-01-18 16:49:37 +0100929 msg_pwarn("Peculiar firmware descriptor, assuming Apollo Lake compatibility.\n");
930 return CHIPSET_APOLLO_LAKE;
931 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200932 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
933 return CHIPSET_5_SERIES_IBEX_PEAK;
934 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
935 if (content->MSL == 0 && content->ISL <= 17)
936 return CHIPSET_BAYTRAIL;
937 else if (content->MSL <= 1 && content->ISL <= 18)
938 return CHIPSET_6_SERIES_COUGAR_POINT;
939 else if (content->MSL <= 1 && content->ISL <= 21)
940 return CHIPSET_8_SERIES_LYNX_POINT;
941 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
942 return CHIPSET_9_SERIES_WILDCAT_POINT;
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200943 } else if (content->ICCRIBA < 0x34) {
944 if (content->NM == 6)
945 return CHIPSET_C620_SERIES_LEWISBURG;
946 else
947 return CHIPSET_100_SERIES_SUNRISE_POINT;
Jonathan Zhange19a41b2020-08-19 12:19:06 -0700948 } else if (content->ICCRIBA == 0x34) {
949 if (content->NM == 6)
950 return CHIPSET_C620_SERIES_LEWISBURG;
951 else
952 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200953 } else {
Jonathan Zhange19a41b2020-08-19 12:19:06 -0700954 msg_pwarn("Unknown firmware descriptor, assuming 300 series compatibility.\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200955 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200956 }
957}
958
959/*
960 * As an additional measure, we check the read frequency like `ifdtool`.
961 * The frequency value 6 (17MHz) was reserved before Skylake and is the
962 * only valid value since. Skylake is currently the most important dis-
963 * tinction because of the dropped number of regions field (NR).
964 */
Nico Huberfa622942017-03-24 17:25:37 +0100965static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
966 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200967{
968 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
969
Nico Huberd2d39932019-01-18 16:49:37 +0100970 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200971 case CHIPSET_300_SERIES_CANNON_POINT:
Angel Pons4db0fdf2020-07-10 17:04:10 +0200972 case CHIPSET_GEMINI_LAKE:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200973 /* `freq_read` was repurposed, so can't check on it any more. */
974 return guess;
Nico Huberd2d39932019-01-18 16:49:37 +0100975 case CHIPSET_100_SERIES_SUNRISE_POINT:
976 case CHIPSET_C620_SERIES_LEWISBURG:
977 case CHIPSET_APOLLO_LAKE:
978 if (component->modes.freq_read != 6) {
979 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
980 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
981 "Please report this message, the output of `ich_descriptors_tool` for\n"
982 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
983 return CHIPSET_9_SERIES_WILDCAT_POINT;
984 }
985 return guess;
986 default:
987 if (component->modes.freq_read == 6) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200988 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
989 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
990 "Please report this message, the output of `ich_descriptors_tool` for\n"
991 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -0700992 return CHIPSET_100_SERIES_SUNRISE_POINT;
993 }
994 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +0200995 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200996}
997
Stefan Taunerb3850962011-12-24 00:00:32 +0000998/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +0100999int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
1000 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +00001001{
Nico Huber519be662018-12-23 20:03:35 +01001002 ssize_t i, max_count;
1003 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +00001004
1005 if (dump == NULL || desc == NULL)
1006 return ICH_RET_PARAM;
1007
1008 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1009 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1010 pch_bug_offset = 4;
1011 else
1012 return ICH_RET_ERR;
1013 }
1014
1015 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001016 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001017 return ICH_RET_OOB;
1018 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1019 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1020 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1021 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1022
1023 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001024 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001025 return ICH_RET_OOB;
1026 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1027 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1028 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1029
Nico Huber67d71792017-06-17 03:10:15 +02001030 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +01001031 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +02001032 prettyprint_ich_chipset(*cs);
1033 }
Nico Huberfa622942017-03-24 17:25:37 +01001034
Stefan Taunerb3850962011-12-24 00:00:32 +00001035 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001036 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001037 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001038 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001039 for (i = 0; i < nr; i++)
1040 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001041
1042 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001043 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001044 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001045 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001046 for (i = 0; i < nm; i++)
1047 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001048
1049 /* upper map */
1050 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1051
1052 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1053 * "Identifies the 1s based number of DWORDS contained in the VSCC
1054 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1055 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1056 * check ensures that the maximum offset actually accessed is available.
1057 */
Nico Huber9e14aed2017-03-28 17:08:46 +02001058 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +00001059 return ICH_RET_OOB;
1060
1061 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001062 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1063 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +00001064 }
1065
1066 /* MCH/PROC (aka. North) straps */
1067 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1068 return ICH_RET_OOB;
1069
1070 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001071 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001072 for (i = 0; i < max_count; i++)
1073 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001074
1075 /* ICH/PCH (aka. South) straps */
1076 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1077 return ICH_RET_OOB;
1078
1079 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001080 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001081 for (i = 0; i < max_count; i++)
1082 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001083
1084 return ICH_RET_OK;
1085}
1086
Nico Huberad186312016-05-02 15:15:29 +02001087#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001088
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001089/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001090\em idx in bytes or -1 if the correct size can not be determined. */
1091int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001092{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001093 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001094 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001095 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001096 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001097
1098 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001099 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001100
1101 uint8_t size_enc;
1102 uint8_t size_max;
1103
1104 switch (cs) {
1105 case CHIPSET_ICH8:
1106 case CHIPSET_ICH9:
1107 case CHIPSET_ICH10:
1108 case CHIPSET_5_SERIES_IBEX_PEAK:
1109 case CHIPSET_6_SERIES_COUGAR_POINT:
1110 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001111 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001112 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001113 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001114 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001115 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001116 }
1117 size_max = 5;
1118 break;
1119 case CHIPSET_8_SERIES_LYNX_POINT:
1120 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1121 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001122 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001123 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001124 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001125 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001126 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001127 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001128 case CHIPSET_GEMINI_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001129 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001130 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001131 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001132 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001133 }
1134 size_max = 7;
1135 break;
1136 case CHIPSET_ICH_UNKNOWN:
1137 default:
1138 msg_pwarn("Density encoding is unknown on this chipset.\n");
1139 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001140 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001141
1142 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001143 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001144 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1145 idx, size_enc, size_max);
1146 return -1;
1147 }
1148
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001149 return (1 << (19 + size_enc));
1150}
1151
Nico Huber8d494992017-06-19 12:18:33 +02001152/* Only used by ichspi.c */
1153#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001154static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001155{
1156 uint32_t control = 0;
1157 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1158 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001159 switch (cs) {
1160 case CHIPSET_100_SERIES_SUNRISE_POINT:
1161 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001162 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001163 case CHIPSET_APOLLO_LAKE:
Angel Pons4db0fdf2020-07-10 17:04:10 +02001164 case CHIPSET_GEMINI_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001165 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1166 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001167 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001168 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1169 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1170 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001171}
1172
Nico Huberd54e4f42017-03-23 23:45:47 +01001173int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001174{
Nico Huber519be662018-12-23 20:03:35 +01001175 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001176 struct ich_desc_region *r = &desc->region;
1177
1178 /* Test if bit-fields are working as expected.
1179 * FIXME: Replace this with dynamic bitfield fixup
1180 */
1181 for (i = 0; i < 4; i++)
1182 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001183 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1184 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1185 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1186 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001187 msg_pdbg("The combination of compiler and CPU architecture used"
1188 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001189 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1190 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1191 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1192 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1193 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1194 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1195 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1196 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001197 return ICH_RET_ERR;
1198 }
1199
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001200 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001201 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001202 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1203 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1204 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1205 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001206
1207 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001208 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1209 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1210 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001211
1212 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001213 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1214 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001215 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001216 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001217 return ICH_RET_ERR;
1218 }
Nico Huberfa622942017-03-24 17:25:37 +01001219 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001220 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001221
1222 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001223 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1224 if (nm < 0) {
1225 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1226 __func__, desc->content.NM + 1);
1227 return ICH_RET_ERR;
1228 }
1229 for (i = 0; i < nm; i++)
1230 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001231
1232 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1233 * reading the upper map is impossible on all chipsets, so don't bother.
1234 */
1235
1236 msg_pdbg2(" done.\n");
1237 return ICH_RET_OK;
1238}
Nico Huber8d494992017-06-19 12:18:33 +02001239#endif
Nico Huber305f4172013-06-14 11:55:26 +02001240
1241/**
1242 * @brief Read a layout from the dump of an Intel ICH descriptor.
1243 *
1244 * @param layout Pointer where to store the layout.
1245 * @param dump The descriptor dump to read from.
1246 * @param len The length of the descriptor dump.
1247 *
1248 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001249 * 1 if the descriptor couldn't be parsed,
1250 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001251 */
1252int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1253{
Nico Huberfa622942017-03-24 17:25:37 +01001254 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001255 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1256 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001257 };
Nico Huber305f4172013-06-14 11:55:26 +02001258
1259 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001260 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1261 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001262 return 1;
1263
1264 memset(layout, 0x00, sizeof(*layout));
1265
Nico Huberfa622942017-03-24 17:25:37 +01001266 ssize_t i, j;
Nico Huber519be662018-12-23 20:03:35 +01001267 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
1268 for (i = 0, j = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001269 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001270 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001271 if (limit <= base)
1272 continue;
1273 layout->entries[j].start = base;
1274 layout->entries[j].end = limit;
1275 layout->entries[j].included = false;
Nico Huber70461a92019-06-15 14:56:19 +02001276 layout->entries[j].name = strdup(regions[i]);
1277 if (!layout->entries[j].name)
1278 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001279 ++j;
1280 }
1281 layout->base.entries = layout->entries;
1282 layout->base.num_entries = j;
1283 return 0;
1284}
1285
Nico Huberad186312016-05-02 15:15:29 +02001286#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */