blob: 7374984dc6ffa1b20319c271c6bf1824f0b247d3 [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:
Nico Huber2a5dfaf2019-07-04 16:01:51 +020044 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -050045 case CHIPSET_400_SERIES_COMET_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:
David Hendricksa5216362017-08-08 20:02:22 -070071 if (cont->NM <= MAX_NUM_MASTERS)
72 return cont->NM;
Richard Hughesdb7482b2018-12-19 12:04:30 +000073 break;
David Hendricksa5216362017-08-08 20:02:22 -070074 default:
75 if (cont->NM < MAX_NUM_MASTERS)
76 return cont->NM + 1;
77 }
78
79 return -1;
Nico Huberfa622942017-03-24 17:25:37 +010080}
81
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000082void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000083{
84 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
85 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
86 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
87 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000088 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
89 if (print_vcl)
90 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
91 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000092}
93
94#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
95#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
96#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
97#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
98#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
99
Nico Huber67d71792017-06-17 03:10:15 +0200100void prettyprint_ich_chipset(enum ich_chipset cs)
101{
102 static const char *const chipset_names[] = {
103 "Unknown ICH", "ICH8", "ICH9", "ICH10",
104 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
105 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
106 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200107 "C620 series Lewisburg", "300 series Cannon Point", "Apollo Lake",
Nico Huber67d71792017-06-17 03:10:15 +0200108 };
109 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
110 cs = 0;
111 else
112 cs = cs - CHIPSET_ICH8 + 1;
113 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
114}
115
Stefan Tauner1e146392011-09-15 23:52:55 +0000116void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
117{
Nico Huberfa622942017-03-24 17:25:37 +0100118 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000119 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100120 prettyprint_ich_descriptor_region(cs, desc);
121 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200122#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000123 if (cs >= CHIPSET_ICH8) {
124 prettyprint_ich_descriptor_upper_map(&desc->upper);
125 prettyprint_ich_descriptor_straps(cs, desc);
126 }
Nico Huberad186312016-05-02 15:15:29 +0200127#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000128}
129
Nico Huberfa622942017-03-24 17:25:37 +0100130void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000131{
132 msg_pdbg2("=== Content Section ===\n");
133 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
134 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
135 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
136 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
137 msg_pdbg2("\n");
138
139 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100140 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
141 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
142 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
143 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
Nico Huberd2d39932019-01-18 16:49:37 +0100144 msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL);
145 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont));
Nico Huberfa622942017-03-24 17:25:37 +0100146 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
147 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
148 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
149 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000150 msg_pdbg2("\n");
151}
152
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000153static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
154{
155 if (idx > 1) {
156 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
157 return NULL;
158 }
159
160 if (desc->content.NC == 0 && idx > 0)
161 return "unused";
162
163 static const char * const size_str[] = {
164 "512 kB", /* 0000 */
165 "1 MB", /* 0001 */
166 "2 MB", /* 0010 */
167 "4 MB", /* 0011 */
168 "8 MB", /* 0100 */
169 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
170 "32 MB", /* 0110 */
171 "64 MB", /* 0111 */
172 };
173
174 switch (cs) {
175 case CHIPSET_ICH8:
176 case CHIPSET_ICH9:
177 case CHIPSET_ICH10:
178 case CHIPSET_5_SERIES_IBEX_PEAK:
179 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000180 case CHIPSET_7_SERIES_PANTHER_POINT:
181 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000182 uint8_t size_enc;
183 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000184 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000185 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000186 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000187 }
188 if (size_enc > 5)
189 return "reserved";
190 return size_str[size_enc];
191 }
192 case CHIPSET_8_SERIES_LYNX_POINT:
193 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000194 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100195 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100196 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
David Hendricksa5216362017-08-08 20:02:22 -0700197 case CHIPSET_100_SERIES_SUNRISE_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100198 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200199 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -0500200 case CHIPSET_400_SERIES_COMET_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100201 case CHIPSET_APOLLO_LAKE: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000202 uint8_t size_enc;
203 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000204 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000205 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000206 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000207 }
208 if (size_enc > 7)
209 return "reserved";
210 return size_str[size_enc];
211 }
212 case CHIPSET_ICH_UNKNOWN:
213 default:
214 return "unknown";
215 }
216}
217
218static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000219{
Nico Huberd2d39932019-01-18 16:49:37 +0100220 static const char *const freq_str[3][8] = { {
Nico Huber129e9382019-06-06 15:43:27 +0200221 "20 MHz",
222 "33 MHz",
223 "reserved",
224 "reserved",
225 "50 MHz", /* New since Ibex Peak */
226 "reserved",
227 "reserved",
228 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100229 }, {
Nico Huber129e9382019-06-06 15:43:27 +0200230 "reserved",
231 "reserved",
232 "48 MHz",
233 "reserved",
234 "30 MHz",
235 "reserved",
236 "17 MHz",
237 "reserved"
Nico Huberd2d39932019-01-18 16:49:37 +0100238 }, {
239 "reserved",
240 "50 MHz",
241 "40 MHz",
242 "reserved",
243 "25 MHz",
244 "reserved",
245 "14 MHz / 17 MHz",
246 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100247 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000248
249 switch (cs) {
250 case CHIPSET_ICH8:
251 case CHIPSET_ICH9:
252 case CHIPSET_ICH10:
253 if (value > 1)
254 return "reserved";
Richard Hughesdb7482b2018-12-19 12:04:30 +0000255 /* Fall through. */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000256 case CHIPSET_5_SERIES_IBEX_PEAK:
257 case CHIPSET_6_SERIES_COUGAR_POINT:
258 case CHIPSET_7_SERIES_PANTHER_POINT:
259 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000260 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000261 case CHIPSET_8_SERIES_LYNX_POINT_LP:
262 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000263 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100264 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100265 return freq_str[0][value];
266 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700267 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200268 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -0500269 case CHIPSET_400_SERIES_COMET_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100270 return freq_str[1][value];
Nico Huberd2d39932019-01-18 16:49:37 +0100271 case CHIPSET_APOLLO_LAKE:
272 return freq_str[2][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000273 case CHIPSET_ICH_UNKNOWN:
274 default:
275 return "unknown";
276 }
277}
278
279void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
280{
Nico Huberd2d39932019-01-18 16:49:37 +0100281 bool has_flill1;
282
283 switch (cs) {
284 case CHIPSET_100_SERIES_SUNRISE_POINT:
285 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200286 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -0500287 case CHIPSET_400_SERIES_COMET_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100288 case CHIPSET_APOLLO_LAKE:
289 has_flill1 = true;
290 break;
291 default:
292 has_flill1 = false;
293 break;
294 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000295
296 msg_pdbg2("=== Component Section ===\n");
297 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
298 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberd2d39932019-01-18 16:49:37 +0100299 if (has_flill1)
Nico Huberfa622942017-03-24 17:25:37 +0100300 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000301 msg_pdbg2("\n");
302
303 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000304 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000305 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000306 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000307 else
308 msg_pdbg2("Component 2 is not used.\n");
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000309 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
310 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
311 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
312 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
313 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000314 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000315 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000316 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
317 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000318 desc->component.modes.dual_output ? "dis" : "en");
David Hendricksa5216362017-08-08 20:02:22 -0700319
320 int has_forbidden_opcode = 0;
321 if (desc->component.FLILL != 0) {
322 has_forbidden_opcode = 1;
Stefan Tauner1e146392011-09-15 23:52:55 +0000323 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
324 desc->component.invalid_instr0);
325 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
326 desc->component.invalid_instr1);
327 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
328 desc->component.invalid_instr2);
329 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
330 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700331 }
Nico Huberd2d39932019-01-18 16:49:37 +0100332 if (has_flill1) {
David Hendricksa5216362017-08-08 20:02:22 -0700333 if (desc->component.FLILL1 != 0) {
334 has_forbidden_opcode = 1;
Nico Huberfa622942017-03-24 17:25:37 +0100335 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
336 desc->component.invalid_instr4);
337 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
338 desc->component.invalid_instr5);
339 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
340 desc->component.invalid_instr6);
341 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
342 desc->component.invalid_instr7);
343 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000344 }
David Hendricksa5216362017-08-08 20:02:22 -0700345 if (!has_forbidden_opcode)
346 msg_pdbg2("No forbidden opcodes.\n");
347
Stefan Tauner1e146392011-09-15 23:52:55 +0000348 msg_pdbg2("\n");
349}
350
351static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
352{
Nico Huberfa622942017-03-24 17:25:37 +0100353 static const char *const region_names[] = {
Nico Huberd2d39932019-01-18 16:49:37 +0100354 "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown",
David Hendricksa5216362017-08-08 20:02:22 -0700355 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000356 };
Nico Huberfa622942017-03-24 17:25:37 +0100357 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000358 msg_pdbg2("%s: region index too high.\n", __func__);
359 return;
360 }
361 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
362 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100363 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000364 if (base > limit)
365 msg_pdbg2("is unused.\n");
366 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200367 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000368}
369
Nico Huberfa622942017-03-24 17:25:37 +0100370void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000371{
Nico Huber519be662018-12-23 20:03:35 +0100372 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100373 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000374 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100375 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000376 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100377 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000378 return;
379 }
Nico Huberfa622942017-03-24 17:25:37 +0100380 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100381 msg_pdbg2("FLREG%zd 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000382 msg_pdbg2("\n");
383
384 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100385 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100386 pprint_freg(&desc->region, (uint32_t)i);
Stefan Tauner1e146392011-09-15 23:52:55 +0000387 msg_pdbg2("\n");
388}
389
Nico Huberfa622942017-03-24 17:25:37 +0100390void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000391{
Nico Huber519be662018-12-23 20:03:35 +0100392 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100393 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000394 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100395 if (nm < 0) {
396 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
397 desc->content.NM + 1);
398 return;
399 }
400 for (i = 0; i < nm; i++)
Nico Huber519be662018-12-23 20:03:35 +0100401 msg_pdbg2("FLMSTR%zd 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000402 msg_pdbg2("\n");
403
404 msg_pdbg2("--- Details ---\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200405 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT ||
Matt DeVillierb1f858f2020-08-12 12:48:06 -0500406 cs == CHIPSET_300_SERIES_CANNON_POINT ||
407 cs == CHIPSET_400_SERIES_COMET_POINT) {
Nico Huberfa622942017-03-24 17:25:37 +0100408 const char *const master_names[] = {
409 "BIOS", "ME", "GbE", "unknown", "EC",
410 };
Nico Huber519be662018-12-23 20:03:35 +0100411 if (nm >= (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberfa622942017-03-24 17:25:37 +0100412 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
413 desc->content.NM + 1);
414 return;
415 }
416
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200417 size_t num_regions;
418 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9");
419 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
420 num_regions = 10;
421 msg_pdbg2("\n");
422 } else {
423 num_regions = 16;
424 msg_pdbg2(" RegA RegB RegC RegD RegE RegF\n");
425 }
Nico Huberfa622942017-03-24 17:25:37 +0100426 for (i = 0; i < nm; i++) {
427 size_t j;
428 msg_pdbg2("%-4s", master_names[i]);
Nico Huber961f4a12019-10-04 17:34:22 +0200429 for (j = 0; j < (size_t)min(num_regions, 12); j++)
Nico Huberfa622942017-03-24 17:25:37 +0100430 msg_pdbg2(" %c%c ",
431 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
432 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200433 for (; j < num_regions; j++)
434 msg_pdbg2(" %c%c ",
435 desc->master.mstr[i].ext_read & (1 << (j - 12)) ? 'r' : ' ',
436 desc->master.mstr[i].ext_write & (1 << (j - 12)) ? 'w' : ' ');
Nico Huberfa622942017-03-24 17:25:37 +0100437 msg_pdbg2("\n");
438 }
David Hendricksa5216362017-08-08 20:02:22 -0700439 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
440 const char *const master_names[] = {
441 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
442 };
443 /* NM starts at 1 instead of 0 for LBG */
Nico Huber519be662018-12-23 20:03:35 +0100444 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
David Hendricksa5216362017-08-08 20:02:22 -0700445 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
446 desc->content.NM);
447 return;
448 }
449
450 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
451 " ", /* width of master name (4 chars minimum) */
452 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
453 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
454 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
455 "Reg15");
456 for (i = 0; i < nm; i++) {
457 size_t j;
458 msg_pdbg2("%-4s", master_names[i]);
459 for (j = 0; j < 16; j++)
460 msg_pdbg2(" %c%c ",
461 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
462 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
463 msg_pdbg2("\n");
464 }
Nico Huberd2d39932019-01-18 16:49:37 +0100465 } else if (cs == CHIPSET_APOLLO_LAKE) {
466 const char *const master_names[] = { "BIOS", "TXE", };
Nico Huber519be662018-12-23 20:03:35 +0100467 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberd2d39932019-01-18 16:49:37 +0100468 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
469 return;
470 }
471
472 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
473 for (i = 0; i < nm; i++) {
Nico Huber519be662018-12-23 20:03:35 +0100474 ssize_t j;
Nico Huberd2d39932019-01-18 16:49:37 +0100475 msg_pdbg2("%-4s", master_names[i]);
476 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
477 msg_pdbg2(" %c%c ",
478 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
479 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
480 msg_pdbg2("\n");
481 }
Nico Huberfa622942017-03-24 17:25:37 +0100482 } else {
483 const struct ich_desc_master *const mstr = &desc->master;
484 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
485 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
486 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
487 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
488 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
489 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
490 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
491 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
492 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
493 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
494 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
495 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
496 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
497 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
498 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
499 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
500 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
501 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
502 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
503 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000504 msg_pdbg2("\n");
505}
506
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600507static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000508{
509 static const char * const str_GPIO12[4] = {
510 "GPIO12",
511 "LAN PHY Power Control Function (Native Output)",
512 "GLAN_DOCK# (Native Input)",
513 "invalid configuration",
514 };
515
516 msg_pdbg2("--- MCH details ---\n");
517 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
518 msg_pdbg2("\n");
519
520 msg_pdbg2("--- ICH details ---\n");
521 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
522 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
523 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
524 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
525 msg_pdbg2("SPI CS1 is used for %s.\n",
526 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
527 "LAN PHY Power Control Function" :
528 "SPI Chip Select");
529 msg_pdbg2("GPIO12 is used as %s.\n",
530 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
531 msg_pdbg2("PCIe Port 6 is used for %s.\n",
532 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
533 msg_pdbg2("%sn BMC Mode: "
534 "Intel AMT SMBus Controller 1 is connected to %s.\n",
535 desc->south.ich8.BMCMODE ? "I" : "Not i",
536 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
537 msg_pdbg2("TCO is in %s Mode.\n",
538 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
539 msg_pdbg2("ME A is %sabled.\n",
540 desc->south.ich8.ME_DISABLE ? "dis" : "en");
541 msg_pdbg2("\n");
542}
543
544static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
545{
546 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
547
548 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000549 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000550 case 0:
551 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
552 break;
553 case 1:
554 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
555 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
556 break;
557 case 2:
558 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
559 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
560 break;
561 case 3:
562 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
563 1+off, 2+off, 4+off);
564 break;
565 }
566 msg_pdbg2("\n");
567}
568
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600569static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000570{
571 /* PCHSTRP4 */
572 msg_pdbg2("Intel PHY is %s.\n",
573 (s->ibex.PHYCON == 2) ? "connected" :
574 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
575 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
576 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
577 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
578 s->ibex.GBEMAC_SMBUS_ADDR);
579 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
580 s->ibex.GBEPHY_SMBUS_ADDR);
581
582 /* PCHSTRP5 */
583 /* PCHSTRP6 */
584 /* PCHSTRP7 */
585 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
586 s->ibex.MESMA2UDID_VENDOR);
587 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
588 s->ibex.MESMA2UDID_VENDOR);
589
590 /* PCHSTRP8 */
591}
592
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600593static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000594{
595 /* PCHSTRP11 */
596 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
597 s->ibex.SML1GPAEN ? "en" : "dis");
598 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
599 s->ibex.SML1GPA);
600 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
601 s->ibex.SML1I2CAEN ? "en" : "dis");
602 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
603 s->ibex.SML1I2CA);
604
605 /* PCHSTRP12 */
606 /* PCHSTRP13 */
607}
608
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600609static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000610{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000611 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000612 100,
613 50,
614 5,
615 1
616 };
617
618 msg_pdbg2("--- PCH ---\n");
619
620 /* PCHSTRP0 */
621 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
622 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
623 s->ibex.SMB_EN ? "en" : "dis");
624 msg_pdbg2("SMLink0 segment is %sabled.\n",
625 s->ibex.SML0_EN ? "en" : "dis");
626 msg_pdbg2("SMLink1 segment is %sabled.\n",
627 s->ibex.SML1_EN ? "en" : "dis");
628 msg_pdbg2("SMLink1 Frequency: %s\n",
629 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
630 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
631 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
632 msg_pdbg2("SMLink0 Frequency: %s\n",
633 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
634 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
635 "LAN_PHY_PWR_CTRL" : "general purpose output");
636 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
637 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
638 s->ibex.DMI_REQID_DIS ? "en" : "dis");
639 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
640 1 << (6 + s->ibex.BBBS));
641
642 /* PCHSTRP1 */
643 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
644
645 /* PCHSTRP2 */
646 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
647 s->ibex.MESMASDEN ? "en" : "dis");
648 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
649 s->ibex.MESMASDA);
650 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
651 s->ibex.MESMI2CEN ? "en" : "dis");
652 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
653 s->ibex.MESMI2CA);
654
655 /* PCHSTRP3 */
656 prettyprint_ich_descriptor_pchstraps45678_56(s);
657 /* PCHSTRP9 */
658 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
659 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
660 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
661 s->ibex.PCIELR1 ? "" : "not ");
662 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
663 s->ibex.PCIELR2 ? "" : "not ");
664 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
665 s->ibex.DMILR ? "" : "not ");
666 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
667 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
668 s->ibex.PHY_PCIE_EN ? "en" : "dis");
669
670 /* PCHSTRP10 */
671 msg_pdbg2("Management Engine will boot from %sflash.\n",
672 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
673 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
674 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
675 s->ibex.VE_EN ? "en" : "dis");
676 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
677 s->ibex.MMDDE ? "en" : "dis");
678 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
679 s->ibex.MMADDR);
680 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
681 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
682 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
683 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
684 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
685
686 prettyprint_ich_descriptor_pchstraps111213_56(s);
687
688 /* PCHSTRP14 */
689 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
690 s->ibex.VE_EN2 ? "en" : "dis");
691 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
692 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
693 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
694 s->ibex.BW_SSD ? "en" : "dis");
695 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
696 s->ibex.NVMHCI_EN ? "en" : "dis");
697
698 /* PCHSTRP15 */
699 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
700 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
701 s->ibex.IWL_EN ? "en" : "dis");
702 msg_pdbg2("t209 min Timing: %d ms\n",
703 dec_t209min[s->ibex.t209min]);
704 msg_pdbg2("\n");
705}
706
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600707static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000708{
709 msg_pdbg2("--- PCH ---\n");
710
711 /* PCHSTRP0 */
712 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
713 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
714 s->ibex.SMB_EN ? "en" : "dis");
715 msg_pdbg2("SMLink0 segment is %sabled.\n",
716 s->ibex.SML0_EN ? "en" : "dis");
717 msg_pdbg2("SMLink1 segment is %sabled.\n",
718 s->ibex.SML1_EN ? "en" : "dis");
719 msg_pdbg2("SMLink1 Frequency: %s\n",
720 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
721 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
722 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
723 msg_pdbg2("SMLink0 Frequency: %s\n",
724 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
725 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
726 "LAN_PHY_PWR_CTRL" : "general purpose output");
727 msg_pdbg2("LinkSec is %sabled.\n",
728 s->cougar.LINKSEC_DIS ? "en" : "dis");
729 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
730 s->ibex.DMI_REQID_DIS ? "en" : "dis");
731 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
732 1 << (6 + s->ibex.BBBS));
733
734 /* PCHSTRP1 */
735 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
736 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
737
738 /* PCHSTRP2 */
739 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
740 s->ibex.MESMASDEN ? "en" : "dis");
741 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
742 s->ibex.MESMASDA);
743 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
744 s->cougar.MESMMCTPAEN ? "en" : "dis");
745 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
746 s->cougar.MESMMCTPA);
747 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
748 s->ibex.MESMI2CEN ? "en" : "dis");
749 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
750 s->ibex.MESMI2CA);
751
752 /* PCHSTRP3 */
753 prettyprint_ich_descriptor_pchstraps45678_56(s);
754 /* PCHSTRP9 */
755 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
756 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
757 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
758 s->ibex.PCIELR1 ? "" : "not ");
759 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
760 s->ibex.PCIELR2 ? "" : "not ");
761 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
762 s->ibex.DMILR ? "" : "not ");
763 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
764 s->cougar.MDSMBE_EN ? "en" : "dis");
765 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
766 s->cougar.MDSMBE_ADD);
767 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
768 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
769 s->ibex.PHY_PCIE_EN ? "en" : "dis");
770 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
771 s->cougar.SUB_DECODE_EN ? "en" : "dis");
772 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
773 "PCHHOT#" : "SML1ALERT#");
774
775 /* PCHSTRP10 */
776 msg_pdbg2("Management Engine will boot from %sflash.\n",
777 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
778
779 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
780 s->cougar.MDSMBE_EN ? "en" : "dis");
781 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
782 s->cougar.MDSMBE_ADD);
783
784 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
785 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000786 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
787 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000788 msg_pdbg2("ICC Profile is selected by %s.\n",
789 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
790 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
791 s->cougar.Deep_SX_EN ? "not " : "");
792 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
793 s->cougar.ME_DBG_LAN ? "en" : "dis");
794
795 prettyprint_ich_descriptor_pchstraps111213_56(s);
796
797 /* PCHSTRP14 */
798 /* PCHSTRP15 */
799 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
800 msg_pdbg2("Integrated wired LAN is %sabled.\n",
801 s->cougar.IWL_EN ? "en" : "dis");
802 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
803 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000804 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000805 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
806 "general purpose output" : "SLP_LAN#");
807
808 /* PCHSTRP16 */
809 /* PCHSTRP17 */
810 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
811 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
812 msg_pdbg2("\n");
813}
814
815void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
816{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000817 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000818 msg_pdbg2("=== Softstraps ===\n");
819
Nico Huber519be662018-12-23 20:03:35 +0100820 max_count = MIN(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
Nico Huberd7c75522017-03-29 16:31:49 +0200821 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000822 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200823 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000824 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200825 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000826
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000827 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
828 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000829 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
830 msg_pdbg2("\n");
831
Nico Huber519be662018-12-23 20:03:35 +0100832 max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
Nico Huberd7c75522017-03-29 16:31:49 +0200833 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000834 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
835 desc->content.ISL, max_count);
836 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200837 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000838
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000839 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
840 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000841 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
842 msg_pdbg2("\n");
843
844 switch (cs) {
845 case CHIPSET_ICH8:
846 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
847 msg_pdbg2("Detailed North/MCH/PROC information is "
848 "probably not reliable, printing anyway.\n");
849 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
850 msg_pdbg2("Detailed South/ICH/PCH information is "
851 "probably not reliable, printing anyway.\n");
852 prettyprint_ich_descriptor_straps_ich8(desc);
853 break;
854 case CHIPSET_5_SERIES_IBEX_PEAK:
855 /* PCH straps only. PROCSTRPs are unknown. */
856 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
857 msg_pdbg2("Detailed South/ICH/PCH information is "
858 "probably not reliable, printing anyway.\n");
859 prettyprint_ich_descriptor_straps_ibex(&desc->south);
860 break;
861 case CHIPSET_6_SERIES_COUGAR_POINT:
862 /* PCH straps only. PROCSTRP0 is "reserved". */
863 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
864 msg_pdbg2("Detailed South/ICH/PCH information is "
865 "probably not reliable, printing anyway.\n");
866 prettyprint_ich_descriptor_straps_cougar(&desc->south);
867 break;
868 case CHIPSET_ICH_UNKNOWN:
869 break;
870 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000871 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000872 break;
873 }
874}
875
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600876static void prettyprint_rdid(uint32_t reg_val)
Stefan Taunerb3850962011-12-24 00:00:32 +0000877{
878 uint8_t mid = reg_val & 0xFF;
879 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
880 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
881}
882
883void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
884{
885 int i;
886 msg_pdbg2("=== Upper Map Section ===\n");
887 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
888 msg_pdbg2("\n");
889
890 msg_pdbg2("--- Details ---\n");
891 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
892 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
893 msg_pdbg2("\n");
894
895 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000896 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000897 uint32_t jid = umap->vscc_table[i].JID;
898 uint32_t vscc = umap->vscc_table[i].VSCC;
899 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
900 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
901 msg_pdbg2(" "); /* indention */
902 prettyprint_rdid(jid);
903 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000904 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000905 }
906 msg_pdbg2("\n");
907}
908
Nico Huber1dc3d422017-06-17 00:09:31 +0200909/*
910 * Guesses a minimum chipset version based on the maximum number of
911 * soft straps per generation.
912 */
913static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
914{
915 if (content->ICCRIBA == 0x00) {
916 if (content->MSL == 0 && content->ISL <= 2)
917 return CHIPSET_ICH8;
918 else if (content->ISL <= 2)
919 return CHIPSET_ICH9;
920 else if (content->ISL <= 10)
921 return CHIPSET_ICH10;
922 else if (content->ISL <= 16)
923 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huberd2d39932019-01-18 16:49:37 +0100924 else if (content->FLMAP2 == 0) {
925 if (content->ISL != 19)
926 msg_pwarn("Peculiar firmware descriptor, assuming Apollo Lake compatibility.\n");
927 return CHIPSET_APOLLO_LAKE;
928 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200929 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
930 return CHIPSET_5_SERIES_IBEX_PEAK;
931 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
932 if (content->MSL == 0 && content->ISL <= 17)
933 return CHIPSET_BAYTRAIL;
934 else if (content->MSL <= 1 && content->ISL <= 18)
935 return CHIPSET_6_SERIES_COUGAR_POINT;
936 else if (content->MSL <= 1 && content->ISL <= 21)
937 return CHIPSET_8_SERIES_LYNX_POINT;
938 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
939 return CHIPSET_9_SERIES_WILDCAT_POINT;
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200940 } else if (content->ICCRIBA < 0x34) {
941 if (content->NM == 6)
942 return CHIPSET_C620_SERIES_LEWISBURG;
943 else
944 return CHIPSET_100_SERIES_SUNRISE_POINT;
Jonathan Zhang95d822e2020-08-19 12:19:06 -0700945 } else if (content->ICCRIBA == 0x34) {
946 if (content->NM == 6)
947 return CHIPSET_C620_SERIES_LEWISBURG;
948 else
949 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200950 } else {
Jonathan Zhang95d822e2020-08-19 12:19:06 -0700951 msg_pwarn("Unknown firmware descriptor, assuming 300 series compatibility.\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200952 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200953 }
954}
955
956/*
957 * As an additional measure, we check the read frequency like `ifdtool`.
958 * The frequency value 6 (17MHz) was reserved before Skylake and is the
959 * only valid value since. Skylake is currently the most important dis-
960 * tinction because of the dropped number of regions field (NR).
961 */
Nico Huberfa622942017-03-24 17:25:37 +0100962static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
963 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200964{
965 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
966
Nico Huberd2d39932019-01-18 16:49:37 +0100967 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200968 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -0500969 case CHIPSET_400_SERIES_COMET_POINT:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200970 /* `freq_read` was repurposed, so can't check on it any more. */
971 return guess;
Nico Huberd2d39932019-01-18 16:49:37 +0100972 case CHIPSET_100_SERIES_SUNRISE_POINT:
973 case CHIPSET_C620_SERIES_LEWISBURG:
974 case CHIPSET_APOLLO_LAKE:
975 if (component->modes.freq_read != 6) {
976 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
977 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
978 "Please report this message, the output of `ich_descriptors_tool` for\n"
979 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
980 return CHIPSET_9_SERIES_WILDCAT_POINT;
981 }
982 return guess;
983 default:
984 if (component->modes.freq_read == 6) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200985 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
986 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
987 "Please report this message, the output of `ich_descriptors_tool` for\n"
988 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -0700989 return CHIPSET_100_SERIES_SUNRISE_POINT;
990 }
991 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +0200992 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200993}
994
Stefan Taunerb3850962011-12-24 00:00:32 +0000995/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +0100996int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
997 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000998{
Nico Huber519be662018-12-23 20:03:35 +0100999 ssize_t i, max_count;
1000 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +00001001
1002 if (dump == NULL || desc == NULL)
1003 return ICH_RET_PARAM;
1004
1005 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1006 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1007 pch_bug_offset = 4;
1008 else
1009 return ICH_RET_ERR;
1010 }
1011
1012 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001013 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001014 return ICH_RET_OOB;
1015 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1016 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1017 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1018 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1019
1020 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001021 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001022 return ICH_RET_OOB;
1023 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1024 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1025 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1026
Nico Huber67d71792017-06-17 03:10:15 +02001027 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +01001028 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +02001029 prettyprint_ich_chipset(*cs);
1030 }
Nico Huberfa622942017-03-24 17:25:37 +01001031
Stefan Taunerb3850962011-12-24 00:00:32 +00001032 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001033 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001034 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001035 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001036 for (i = 0; i < nr; i++)
1037 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001038
1039 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001040 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001041 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001042 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001043 for (i = 0; i < nm; i++)
1044 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001045
1046 /* upper map */
1047 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1048
1049 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1050 * "Identifies the 1s based number of DWORDS contained in the VSCC
1051 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1052 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1053 * check ensures that the maximum offset actually accessed is available.
1054 */
Nico Huber9e14aed2017-03-28 17:08:46 +02001055 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +00001056 return ICH_RET_OOB;
1057
1058 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001059 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1060 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +00001061 }
1062
1063 /* MCH/PROC (aka. North) straps */
1064 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1065 return ICH_RET_OOB;
1066
1067 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001068 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001069 for (i = 0; i < max_count; i++)
1070 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001071
1072 /* ICH/PCH (aka. South) straps */
1073 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1074 return ICH_RET_OOB;
1075
1076 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001077 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001078 for (i = 0; i < max_count; i++)
1079 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001080
1081 return ICH_RET_OK;
1082}
1083
Nico Huberad186312016-05-02 15:15:29 +02001084#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001085
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001086/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001087\em idx in bytes or -1 if the correct size can not be determined. */
1088int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001089{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001090 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001091 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001092 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001093 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001094
1095 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001096 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001097
1098 uint8_t size_enc;
1099 uint8_t size_max;
1100
1101 switch (cs) {
1102 case CHIPSET_ICH8:
1103 case CHIPSET_ICH9:
1104 case CHIPSET_ICH10:
1105 case CHIPSET_5_SERIES_IBEX_PEAK:
1106 case CHIPSET_6_SERIES_COUGAR_POINT:
1107 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001108 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001109 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001110 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001111 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001112 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001113 }
1114 size_max = 5;
1115 break;
1116 case CHIPSET_8_SERIES_LYNX_POINT:
1117 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1118 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001119 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001120 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001121 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001122 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001123 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -05001124 case CHIPSET_400_SERIES_COMET_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001125 case CHIPSET_APOLLO_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001126 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001127 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001128 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001129 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001130 }
1131 size_max = 7;
1132 break;
1133 case CHIPSET_ICH_UNKNOWN:
1134 default:
1135 msg_pwarn("Density encoding is unknown on this chipset.\n");
1136 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001137 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001138
1139 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001140 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001141 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1142 idx, size_enc, size_max);
1143 return -1;
1144 }
1145
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001146 return (1 << (19 + size_enc));
1147}
1148
Nico Huber8d494992017-06-19 12:18:33 +02001149/* Only used by ichspi.c */
1150#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001151static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001152{
1153 uint32_t control = 0;
1154 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1155 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001156 switch (cs) {
1157 case CHIPSET_100_SERIES_SUNRISE_POINT:
1158 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001159 case CHIPSET_300_SERIES_CANNON_POINT:
Matt DeVillierb1f858f2020-08-12 12:48:06 -05001160 case CHIPSET_400_SERIES_COMET_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001161 case CHIPSET_APOLLO_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001162 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1163 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001164 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001165 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1166 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1167 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001168}
1169
Nico Huberd54e4f42017-03-23 23:45:47 +01001170int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001171{
Nico Huber519be662018-12-23 20:03:35 +01001172 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001173 struct ich_desc_region *r = &desc->region;
1174
1175 /* Test if bit-fields are working as expected.
1176 * FIXME: Replace this with dynamic bitfield fixup
1177 */
1178 for (i = 0; i < 4; i++)
1179 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001180 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1181 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1182 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1183 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001184 msg_pdbg("The combination of compiler and CPU architecture used"
1185 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001186 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1187 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1188 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1189 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1190 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1191 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1192 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1193 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001194 return ICH_RET_ERR;
1195 }
1196
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001197 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001198 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001199 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1200 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1201 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1202 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001203
1204 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001205 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1206 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1207 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001208
1209 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001210 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1211 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001212 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001213 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001214 return ICH_RET_ERR;
1215 }
Nico Huberfa622942017-03-24 17:25:37 +01001216 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001217 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001218
1219 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001220 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1221 if (nm < 0) {
1222 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1223 __func__, desc->content.NM + 1);
1224 return ICH_RET_ERR;
1225 }
1226 for (i = 0; i < nm; i++)
1227 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001228
1229 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1230 * reading the upper map is impossible on all chipsets, so don't bother.
1231 */
1232
1233 msg_pdbg2(" done.\n");
1234 return ICH_RET_OK;
1235}
Nico Huber8d494992017-06-19 12:18:33 +02001236#endif
Nico Huber305f4172013-06-14 11:55:26 +02001237
1238/**
1239 * @brief Read a layout from the dump of an Intel ICH descriptor.
1240 *
1241 * @param layout Pointer where to store the layout.
1242 * @param dump The descriptor dump to read from.
1243 * @param len The length of the descriptor dump.
1244 *
1245 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001246 * 1 if the descriptor couldn't be parsed,
1247 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001248 */
1249int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1250{
Nico Huberfa622942017-03-24 17:25:37 +01001251 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001252 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1253 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001254 };
Nico Huber305f4172013-06-14 11:55:26 +02001255
1256 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001257 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
Jonathan Zhang95d822e2020-08-19 12:19:06 -07001258 int ret = read_ich_descriptors_from_dump(dump, len, &cs, &desc);
1259 if (ret) {
1260 msg_pdbg("%s():%d, returned with value %d.\n",
1261 __func__, __LINE__, ret);
Nico Huber305f4172013-06-14 11:55:26 +02001262 return 1;
Jonathan Zhang95d822e2020-08-19 12:19:06 -07001263 }
Nico Huber305f4172013-06-14 11:55:26 +02001264
1265 memset(layout, 0x00, sizeof(*layout));
1266
Nico Huberfa622942017-03-24 17:25:37 +01001267 ssize_t i, j;
Nico Huber519be662018-12-23 20:03:35 +01001268 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
1269 for (i = 0, j = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001270 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001271 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001272 if (limit <= base)
1273 continue;
1274 layout->entries[j].start = base;
1275 layout->entries[j].end = limit;
1276 layout->entries[j].included = false;
Nico Huber70461a92019-06-15 14:56:19 +02001277 layout->entries[j].name = strdup(regions[i]);
1278 if (!layout->entries[j].name)
1279 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001280 ++j;
1281 }
1282 layout->base.entries = layout->entries;
1283 layout->base.num_entries = j;
1284 return 0;
1285}
1286
Nico Huberad186312016-05-02 15:15:29 +02001287#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */