blob: 684b84546f4e14bb74f69a224cd787bfe4bab13c [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:
42 return 6;
David Hendricksa5216362017-08-08 20:02:22 -070043 case CHIPSET_C620_SERIES_LEWISBURG:
44 return 16;
Nico Huberfa622942017-03-24 17:25:37 +010045 case CHIPSET_100_SERIES_SUNRISE_POINT:
46 return 10;
47 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
48 case CHIPSET_9_SERIES_WILDCAT_POINT:
49 case CHIPSET_8_SERIES_LYNX_POINT_LP:
50 case CHIPSET_8_SERIES_LYNX_POINT:
51 case CHIPSET_8_SERIES_WELLSBURG:
52 if (cont->NR <= 6)
53 return cont->NR + 1;
54 else
55 return -1;
56 default:
57 if (cont->NR <= 4)
58 return cont->NR + 1;
59 else
60 return -1;
61 }
62}
63
64ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
65{
David Hendricksa5216362017-08-08 20:02:22 -070066 switch (cs) {
67 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberd2d39932019-01-18 16:49:37 +010068 case CHIPSET_APOLLO_LAKE:
David Hendricksa5216362017-08-08 20:02:22 -070069 if (cont->NM <= MAX_NUM_MASTERS)
70 return cont->NM;
Richard Hughesdb7482b2018-12-19 12:04:30 +000071 break;
David Hendricksa5216362017-08-08 20:02:22 -070072 default:
73 if (cont->NM < MAX_NUM_MASTERS)
74 return cont->NM + 1;
75 }
76
77 return -1;
Nico Huberfa622942017-03-24 17:25:37 +010078}
79
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000080void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000081{
82 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
83 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
84 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
85 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000086 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
87 if (print_vcl)
88 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
89 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000090}
91
92#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
93#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
94#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
95#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
96#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
97
Nico Huber67d71792017-06-17 03:10:15 +020098void prettyprint_ich_chipset(enum ich_chipset cs)
99{
100 static const char *const chipset_names[] = {
101 "Unknown ICH", "ICH8", "ICH9", "ICH10",
102 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
103 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
104 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
Nico Huberd2d39932019-01-18 16:49:37 +0100105 "C620 series Lewisburg", "Apollo Lake",
Nico Huber67d71792017-06-17 03:10:15 +0200106 };
107 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
108 cs = 0;
109 else
110 cs = cs - CHIPSET_ICH8 + 1;
111 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
112}
113
Stefan Tauner1e146392011-09-15 23:52:55 +0000114void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
115{
Nico Huberfa622942017-03-24 17:25:37 +0100116 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000117 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100118 prettyprint_ich_descriptor_region(cs, desc);
119 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200120#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000121 if (cs >= CHIPSET_ICH8) {
122 prettyprint_ich_descriptor_upper_map(&desc->upper);
123 prettyprint_ich_descriptor_straps(cs, desc);
124 }
Nico Huberad186312016-05-02 15:15:29 +0200125#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000126}
127
Nico Huberfa622942017-03-24 17:25:37 +0100128void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000129{
130 msg_pdbg2("=== Content Section ===\n");
131 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
132 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
133 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
134 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
135 msg_pdbg2("\n");
136
137 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100138 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
139 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
140 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
141 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
Nico Huberd2d39932019-01-18 16:49:37 +0100142 msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL);
143 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont));
Nico Huberfa622942017-03-24 17:25:37 +0100144 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
145 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
146 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
147 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000148 msg_pdbg2("\n");
149}
150
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000151static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
152{
153 if (idx > 1) {
154 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
155 return NULL;
156 }
157
158 if (desc->content.NC == 0 && idx > 0)
159 return "unused";
160
161 static const char * const size_str[] = {
162 "512 kB", /* 0000 */
163 "1 MB", /* 0001 */
164 "2 MB", /* 0010 */
165 "4 MB", /* 0011 */
166 "8 MB", /* 0100 */
167 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
168 "32 MB", /* 0110 */
169 "64 MB", /* 0111 */
170 };
171
172 switch (cs) {
173 case CHIPSET_ICH8:
174 case CHIPSET_ICH9:
175 case CHIPSET_ICH10:
176 case CHIPSET_5_SERIES_IBEX_PEAK:
177 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000178 case CHIPSET_7_SERIES_PANTHER_POINT:
179 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000180 uint8_t size_enc;
181 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000182 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000183 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000184 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000185 }
186 if (size_enc > 5)
187 return "reserved";
188 return size_str[size_enc];
189 }
190 case CHIPSET_8_SERIES_LYNX_POINT:
191 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000192 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100193 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100194 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
David Hendricksa5216362017-08-08 20:02:22 -0700195 case CHIPSET_100_SERIES_SUNRISE_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100196 case CHIPSET_C620_SERIES_LEWISBURG:
197 case CHIPSET_APOLLO_LAKE: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000198 uint8_t size_enc;
199 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000200 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000201 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000202 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000203 }
204 if (size_enc > 7)
205 return "reserved";
206 return size_str[size_enc];
207 }
208 case CHIPSET_ICH_UNKNOWN:
209 default:
210 return "unknown";
211 }
212}
213
214static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000215{
Nico Huberd2d39932019-01-18 16:49:37 +0100216 static const char *const freq_str[3][8] = { {
Nico Huber129e9382019-06-06 15:43:27 +0200217 "20 MHz",
218 "33 MHz",
219 "reserved",
220 "reserved",
221 "50 MHz", /* New since Ibex Peak */
222 "reserved",
223 "reserved",
224 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100225 }, {
Nico Huber129e9382019-06-06 15:43:27 +0200226 "reserved",
227 "reserved",
228 "48 MHz",
229 "reserved",
230 "30 MHz",
231 "reserved",
232 "17 MHz",
233 "reserved"
Nico Huberd2d39932019-01-18 16:49:37 +0100234 }, {
235 "reserved",
236 "50 MHz",
237 "40 MHz",
238 "reserved",
239 "25 MHz",
240 "reserved",
241 "14 MHz / 17 MHz",
242 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100243 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000244
245 switch (cs) {
246 case CHIPSET_ICH8:
247 case CHIPSET_ICH9:
248 case CHIPSET_ICH10:
249 if (value > 1)
250 return "reserved";
Richard Hughesdb7482b2018-12-19 12:04:30 +0000251 /* Fall through. */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000252 case CHIPSET_5_SERIES_IBEX_PEAK:
253 case CHIPSET_6_SERIES_COUGAR_POINT:
254 case CHIPSET_7_SERIES_PANTHER_POINT:
255 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000256 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000257 case CHIPSET_8_SERIES_LYNX_POINT_LP:
258 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000259 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100260 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100261 return freq_str[0][value];
262 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700263 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberfa622942017-03-24 17:25:37 +0100264 return freq_str[1][value];
Nico Huberd2d39932019-01-18 16:49:37 +0100265 case CHIPSET_APOLLO_LAKE:
266 return freq_str[2][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000267 case CHIPSET_ICH_UNKNOWN:
268 default:
269 return "unknown";
270 }
271}
272
273void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
274{
Nico Huberd2d39932019-01-18 16:49:37 +0100275 bool has_flill1;
276
277 switch (cs) {
278 case CHIPSET_100_SERIES_SUNRISE_POINT:
279 case CHIPSET_C620_SERIES_LEWISBURG:
280 case CHIPSET_APOLLO_LAKE:
281 has_flill1 = true;
282 break;
283 default:
284 has_flill1 = false;
285 break;
286 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000287
288 msg_pdbg2("=== Component Section ===\n");
289 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
290 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberd2d39932019-01-18 16:49:37 +0100291 if (has_flill1)
Nico Huberfa622942017-03-24 17:25:37 +0100292 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000293 msg_pdbg2("\n");
294
295 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000296 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000297 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000298 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000299 else
300 msg_pdbg2("Component 2 is not used.\n");
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000301 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
302 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
303 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
304 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
305 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000306 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000307 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000308 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
309 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000310 desc->component.modes.dual_output ? "dis" : "en");
David Hendricksa5216362017-08-08 20:02:22 -0700311
312 int has_forbidden_opcode = 0;
313 if (desc->component.FLILL != 0) {
314 has_forbidden_opcode = 1;
Stefan Tauner1e146392011-09-15 23:52:55 +0000315 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
316 desc->component.invalid_instr0);
317 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
318 desc->component.invalid_instr1);
319 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
320 desc->component.invalid_instr2);
321 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
322 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700323 }
Nico Huberd2d39932019-01-18 16:49:37 +0100324 if (has_flill1) {
David Hendricksa5216362017-08-08 20:02:22 -0700325 if (desc->component.FLILL1 != 0) {
326 has_forbidden_opcode = 1;
Nico Huberfa622942017-03-24 17:25:37 +0100327 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
328 desc->component.invalid_instr4);
329 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
330 desc->component.invalid_instr5);
331 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
332 desc->component.invalid_instr6);
333 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
334 desc->component.invalid_instr7);
335 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000336 }
David Hendricksa5216362017-08-08 20:02:22 -0700337 if (!has_forbidden_opcode)
338 msg_pdbg2("No forbidden opcodes.\n");
339
Stefan Tauner1e146392011-09-15 23:52:55 +0000340 msg_pdbg2("\n");
341}
342
343static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
344{
Nico Huberfa622942017-03-24 17:25:37 +0100345 static const char *const region_names[] = {
Nico Huberd2d39932019-01-18 16:49:37 +0100346 "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown",
David Hendricksa5216362017-08-08 20:02:22 -0700347 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000348 };
Nico Huberfa622942017-03-24 17:25:37 +0100349 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000350 msg_pdbg2("%s: region index too high.\n", __func__);
351 return;
352 }
353 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
354 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100355 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000356 if (base > limit)
357 msg_pdbg2("is unused.\n");
358 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200359 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000360}
361
Nico Huberfa622942017-03-24 17:25:37 +0100362void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000363{
Nico Huber519be662018-12-23 20:03:35 +0100364 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100365 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000366 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100367 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000368 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100369 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000370 return;
371 }
Nico Huberfa622942017-03-24 17:25:37 +0100372 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100373 msg_pdbg2("FLREG%zd 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000374 msg_pdbg2("\n");
375
376 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100377 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100378 pprint_freg(&desc->region, (uint32_t)i);
Stefan Tauner1e146392011-09-15 23:52:55 +0000379 msg_pdbg2("\n");
380}
381
Nico Huberfa622942017-03-24 17:25:37 +0100382void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000383{
Nico Huber519be662018-12-23 20:03:35 +0100384 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100385 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000386 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100387 if (nm < 0) {
388 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
389 desc->content.NM + 1);
390 return;
391 }
392 for (i = 0; i < nm; i++)
Nico Huber519be662018-12-23 20:03:35 +0100393 msg_pdbg2("FLMSTR%zd 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000394 msg_pdbg2("\n");
395
396 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100397 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
398 const char *const master_names[] = {
399 "BIOS", "ME", "GbE", "unknown", "EC",
400 };
Nico Huber519be662018-12-23 20:03:35 +0100401 if (nm >= (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberfa622942017-03-24 17:25:37 +0100402 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
403 desc->content.NM + 1);
404 return;
405 }
406
407 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9\n");
408 for (i = 0; i < nm; i++) {
409 size_t j;
410 msg_pdbg2("%-4s", master_names[i]);
411 for (j = 0; j < 10; j++)
412 msg_pdbg2(" %c%c ",
413 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
414 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
415 msg_pdbg2("\n");
416 }
David Hendricksa5216362017-08-08 20:02:22 -0700417 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
418 const char *const master_names[] = {
419 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
420 };
421 /* NM starts at 1 instead of 0 for LBG */
Nico Huber519be662018-12-23 20:03:35 +0100422 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
David Hendricksa5216362017-08-08 20:02:22 -0700423 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
424 desc->content.NM);
425 return;
426 }
427
428 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
429 " ", /* width of master name (4 chars minimum) */
430 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
431 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
432 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
433 "Reg15");
434 for (i = 0; i < nm; i++) {
435 size_t j;
436 msg_pdbg2("%-4s", master_names[i]);
437 for (j = 0; j < 16; j++)
438 msg_pdbg2(" %c%c ",
439 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
440 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
441 msg_pdbg2("\n");
442 }
Nico Huberd2d39932019-01-18 16:49:37 +0100443 } else if (cs == CHIPSET_APOLLO_LAKE) {
444 const char *const master_names[] = { "BIOS", "TXE", };
Nico Huber519be662018-12-23 20:03:35 +0100445 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberd2d39932019-01-18 16:49:37 +0100446 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
447 return;
448 }
449
450 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
451 for (i = 0; i < nm; i++) {
Nico Huber519be662018-12-23 20:03:35 +0100452 ssize_t j;
Nico Huberd2d39932019-01-18 16:49:37 +0100453 msg_pdbg2("%-4s", master_names[i]);
454 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
455 msg_pdbg2(" %c%c ",
456 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
457 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
458 msg_pdbg2("\n");
459 }
Nico Huberfa622942017-03-24 17:25:37 +0100460 } else {
461 const struct ich_desc_master *const mstr = &desc->master;
462 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
463 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
464 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
465 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
466 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
467 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
468 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
469 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
470 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
471 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
472 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
473 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
474 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
475 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
476 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
477 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
478 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
479 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
480 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
481 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000482 msg_pdbg2("\n");
483}
484
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600485static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000486{
487 static const char * const str_GPIO12[4] = {
488 "GPIO12",
489 "LAN PHY Power Control Function (Native Output)",
490 "GLAN_DOCK# (Native Input)",
491 "invalid configuration",
492 };
493
494 msg_pdbg2("--- MCH details ---\n");
495 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
496 msg_pdbg2("\n");
497
498 msg_pdbg2("--- ICH details ---\n");
499 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
500 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
501 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
502 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
503 msg_pdbg2("SPI CS1 is used for %s.\n",
504 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
505 "LAN PHY Power Control Function" :
506 "SPI Chip Select");
507 msg_pdbg2("GPIO12 is used as %s.\n",
508 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
509 msg_pdbg2("PCIe Port 6 is used for %s.\n",
510 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
511 msg_pdbg2("%sn BMC Mode: "
512 "Intel AMT SMBus Controller 1 is connected to %s.\n",
513 desc->south.ich8.BMCMODE ? "I" : "Not i",
514 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
515 msg_pdbg2("TCO is in %s Mode.\n",
516 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
517 msg_pdbg2("ME A is %sabled.\n",
518 desc->south.ich8.ME_DISABLE ? "dis" : "en");
519 msg_pdbg2("\n");
520}
521
522static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
523{
524 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
525
526 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000527 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000528 case 0:
529 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
530 break;
531 case 1:
532 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
533 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
534 break;
535 case 2:
536 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
537 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
538 break;
539 case 3:
540 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
541 1+off, 2+off, 4+off);
542 break;
543 }
544 msg_pdbg2("\n");
545}
546
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600547static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000548{
549 /* PCHSTRP4 */
550 msg_pdbg2("Intel PHY is %s.\n",
551 (s->ibex.PHYCON == 2) ? "connected" :
552 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
553 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
554 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
555 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
556 s->ibex.GBEMAC_SMBUS_ADDR);
557 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
558 s->ibex.GBEPHY_SMBUS_ADDR);
559
560 /* PCHSTRP5 */
561 /* PCHSTRP6 */
562 /* PCHSTRP7 */
563 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
564 s->ibex.MESMA2UDID_VENDOR);
565 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
566 s->ibex.MESMA2UDID_VENDOR);
567
568 /* PCHSTRP8 */
569}
570
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600571static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000572{
573 /* PCHSTRP11 */
574 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
575 s->ibex.SML1GPAEN ? "en" : "dis");
576 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
577 s->ibex.SML1GPA);
578 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
579 s->ibex.SML1I2CAEN ? "en" : "dis");
580 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
581 s->ibex.SML1I2CA);
582
583 /* PCHSTRP12 */
584 /* PCHSTRP13 */
585}
586
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600587static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000588{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000589 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000590 100,
591 50,
592 5,
593 1
594 };
595
596 msg_pdbg2("--- PCH ---\n");
597
598 /* PCHSTRP0 */
599 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
600 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
601 s->ibex.SMB_EN ? "en" : "dis");
602 msg_pdbg2("SMLink0 segment is %sabled.\n",
603 s->ibex.SML0_EN ? "en" : "dis");
604 msg_pdbg2("SMLink1 segment is %sabled.\n",
605 s->ibex.SML1_EN ? "en" : "dis");
606 msg_pdbg2("SMLink1 Frequency: %s\n",
607 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
608 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
609 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
610 msg_pdbg2("SMLink0 Frequency: %s\n",
611 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
612 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
613 "LAN_PHY_PWR_CTRL" : "general purpose output");
614 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
615 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
616 s->ibex.DMI_REQID_DIS ? "en" : "dis");
617 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
618 1 << (6 + s->ibex.BBBS));
619
620 /* PCHSTRP1 */
621 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
622
623 /* PCHSTRP2 */
624 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
625 s->ibex.MESMASDEN ? "en" : "dis");
626 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
627 s->ibex.MESMASDA);
628 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
629 s->ibex.MESMI2CEN ? "en" : "dis");
630 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
631 s->ibex.MESMI2CA);
632
633 /* PCHSTRP3 */
634 prettyprint_ich_descriptor_pchstraps45678_56(s);
635 /* PCHSTRP9 */
636 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
637 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
638 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
639 s->ibex.PCIELR1 ? "" : "not ");
640 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
641 s->ibex.PCIELR2 ? "" : "not ");
642 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
643 s->ibex.DMILR ? "" : "not ");
644 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
645 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
646 s->ibex.PHY_PCIE_EN ? "en" : "dis");
647
648 /* PCHSTRP10 */
649 msg_pdbg2("Management Engine will boot from %sflash.\n",
650 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
651 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
652 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
653 s->ibex.VE_EN ? "en" : "dis");
654 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
655 s->ibex.MMDDE ? "en" : "dis");
656 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
657 s->ibex.MMADDR);
658 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
659 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
660 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
661 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
662 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
663
664 prettyprint_ich_descriptor_pchstraps111213_56(s);
665
666 /* PCHSTRP14 */
667 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
668 s->ibex.VE_EN2 ? "en" : "dis");
669 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
670 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
671 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
672 s->ibex.BW_SSD ? "en" : "dis");
673 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
674 s->ibex.NVMHCI_EN ? "en" : "dis");
675
676 /* PCHSTRP15 */
677 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
678 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
679 s->ibex.IWL_EN ? "en" : "dis");
680 msg_pdbg2("t209 min Timing: %d ms\n",
681 dec_t209min[s->ibex.t209min]);
682 msg_pdbg2("\n");
683}
684
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600685static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000686{
687 msg_pdbg2("--- PCH ---\n");
688
689 /* PCHSTRP0 */
690 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
691 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
692 s->ibex.SMB_EN ? "en" : "dis");
693 msg_pdbg2("SMLink0 segment is %sabled.\n",
694 s->ibex.SML0_EN ? "en" : "dis");
695 msg_pdbg2("SMLink1 segment is %sabled.\n",
696 s->ibex.SML1_EN ? "en" : "dis");
697 msg_pdbg2("SMLink1 Frequency: %s\n",
698 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
699 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
700 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
701 msg_pdbg2("SMLink0 Frequency: %s\n",
702 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
703 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
704 "LAN_PHY_PWR_CTRL" : "general purpose output");
705 msg_pdbg2("LinkSec is %sabled.\n",
706 s->cougar.LINKSEC_DIS ? "en" : "dis");
707 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
708 s->ibex.DMI_REQID_DIS ? "en" : "dis");
709 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
710 1 << (6 + s->ibex.BBBS));
711
712 /* PCHSTRP1 */
713 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
714 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
715
716 /* PCHSTRP2 */
717 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
718 s->ibex.MESMASDEN ? "en" : "dis");
719 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
720 s->ibex.MESMASDA);
721 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
722 s->cougar.MESMMCTPAEN ? "en" : "dis");
723 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
724 s->cougar.MESMMCTPA);
725 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
726 s->ibex.MESMI2CEN ? "en" : "dis");
727 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
728 s->ibex.MESMI2CA);
729
730 /* PCHSTRP3 */
731 prettyprint_ich_descriptor_pchstraps45678_56(s);
732 /* PCHSTRP9 */
733 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
734 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
735 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
736 s->ibex.PCIELR1 ? "" : "not ");
737 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
738 s->ibex.PCIELR2 ? "" : "not ");
739 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
740 s->ibex.DMILR ? "" : "not ");
741 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
742 s->cougar.MDSMBE_EN ? "en" : "dis");
743 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
744 s->cougar.MDSMBE_ADD);
745 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
746 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
747 s->ibex.PHY_PCIE_EN ? "en" : "dis");
748 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
749 s->cougar.SUB_DECODE_EN ? "en" : "dis");
750 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
751 "PCHHOT#" : "SML1ALERT#");
752
753 /* PCHSTRP10 */
754 msg_pdbg2("Management Engine will boot from %sflash.\n",
755 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
756
757 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
758 s->cougar.MDSMBE_EN ? "en" : "dis");
759 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
760 s->cougar.MDSMBE_ADD);
761
762 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
763 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000764 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
765 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000766 msg_pdbg2("ICC Profile is selected by %s.\n",
767 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
768 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
769 s->cougar.Deep_SX_EN ? "not " : "");
770 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
771 s->cougar.ME_DBG_LAN ? "en" : "dis");
772
773 prettyprint_ich_descriptor_pchstraps111213_56(s);
774
775 /* PCHSTRP14 */
776 /* PCHSTRP15 */
777 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
778 msg_pdbg2("Integrated wired LAN is %sabled.\n",
779 s->cougar.IWL_EN ? "en" : "dis");
780 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
781 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000782 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000783 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
784 "general purpose output" : "SLP_LAN#");
785
786 /* PCHSTRP16 */
787 /* PCHSTRP17 */
788 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
789 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
790 msg_pdbg2("\n");
791}
792
793void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
794{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000795 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000796 msg_pdbg2("=== Softstraps ===\n");
797
Nico Huber519be662018-12-23 20:03:35 +0100798 max_count = MIN(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
Nico Huberd7c75522017-03-29 16:31:49 +0200799 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000800 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200801 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000802 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200803 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000804
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000805 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
806 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000807 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
808 msg_pdbg2("\n");
809
Nico Huber519be662018-12-23 20:03:35 +0100810 max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
Nico Huberd7c75522017-03-29 16:31:49 +0200811 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000812 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
813 desc->content.ISL, max_count);
814 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200815 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000816
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000817 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
818 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000819 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
820 msg_pdbg2("\n");
821
822 switch (cs) {
823 case CHIPSET_ICH8:
824 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
825 msg_pdbg2("Detailed North/MCH/PROC information is "
826 "probably not reliable, printing anyway.\n");
827 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
828 msg_pdbg2("Detailed South/ICH/PCH information is "
829 "probably not reliable, printing anyway.\n");
830 prettyprint_ich_descriptor_straps_ich8(desc);
831 break;
832 case CHIPSET_5_SERIES_IBEX_PEAK:
833 /* PCH straps only. PROCSTRPs are unknown. */
834 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
835 msg_pdbg2("Detailed South/ICH/PCH information is "
836 "probably not reliable, printing anyway.\n");
837 prettyprint_ich_descriptor_straps_ibex(&desc->south);
838 break;
839 case CHIPSET_6_SERIES_COUGAR_POINT:
840 /* PCH straps only. PROCSTRP0 is "reserved". */
841 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
842 msg_pdbg2("Detailed South/ICH/PCH information is "
843 "probably not reliable, printing anyway.\n");
844 prettyprint_ich_descriptor_straps_cougar(&desc->south);
845 break;
846 case CHIPSET_ICH_UNKNOWN:
847 break;
848 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000849 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000850 break;
851 }
852}
853
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600854static void prettyprint_rdid(uint32_t reg_val)
Stefan Taunerb3850962011-12-24 00:00:32 +0000855{
856 uint8_t mid = reg_val & 0xFF;
857 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
858 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
859}
860
861void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
862{
863 int i;
864 msg_pdbg2("=== Upper Map Section ===\n");
865 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
866 msg_pdbg2("\n");
867
868 msg_pdbg2("--- Details ---\n");
869 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
870 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
871 msg_pdbg2("\n");
872
873 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000874 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000875 uint32_t jid = umap->vscc_table[i].JID;
876 uint32_t vscc = umap->vscc_table[i].VSCC;
877 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
878 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
879 msg_pdbg2(" "); /* indention */
880 prettyprint_rdid(jid);
881 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000882 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000883 }
884 msg_pdbg2("\n");
885}
886
Nico Huber1dc3d422017-06-17 00:09:31 +0200887/*
888 * Guesses a minimum chipset version based on the maximum number of
889 * soft straps per generation.
890 */
891static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
892{
893 if (content->ICCRIBA == 0x00) {
894 if (content->MSL == 0 && content->ISL <= 2)
895 return CHIPSET_ICH8;
896 else if (content->ISL <= 2)
897 return CHIPSET_ICH9;
898 else if (content->ISL <= 10)
899 return CHIPSET_ICH10;
900 else if (content->ISL <= 16)
901 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huberd2d39932019-01-18 16:49:37 +0100902 else if (content->FLMAP2 == 0) {
903 if (content->ISL != 19)
904 msg_pwarn("Peculiar firmware descriptor, assuming Apollo Lake compatibility.\n");
905 return CHIPSET_APOLLO_LAKE;
906 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200907 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
908 return CHIPSET_5_SERIES_IBEX_PEAK;
909 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
910 if (content->MSL == 0 && content->ISL <= 17)
911 return CHIPSET_BAYTRAIL;
912 else if (content->MSL <= 1 && content->ISL <= 18)
913 return CHIPSET_6_SERIES_COUGAR_POINT;
914 else if (content->MSL <= 1 && content->ISL <= 21)
915 return CHIPSET_8_SERIES_LYNX_POINT;
916 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
917 return CHIPSET_9_SERIES_WILDCAT_POINT;
David Hendricksa5216362017-08-08 20:02:22 -0700918 } else if (content->NM == 6) {
919 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber1dc3d422017-06-17 00:09:31 +0200920 } else {
921 return CHIPSET_100_SERIES_SUNRISE_POINT;
922 }
923}
924
925/*
926 * As an additional measure, we check the read frequency like `ifdtool`.
927 * The frequency value 6 (17MHz) was reserved before Skylake and is the
928 * only valid value since. Skylake is currently the most important dis-
929 * tinction because of the dropped number of regions field (NR).
930 */
Nico Huberfa622942017-03-24 17:25:37 +0100931static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
932 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200933{
934 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
935
Nico Huberd2d39932019-01-18 16:49:37 +0100936 switch (guess) {
937 case CHIPSET_100_SERIES_SUNRISE_POINT:
938 case CHIPSET_C620_SERIES_LEWISBURG:
939 case CHIPSET_APOLLO_LAKE:
940 if (component->modes.freq_read != 6) {
941 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
942 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
943 "Please report this message, the output of `ich_descriptors_tool` for\n"
944 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
945 return CHIPSET_9_SERIES_WILDCAT_POINT;
946 }
947 return guess;
948 default:
949 if (component->modes.freq_read == 6) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200950 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
951 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
952 "Please report this message, the output of `ich_descriptors_tool` for\n"
953 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -0700954 return CHIPSET_100_SERIES_SUNRISE_POINT;
955 }
956 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +0200957 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200958}
959
Stefan Taunerb3850962011-12-24 00:00:32 +0000960/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +0100961int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
962 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000963{
Nico Huber519be662018-12-23 20:03:35 +0100964 ssize_t i, max_count;
965 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +0000966
967 if (dump == NULL || desc == NULL)
968 return ICH_RET_PARAM;
969
970 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
971 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
972 pch_bug_offset = 4;
973 else
974 return ICH_RET_ERR;
975 }
976
977 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +0200978 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000979 return ICH_RET_OOB;
980 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
981 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
982 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
983 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
984
985 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +0200986 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000987 return ICH_RET_OOB;
988 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
989 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
990 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
991
Nico Huber67d71792017-06-17 03:10:15 +0200992 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +0100993 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +0200994 prettyprint_ich_chipset(*cs);
995 }
Nico Huberfa622942017-03-24 17:25:37 +0100996
Stefan Taunerb3850962011-12-24 00:00:32 +0000997 /* region */
Nico Huberfa622942017-03-24 17:25:37 +0100998 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +0100999 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001000 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001001 for (i = 0; i < nr; i++)
1002 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001003
1004 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001005 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001006 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001007 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001008 for (i = 0; i < nm; i++)
1009 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001010
1011 /* upper map */
1012 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1013
1014 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1015 * "Identifies the 1s based number of DWORDS contained in the VSCC
1016 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1017 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1018 * check ensures that the maximum offset actually accessed is available.
1019 */
Nico Huber9e14aed2017-03-28 17:08:46 +02001020 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +00001021 return ICH_RET_OOB;
1022
1023 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001024 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1025 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +00001026 }
1027
1028 /* MCH/PROC (aka. North) straps */
1029 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1030 return ICH_RET_OOB;
1031
1032 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001033 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001034 for (i = 0; i < max_count; i++)
1035 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001036
1037 /* ICH/PCH (aka. South) straps */
1038 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1039 return ICH_RET_OOB;
1040
1041 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001042 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001043 for (i = 0; i < max_count; i++)
1044 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001045
1046 return ICH_RET_OK;
1047}
1048
Nico Huberad186312016-05-02 15:15:29 +02001049#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001050
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001051/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001052\em idx in bytes or -1 if the correct size can not be determined. */
1053int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001054{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001055 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001056 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001057 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001058 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001059
1060 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001061 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001062
1063 uint8_t size_enc;
1064 uint8_t size_max;
1065
1066 switch (cs) {
1067 case CHIPSET_ICH8:
1068 case CHIPSET_ICH9:
1069 case CHIPSET_ICH10:
1070 case CHIPSET_5_SERIES_IBEX_PEAK:
1071 case CHIPSET_6_SERIES_COUGAR_POINT:
1072 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001073 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001074 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001075 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001076 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001077 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001078 }
1079 size_max = 5;
1080 break;
1081 case CHIPSET_8_SERIES_LYNX_POINT:
1082 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1083 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001084 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001085 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001086 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001087 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberd2d39932019-01-18 16:49:37 +01001088 case CHIPSET_APOLLO_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001089 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001090 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001091 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001092 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001093 }
1094 size_max = 7;
1095 break;
1096 case CHIPSET_ICH_UNKNOWN:
1097 default:
1098 msg_pwarn("Density encoding is unknown on this chipset.\n");
1099 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001100 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001101
1102 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001103 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001104 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1105 idx, size_enc, size_max);
1106 return -1;
1107 }
1108
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001109 return (1 << (19 + size_enc));
1110}
1111
Nico Huber8d494992017-06-19 12:18:33 +02001112/* Only used by ichspi.c */
1113#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001114static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001115{
1116 uint32_t control = 0;
1117 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1118 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001119 switch (cs) {
1120 case CHIPSET_100_SERIES_SUNRISE_POINT:
1121 case CHIPSET_C620_SERIES_LEWISBURG:
1122 case CHIPSET_APOLLO_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001123 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1124 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001125 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001126 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1127 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1128 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001129}
1130
Nico Huberd54e4f42017-03-23 23:45:47 +01001131int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001132{
Nico Huber519be662018-12-23 20:03:35 +01001133 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001134 struct ich_desc_region *r = &desc->region;
1135
1136 /* Test if bit-fields are working as expected.
1137 * FIXME: Replace this with dynamic bitfield fixup
1138 */
1139 for (i = 0; i < 4; i++)
1140 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001141 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1142 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1143 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1144 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001145 msg_pdbg("The combination of compiler and CPU architecture used"
1146 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001147 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1148 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1149 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1150 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1151 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1152 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1153 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1154 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001155 return ICH_RET_ERR;
1156 }
1157
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001158 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001159 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001160 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1161 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1162 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1163 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001164
1165 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001166 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1167 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1168 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001169
1170 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001171 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1172 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001173 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001174 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001175 return ICH_RET_ERR;
1176 }
Nico Huberfa622942017-03-24 17:25:37 +01001177 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001178 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001179
1180 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001181 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1182 if (nm < 0) {
1183 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1184 __func__, desc->content.NM + 1);
1185 return ICH_RET_ERR;
1186 }
1187 for (i = 0; i < nm; i++)
1188 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001189
1190 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1191 * reading the upper map is impossible on all chipsets, so don't bother.
1192 */
1193
1194 msg_pdbg2(" done.\n");
1195 return ICH_RET_OK;
1196}
Nico Huber8d494992017-06-19 12:18:33 +02001197#endif
Nico Huber305f4172013-06-14 11:55:26 +02001198
1199/**
1200 * @brief Read a layout from the dump of an Intel ICH descriptor.
1201 *
1202 * @param layout Pointer where to store the layout.
1203 * @param dump The descriptor dump to read from.
1204 * @param len The length of the descriptor dump.
1205 *
1206 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001207 * 1 if the descriptor couldn't be parsed,
1208 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001209 */
1210int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1211{
Nico Huberfa622942017-03-24 17:25:37 +01001212 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001213 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1214 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001215 };
Nico Huber305f4172013-06-14 11:55:26 +02001216
1217 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001218 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1219 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001220 return 1;
1221
1222 memset(layout, 0x00, sizeof(*layout));
1223
Nico Huberfa622942017-03-24 17:25:37 +01001224 ssize_t i, j;
Nico Huber519be662018-12-23 20:03:35 +01001225 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
1226 for (i = 0, j = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001227 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001228 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001229 if (limit <= base)
1230 continue;
1231 layout->entries[j].start = base;
1232 layout->entries[j].end = limit;
1233 layout->entries[j].included = false;
Nico Huber70461a92019-06-15 14:56:19 +02001234 layout->entries[j].name = strdup(regions[i]);
1235 if (!layout->entries[j].name)
1236 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001237 ++j;
1238 }
1239 layout->base.entries = layout->entries;
1240 layout->base.num_entries = j;
1241 return 0;
1242}
1243
Nico Huberad186312016-05-02 15:15:29 +02001244#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */