blob: 2e9d0f84e8f8d7966d4ea486c7e3798f18f80d03 [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:
David Hendricksa5216362017-08-08 20:02:22 -070045 return 16;
Nico Huberfa622942017-03-24 17:25:37 +010046 case CHIPSET_100_SERIES_SUNRISE_POINT:
47 return 10;
48 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
49 case CHIPSET_9_SERIES_WILDCAT_POINT:
50 case CHIPSET_8_SERIES_LYNX_POINT_LP:
51 case CHIPSET_8_SERIES_LYNX_POINT:
52 case CHIPSET_8_SERIES_WELLSBURG:
53 if (cont->NR <= 6)
54 return cont->NR + 1;
55 else
56 return -1;
57 default:
58 if (cont->NR <= 4)
59 return cont->NR + 1;
60 else
61 return -1;
62 }
63}
64
65ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
66{
David Hendricksa5216362017-08-08 20:02:22 -070067 switch (cs) {
68 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberd2d39932019-01-18 16:49:37 +010069 case CHIPSET_APOLLO_LAKE:
David Hendricksa5216362017-08-08 20:02:22 -070070 if (cont->NM <= MAX_NUM_MASTERS)
71 return cont->NM;
Richard Hughesdb7482b2018-12-19 12:04:30 +000072 break;
David Hendricksa5216362017-08-08 20:02:22 -070073 default:
74 if (cont->NM < MAX_NUM_MASTERS)
75 return cont->NM + 1;
76 }
77
78 return -1;
Nico Huberfa622942017-03-24 17:25:37 +010079}
80
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000081void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000082{
83 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
84 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
85 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
86 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000087 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
88 if (print_vcl)
89 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
90 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000091}
92
93#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
94#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
95#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
96#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
97#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
98
Nico Huber67d71792017-06-17 03:10:15 +020099void prettyprint_ich_chipset(enum ich_chipset cs)
100{
101 static const char *const chipset_names[] = {
102 "Unknown ICH", "ICH8", "ICH9", "ICH10",
103 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
104 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
105 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200106 "C620 series Lewisburg", "300 series Cannon Point", "Apollo Lake",
Nico Huber67d71792017-06-17 03:10:15 +0200107 };
108 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
109 cs = 0;
110 else
111 cs = cs - CHIPSET_ICH8 + 1;
112 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
113}
114
Stefan Tauner1e146392011-09-15 23:52:55 +0000115void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
116{
Nico Huberfa622942017-03-24 17:25:37 +0100117 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000118 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100119 prettyprint_ich_descriptor_region(cs, desc);
120 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200121#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000122 if (cs >= CHIPSET_ICH8) {
123 prettyprint_ich_descriptor_upper_map(&desc->upper);
124 prettyprint_ich_descriptor_straps(cs, desc);
125 }
Nico Huberad186312016-05-02 15:15:29 +0200126#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000127}
128
Nico Huberfa622942017-03-24 17:25:37 +0100129void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000130{
131 msg_pdbg2("=== Content Section ===\n");
132 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
133 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
134 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
135 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
136 msg_pdbg2("\n");
137
138 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100139 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
140 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
141 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
142 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
Nico Huberd2d39932019-01-18 16:49:37 +0100143 msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL);
144 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont));
Nico Huberfa622942017-03-24 17:25:37 +0100145 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
146 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
147 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
148 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000149 msg_pdbg2("\n");
150}
151
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000152static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
153{
154 if (idx > 1) {
155 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
156 return NULL;
157 }
158
159 if (desc->content.NC == 0 && idx > 0)
160 return "unused";
161
162 static const char * const size_str[] = {
163 "512 kB", /* 0000 */
164 "1 MB", /* 0001 */
165 "2 MB", /* 0010 */
166 "4 MB", /* 0011 */
167 "8 MB", /* 0100 */
168 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
169 "32 MB", /* 0110 */
170 "64 MB", /* 0111 */
171 };
172
173 switch (cs) {
174 case CHIPSET_ICH8:
175 case CHIPSET_ICH9:
176 case CHIPSET_ICH10:
177 case CHIPSET_5_SERIES_IBEX_PEAK:
178 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000179 case CHIPSET_7_SERIES_PANTHER_POINT:
180 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000181 uint8_t size_enc;
182 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000183 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000184 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000185 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000186 }
187 if (size_enc > 5)
188 return "reserved";
189 return size_str[size_enc];
190 }
191 case CHIPSET_8_SERIES_LYNX_POINT:
192 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000193 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100194 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100195 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
David Hendricksa5216362017-08-08 20:02:22 -0700196 case CHIPSET_100_SERIES_SUNRISE_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100197 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200198 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100199 case CHIPSET_APOLLO_LAKE: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000200 uint8_t size_enc;
201 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000202 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000203 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000204 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000205 }
206 if (size_enc > 7)
207 return "reserved";
208 return size_str[size_enc];
209 }
210 case CHIPSET_ICH_UNKNOWN:
211 default:
212 return "unknown";
213 }
214}
215
216static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000217{
Nico Huberd2d39932019-01-18 16:49:37 +0100218 static const char *const freq_str[3][8] = { {
Nico Huber129e9382019-06-06 15:43:27 +0200219 "20 MHz",
220 "33 MHz",
221 "reserved",
222 "reserved",
223 "50 MHz", /* New since Ibex Peak */
224 "reserved",
225 "reserved",
226 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100227 }, {
Nico Huber129e9382019-06-06 15:43:27 +0200228 "reserved",
229 "reserved",
230 "48 MHz",
231 "reserved",
232 "30 MHz",
233 "reserved",
234 "17 MHz",
235 "reserved"
Nico Huberd2d39932019-01-18 16:49:37 +0100236 }, {
237 "reserved",
238 "50 MHz",
239 "40 MHz",
240 "reserved",
241 "25 MHz",
242 "reserved",
243 "14 MHz / 17 MHz",
244 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100245 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000246
247 switch (cs) {
248 case CHIPSET_ICH8:
249 case CHIPSET_ICH9:
250 case CHIPSET_ICH10:
251 if (value > 1)
252 return "reserved";
Richard Hughesdb7482b2018-12-19 12:04:30 +0000253 /* Fall through. */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000254 case CHIPSET_5_SERIES_IBEX_PEAK:
255 case CHIPSET_6_SERIES_COUGAR_POINT:
256 case CHIPSET_7_SERIES_PANTHER_POINT:
257 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000258 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000259 case CHIPSET_8_SERIES_LYNX_POINT_LP:
260 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000261 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100262 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100263 return freq_str[0][value];
264 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700265 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200266 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100267 return freq_str[1][value];
Nico Huberd2d39932019-01-18 16:49:37 +0100268 case CHIPSET_APOLLO_LAKE:
269 return freq_str[2][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000270 case CHIPSET_ICH_UNKNOWN:
271 default:
272 return "unknown";
273 }
274}
275
276void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
277{
Nico Huberd2d39932019-01-18 16:49:37 +0100278 bool has_flill1;
279
280 switch (cs) {
281 case CHIPSET_100_SERIES_SUNRISE_POINT:
282 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200283 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100284 case CHIPSET_APOLLO_LAKE:
285 has_flill1 = true;
286 break;
287 default:
288 has_flill1 = false;
289 break;
290 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000291
292 msg_pdbg2("=== Component Section ===\n");
293 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
294 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberd2d39932019-01-18 16:49:37 +0100295 if (has_flill1)
Nico Huberfa622942017-03-24 17:25:37 +0100296 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000297 msg_pdbg2("\n");
298
299 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000300 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000301 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000302 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000303 else
304 msg_pdbg2("Component 2 is not used.\n");
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000305 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
306 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
307 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
308 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
309 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000310 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000311 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000312 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
313 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000314 desc->component.modes.dual_output ? "dis" : "en");
David Hendricksa5216362017-08-08 20:02:22 -0700315
316 int has_forbidden_opcode = 0;
317 if (desc->component.FLILL != 0) {
318 has_forbidden_opcode = 1;
Stefan Tauner1e146392011-09-15 23:52:55 +0000319 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
320 desc->component.invalid_instr0);
321 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
322 desc->component.invalid_instr1);
323 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
324 desc->component.invalid_instr2);
325 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
326 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700327 }
Nico Huberd2d39932019-01-18 16:49:37 +0100328 if (has_flill1) {
David Hendricksa5216362017-08-08 20:02:22 -0700329 if (desc->component.FLILL1 != 0) {
330 has_forbidden_opcode = 1;
Nico Huberfa622942017-03-24 17:25:37 +0100331 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
332 desc->component.invalid_instr4);
333 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
334 desc->component.invalid_instr5);
335 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
336 desc->component.invalid_instr6);
337 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
338 desc->component.invalid_instr7);
339 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000340 }
David Hendricksa5216362017-08-08 20:02:22 -0700341 if (!has_forbidden_opcode)
342 msg_pdbg2("No forbidden opcodes.\n");
343
Stefan Tauner1e146392011-09-15 23:52:55 +0000344 msg_pdbg2("\n");
345}
346
347static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
348{
Nico Huberfa622942017-03-24 17:25:37 +0100349 static const char *const region_names[] = {
Nico Huberd2d39932019-01-18 16:49:37 +0100350 "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown",
David Hendricksa5216362017-08-08 20:02:22 -0700351 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000352 };
Nico Huberfa622942017-03-24 17:25:37 +0100353 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000354 msg_pdbg2("%s: region index too high.\n", __func__);
355 return;
356 }
357 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
358 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100359 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000360 if (base > limit)
361 msg_pdbg2("is unused.\n");
362 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200363 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000364}
365
Nico Huberfa622942017-03-24 17:25:37 +0100366void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000367{
Nico Huber519be662018-12-23 20:03:35 +0100368 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100369 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000370 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100371 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000372 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100373 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000374 return;
375 }
Nico Huberfa622942017-03-24 17:25:37 +0100376 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100377 msg_pdbg2("FLREG%zd 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000378 msg_pdbg2("\n");
379
380 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100381 for (i = 0; i < nr; i++)
Nico Huber519be662018-12-23 20:03:35 +0100382 pprint_freg(&desc->region, (uint32_t)i);
Stefan Tauner1e146392011-09-15 23:52:55 +0000383 msg_pdbg2("\n");
384}
385
Nico Huberfa622942017-03-24 17:25:37 +0100386void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000387{
Nico Huber519be662018-12-23 20:03:35 +0100388 ssize_t i;
Nico Huberfa622942017-03-24 17:25:37 +0100389 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000390 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100391 if (nm < 0) {
392 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
393 desc->content.NM + 1);
394 return;
395 }
396 for (i = 0; i < nm; i++)
Nico Huber519be662018-12-23 20:03:35 +0100397 msg_pdbg2("FLMSTR%zd 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000398 msg_pdbg2("\n");
399
400 msg_pdbg2("--- Details ---\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200401 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT ||
402 cs == CHIPSET_300_SERIES_CANNON_POINT) {
Nico Huberfa622942017-03-24 17:25:37 +0100403 const char *const master_names[] = {
404 "BIOS", "ME", "GbE", "unknown", "EC",
405 };
Nico Huber519be662018-12-23 20:03:35 +0100406 if (nm >= (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberfa622942017-03-24 17:25:37 +0100407 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
408 desc->content.NM + 1);
409 return;
410 }
411
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200412 size_t num_regions;
413 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9");
414 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
415 num_regions = 10;
416 msg_pdbg2("\n");
417 } else {
418 num_regions = 16;
419 msg_pdbg2(" RegA RegB RegC RegD RegE RegF\n");
420 }
Nico Huberfa622942017-03-24 17:25:37 +0100421 for (i = 0; i < nm; i++) {
422 size_t j;
423 msg_pdbg2("%-4s", master_names[i]);
Nico Huber961f4a12019-10-04 17:34:22 +0200424 for (j = 0; j < (size_t)min(num_regions, 12); j++)
Nico Huberfa622942017-03-24 17:25:37 +0100425 msg_pdbg2(" %c%c ",
426 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
427 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200428 for (; j < num_regions; j++)
429 msg_pdbg2(" %c%c ",
430 desc->master.mstr[i].ext_read & (1 << (j - 12)) ? 'r' : ' ',
431 desc->master.mstr[i].ext_write & (1 << (j - 12)) ? 'w' : ' ');
Nico Huberfa622942017-03-24 17:25:37 +0100432 msg_pdbg2("\n");
433 }
David Hendricksa5216362017-08-08 20:02:22 -0700434 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
435 const char *const master_names[] = {
436 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
437 };
438 /* NM starts at 1 instead of 0 for LBG */
Nico Huber519be662018-12-23 20:03:35 +0100439 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
David Hendricksa5216362017-08-08 20:02:22 -0700440 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
441 desc->content.NM);
442 return;
443 }
444
445 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
446 " ", /* width of master name (4 chars minimum) */
447 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
448 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
449 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
450 "Reg15");
451 for (i = 0; i < nm; i++) {
452 size_t j;
453 msg_pdbg2("%-4s", master_names[i]);
454 for (j = 0; j < 16; 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 Huberd2d39932019-01-18 16:49:37 +0100460 } else if (cs == CHIPSET_APOLLO_LAKE) {
461 const char *const master_names[] = { "BIOS", "TXE", };
Nico Huber519be662018-12-23 20:03:35 +0100462 if (nm > (ssize_t)ARRAY_SIZE(master_names)) {
Nico Huberd2d39932019-01-18 16:49:37 +0100463 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
464 return;
465 }
466
467 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
468 for (i = 0; i < nm; i++) {
Nico Huber519be662018-12-23 20:03:35 +0100469 ssize_t j;
Nico Huberd2d39932019-01-18 16:49:37 +0100470 msg_pdbg2("%-4s", master_names[i]);
471 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
472 msg_pdbg2(" %c%c ",
473 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
474 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
475 msg_pdbg2("\n");
476 }
Nico Huberfa622942017-03-24 17:25:37 +0100477 } else {
478 const struct ich_desc_master *const mstr = &desc->master;
479 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
480 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
481 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
482 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
483 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
484 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
485 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
486 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
487 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
488 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
489 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
490 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
491 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
492 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
493 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
494 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
495 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
496 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
497 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
498 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000499 msg_pdbg2("\n");
500}
501
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600502static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000503{
504 static const char * const str_GPIO12[4] = {
505 "GPIO12",
506 "LAN PHY Power Control Function (Native Output)",
507 "GLAN_DOCK# (Native Input)",
508 "invalid configuration",
509 };
510
511 msg_pdbg2("--- MCH details ---\n");
512 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
513 msg_pdbg2("\n");
514
515 msg_pdbg2("--- ICH details ---\n");
516 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
517 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
518 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
519 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
520 msg_pdbg2("SPI CS1 is used for %s.\n",
521 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
522 "LAN PHY Power Control Function" :
523 "SPI Chip Select");
524 msg_pdbg2("GPIO12 is used as %s.\n",
525 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
526 msg_pdbg2("PCIe Port 6 is used for %s.\n",
527 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
528 msg_pdbg2("%sn BMC Mode: "
529 "Intel AMT SMBus Controller 1 is connected to %s.\n",
530 desc->south.ich8.BMCMODE ? "I" : "Not i",
531 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
532 msg_pdbg2("TCO is in %s Mode.\n",
533 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
534 msg_pdbg2("ME A is %sabled.\n",
535 desc->south.ich8.ME_DISABLE ? "dis" : "en");
536 msg_pdbg2("\n");
537}
538
539static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
540{
541 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
542
543 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000544 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000545 case 0:
546 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
547 break;
548 case 1:
549 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
550 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
551 break;
552 case 2:
553 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
554 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
555 break;
556 case 3:
557 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
558 1+off, 2+off, 4+off);
559 break;
560 }
561 msg_pdbg2("\n");
562}
563
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600564static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000565{
566 /* PCHSTRP4 */
567 msg_pdbg2("Intel PHY is %s.\n",
568 (s->ibex.PHYCON == 2) ? "connected" :
569 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
570 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
571 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
572 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
573 s->ibex.GBEMAC_SMBUS_ADDR);
574 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
575 s->ibex.GBEPHY_SMBUS_ADDR);
576
577 /* PCHSTRP5 */
578 /* PCHSTRP6 */
579 /* PCHSTRP7 */
580 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
581 s->ibex.MESMA2UDID_VENDOR);
582 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
583 s->ibex.MESMA2UDID_VENDOR);
584
585 /* PCHSTRP8 */
586}
587
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600588static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000589{
590 /* PCHSTRP11 */
591 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
592 s->ibex.SML1GPAEN ? "en" : "dis");
593 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
594 s->ibex.SML1GPA);
595 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
596 s->ibex.SML1I2CAEN ? "en" : "dis");
597 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
598 s->ibex.SML1I2CA);
599
600 /* PCHSTRP12 */
601 /* PCHSTRP13 */
602}
603
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600604static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000605{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000606 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000607 100,
608 50,
609 5,
610 1
611 };
612
613 msg_pdbg2("--- PCH ---\n");
614
615 /* PCHSTRP0 */
616 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
617 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
618 s->ibex.SMB_EN ? "en" : "dis");
619 msg_pdbg2("SMLink0 segment is %sabled.\n",
620 s->ibex.SML0_EN ? "en" : "dis");
621 msg_pdbg2("SMLink1 segment is %sabled.\n",
622 s->ibex.SML1_EN ? "en" : "dis");
623 msg_pdbg2("SMLink1 Frequency: %s\n",
624 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
625 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
626 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
627 msg_pdbg2("SMLink0 Frequency: %s\n",
628 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
629 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
630 "LAN_PHY_PWR_CTRL" : "general purpose output");
631 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
632 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
633 s->ibex.DMI_REQID_DIS ? "en" : "dis");
634 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
635 1 << (6 + s->ibex.BBBS));
636
637 /* PCHSTRP1 */
638 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
639
640 /* PCHSTRP2 */
641 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
642 s->ibex.MESMASDEN ? "en" : "dis");
643 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
644 s->ibex.MESMASDA);
645 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
646 s->ibex.MESMI2CEN ? "en" : "dis");
647 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
648 s->ibex.MESMI2CA);
649
650 /* PCHSTRP3 */
651 prettyprint_ich_descriptor_pchstraps45678_56(s);
652 /* PCHSTRP9 */
653 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
654 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
655 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
656 s->ibex.PCIELR1 ? "" : "not ");
657 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
658 s->ibex.PCIELR2 ? "" : "not ");
659 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
660 s->ibex.DMILR ? "" : "not ");
661 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
662 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
663 s->ibex.PHY_PCIE_EN ? "en" : "dis");
664
665 /* PCHSTRP10 */
666 msg_pdbg2("Management Engine will boot from %sflash.\n",
667 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
668 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
669 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
670 s->ibex.VE_EN ? "en" : "dis");
671 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
672 s->ibex.MMDDE ? "en" : "dis");
673 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
674 s->ibex.MMADDR);
675 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
676 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
677 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
678 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
679 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
680
681 prettyprint_ich_descriptor_pchstraps111213_56(s);
682
683 /* PCHSTRP14 */
684 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
685 s->ibex.VE_EN2 ? "en" : "dis");
686 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
687 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
688 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
689 s->ibex.BW_SSD ? "en" : "dis");
690 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
691 s->ibex.NVMHCI_EN ? "en" : "dis");
692
693 /* PCHSTRP15 */
694 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
695 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
696 s->ibex.IWL_EN ? "en" : "dis");
697 msg_pdbg2("t209 min Timing: %d ms\n",
698 dec_t209min[s->ibex.t209min]);
699 msg_pdbg2("\n");
700}
701
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600702static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000703{
704 msg_pdbg2("--- PCH ---\n");
705
706 /* PCHSTRP0 */
707 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
708 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
709 s->ibex.SMB_EN ? "en" : "dis");
710 msg_pdbg2("SMLink0 segment is %sabled.\n",
711 s->ibex.SML0_EN ? "en" : "dis");
712 msg_pdbg2("SMLink1 segment is %sabled.\n",
713 s->ibex.SML1_EN ? "en" : "dis");
714 msg_pdbg2("SMLink1 Frequency: %s\n",
715 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
716 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
717 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
718 msg_pdbg2("SMLink0 Frequency: %s\n",
719 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
720 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
721 "LAN_PHY_PWR_CTRL" : "general purpose output");
722 msg_pdbg2("LinkSec is %sabled.\n",
723 s->cougar.LINKSEC_DIS ? "en" : "dis");
724 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
725 s->ibex.DMI_REQID_DIS ? "en" : "dis");
726 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
727 1 << (6 + s->ibex.BBBS));
728
729 /* PCHSTRP1 */
730 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
731 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
732
733 /* PCHSTRP2 */
734 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
735 s->ibex.MESMASDEN ? "en" : "dis");
736 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
737 s->ibex.MESMASDA);
738 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
739 s->cougar.MESMMCTPAEN ? "en" : "dis");
740 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
741 s->cougar.MESMMCTPA);
742 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
743 s->ibex.MESMI2CEN ? "en" : "dis");
744 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
745 s->ibex.MESMI2CA);
746
747 /* PCHSTRP3 */
748 prettyprint_ich_descriptor_pchstraps45678_56(s);
749 /* PCHSTRP9 */
750 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
751 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
752 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
753 s->ibex.PCIELR1 ? "" : "not ");
754 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
755 s->ibex.PCIELR2 ? "" : "not ");
756 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
757 s->ibex.DMILR ? "" : "not ");
758 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
759 s->cougar.MDSMBE_EN ? "en" : "dis");
760 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
761 s->cougar.MDSMBE_ADD);
762 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
763 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
764 s->ibex.PHY_PCIE_EN ? "en" : "dis");
765 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
766 s->cougar.SUB_DECODE_EN ? "en" : "dis");
767 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
768 "PCHHOT#" : "SML1ALERT#");
769
770 /* PCHSTRP10 */
771 msg_pdbg2("Management Engine will boot from %sflash.\n",
772 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
773
774 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
775 s->cougar.MDSMBE_EN ? "en" : "dis");
776 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
777 s->cougar.MDSMBE_ADD);
778
779 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
780 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000781 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
782 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000783 msg_pdbg2("ICC Profile is selected by %s.\n",
784 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
785 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
786 s->cougar.Deep_SX_EN ? "not " : "");
787 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
788 s->cougar.ME_DBG_LAN ? "en" : "dis");
789
790 prettyprint_ich_descriptor_pchstraps111213_56(s);
791
792 /* PCHSTRP14 */
793 /* PCHSTRP15 */
794 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
795 msg_pdbg2("Integrated wired LAN is %sabled.\n",
796 s->cougar.IWL_EN ? "en" : "dis");
797 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
798 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000799 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000800 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
801 "general purpose output" : "SLP_LAN#");
802
803 /* PCHSTRP16 */
804 /* PCHSTRP17 */
805 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
806 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
807 msg_pdbg2("\n");
808}
809
810void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
811{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000812 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000813 msg_pdbg2("=== Softstraps ===\n");
814
Nico Huber519be662018-12-23 20:03:35 +0100815 max_count = MIN(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
Nico Huberd7c75522017-03-29 16:31:49 +0200816 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000817 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200818 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000819 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200820 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000821
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000822 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
823 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000824 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
825 msg_pdbg2("\n");
826
Nico Huber519be662018-12-23 20:03:35 +0100827 max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
Nico Huberd7c75522017-03-29 16:31:49 +0200828 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000829 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
830 desc->content.ISL, max_count);
831 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200832 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000833
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000834 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
835 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000836 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
837 msg_pdbg2("\n");
838
839 switch (cs) {
840 case CHIPSET_ICH8:
841 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
842 msg_pdbg2("Detailed North/MCH/PROC information is "
843 "probably not reliable, printing anyway.\n");
844 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
845 msg_pdbg2("Detailed South/ICH/PCH information is "
846 "probably not reliable, printing anyway.\n");
847 prettyprint_ich_descriptor_straps_ich8(desc);
848 break;
849 case CHIPSET_5_SERIES_IBEX_PEAK:
850 /* PCH straps only. PROCSTRPs are unknown. */
851 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
852 msg_pdbg2("Detailed South/ICH/PCH information is "
853 "probably not reliable, printing anyway.\n");
854 prettyprint_ich_descriptor_straps_ibex(&desc->south);
855 break;
856 case CHIPSET_6_SERIES_COUGAR_POINT:
857 /* PCH straps only. PROCSTRP0 is "reserved". */
858 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
859 msg_pdbg2("Detailed South/ICH/PCH information is "
860 "probably not reliable, printing anyway.\n");
861 prettyprint_ich_descriptor_straps_cougar(&desc->south);
862 break;
863 case CHIPSET_ICH_UNKNOWN:
864 break;
865 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000866 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000867 break;
868 }
869}
870
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600871static void prettyprint_rdid(uint32_t reg_val)
Stefan Taunerb3850962011-12-24 00:00:32 +0000872{
873 uint8_t mid = reg_val & 0xFF;
874 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
875 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
876}
877
878void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
879{
880 int i;
881 msg_pdbg2("=== Upper Map Section ===\n");
882 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
883 msg_pdbg2("\n");
884
885 msg_pdbg2("--- Details ---\n");
886 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
887 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
888 msg_pdbg2("\n");
889
890 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000891 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000892 uint32_t jid = umap->vscc_table[i].JID;
893 uint32_t vscc = umap->vscc_table[i].VSCC;
894 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
895 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
896 msg_pdbg2(" "); /* indention */
897 prettyprint_rdid(jid);
898 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000899 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000900 }
901 msg_pdbg2("\n");
902}
903
Nico Huber1dc3d422017-06-17 00:09:31 +0200904/*
905 * Guesses a minimum chipset version based on the maximum number of
906 * soft straps per generation.
907 */
908static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
909{
910 if (content->ICCRIBA == 0x00) {
911 if (content->MSL == 0 && content->ISL <= 2)
912 return CHIPSET_ICH8;
913 else if (content->ISL <= 2)
914 return CHIPSET_ICH9;
915 else if (content->ISL <= 10)
916 return CHIPSET_ICH10;
917 else if (content->ISL <= 16)
918 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huberd2d39932019-01-18 16:49:37 +0100919 else if (content->FLMAP2 == 0) {
920 if (content->ISL != 19)
921 msg_pwarn("Peculiar firmware descriptor, assuming Apollo Lake compatibility.\n");
922 return CHIPSET_APOLLO_LAKE;
923 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200924 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
925 return CHIPSET_5_SERIES_IBEX_PEAK;
926 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
927 if (content->MSL == 0 && content->ISL <= 17)
928 return CHIPSET_BAYTRAIL;
929 else if (content->MSL <= 1 && content->ISL <= 18)
930 return CHIPSET_6_SERIES_COUGAR_POINT;
931 else if (content->MSL <= 1 && content->ISL <= 21)
932 return CHIPSET_8_SERIES_LYNX_POINT;
933 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
934 return CHIPSET_9_SERIES_WILDCAT_POINT;
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200935 } else if (content->ICCRIBA < 0x34) {
936 if (content->NM == 6)
937 return CHIPSET_C620_SERIES_LEWISBURG;
938 else
939 return CHIPSET_100_SERIES_SUNRISE_POINT;
Jonathan Zhange19a41b2020-08-19 12:19:06 -0700940 } else if (content->ICCRIBA == 0x34) {
941 if (content->NM == 6)
942 return CHIPSET_C620_SERIES_LEWISBURG;
943 else
944 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200945 } else {
Jonathan Zhange19a41b2020-08-19 12:19:06 -0700946 msg_pwarn("Unknown firmware descriptor, assuming 300 series compatibility.\n");
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200947 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200948 }
949}
950
951/*
952 * As an additional measure, we check the read frequency like `ifdtool`.
953 * The frequency value 6 (17MHz) was reserved before Skylake and is the
954 * only valid value since. Skylake is currently the most important dis-
955 * tinction because of the dropped number of regions field (NR).
956 */
Nico Huberfa622942017-03-24 17:25:37 +0100957static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
958 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200959{
960 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
961
Nico Huberd2d39932019-01-18 16:49:37 +0100962 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200963 case CHIPSET_300_SERIES_CANNON_POINT:
964 /* `freq_read` was repurposed, so can't check on it any more. */
965 return guess;
Nico Huberd2d39932019-01-18 16:49:37 +0100966 case CHIPSET_100_SERIES_SUNRISE_POINT:
967 case CHIPSET_C620_SERIES_LEWISBURG:
968 case CHIPSET_APOLLO_LAKE:
969 if (component->modes.freq_read != 6) {
970 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
971 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
972 "Please report this message, the output of `ich_descriptors_tool` for\n"
973 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
974 return CHIPSET_9_SERIES_WILDCAT_POINT;
975 }
976 return guess;
977 default:
978 if (component->modes.freq_read == 6) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200979 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
980 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
981 "Please report this message, the output of `ich_descriptors_tool` for\n"
982 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -0700983 return CHIPSET_100_SERIES_SUNRISE_POINT;
984 }
985 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +0200986 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200987}
988
Stefan Taunerb3850962011-12-24 00:00:32 +0000989/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +0100990int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
991 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000992{
Nico Huber519be662018-12-23 20:03:35 +0100993 ssize_t i, max_count;
994 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +0000995
996 if (dump == NULL || desc == NULL)
997 return ICH_RET_PARAM;
998
999 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
1000 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
1001 pch_bug_offset = 4;
1002 else
1003 return ICH_RET_ERR;
1004 }
1005
1006 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001007 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001008 return ICH_RET_OOB;
1009 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1010 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1011 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1012 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1013
1014 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001015 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001016 return ICH_RET_OOB;
1017 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1018 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1019 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1020
Nico Huber67d71792017-06-17 03:10:15 +02001021 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +01001022 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +02001023 prettyprint_ich_chipset(*cs);
1024 }
Nico Huberfa622942017-03-24 17:25:37 +01001025
Stefan Taunerb3850962011-12-24 00:00:32 +00001026 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001027 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001028 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001029 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001030 for (i = 0; i < nr; i++)
1031 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001032
1033 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001034 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001035 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001036 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001037 for (i = 0; i < nm; i++)
1038 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001039
1040 /* upper map */
1041 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1042
1043 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1044 * "Identifies the 1s based number of DWORDS contained in the VSCC
1045 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1046 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1047 * check ensures that the maximum offset actually accessed is available.
1048 */
Nico Huber9e14aed2017-03-28 17:08:46 +02001049 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +00001050 return ICH_RET_OOB;
1051
1052 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001053 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1054 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +00001055 }
1056
1057 /* MCH/PROC (aka. North) straps */
1058 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1059 return ICH_RET_OOB;
1060
1061 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001062 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001063 for (i = 0; i < max_count; i++)
1064 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001065
1066 /* ICH/PCH (aka. South) straps */
1067 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1068 return ICH_RET_OOB;
1069
1070 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001071 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001072 for (i = 0; i < max_count; i++)
1073 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001074
1075 return ICH_RET_OK;
1076}
1077
Nico Huberad186312016-05-02 15:15:29 +02001078#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001079
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001080/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001081\em idx in bytes or -1 if the correct size can not be determined. */
1082int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001083{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001084 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001085 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001086 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001087 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001088
1089 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001090 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001091
1092 uint8_t size_enc;
1093 uint8_t size_max;
1094
1095 switch (cs) {
1096 case CHIPSET_ICH8:
1097 case CHIPSET_ICH9:
1098 case CHIPSET_ICH10:
1099 case CHIPSET_5_SERIES_IBEX_PEAK:
1100 case CHIPSET_6_SERIES_COUGAR_POINT:
1101 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001102 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001103 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001104 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001105 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001106 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001107 }
1108 size_max = 5;
1109 break;
1110 case CHIPSET_8_SERIES_LYNX_POINT:
1111 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1112 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001113 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001114 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001115 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001116 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001117 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001118 case CHIPSET_APOLLO_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001119 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001120 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001121 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001122 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001123 }
1124 size_max = 7;
1125 break;
1126 case CHIPSET_ICH_UNKNOWN:
1127 default:
1128 msg_pwarn("Density encoding is unknown on this chipset.\n");
1129 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001130 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001131
1132 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001133 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001134 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1135 idx, size_enc, size_max);
1136 return -1;
1137 }
1138
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001139 return (1 << (19 + size_enc));
1140}
1141
Nico Huber8d494992017-06-19 12:18:33 +02001142/* Only used by ichspi.c */
1143#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001144static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001145{
1146 uint32_t control = 0;
1147 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1148 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001149 switch (cs) {
1150 case CHIPSET_100_SERIES_SUNRISE_POINT:
1151 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001152 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001153 case CHIPSET_APOLLO_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001154 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1155 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001156 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001157 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1158 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1159 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001160}
1161
Nico Huberd54e4f42017-03-23 23:45:47 +01001162int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001163{
Nico Huber519be662018-12-23 20:03:35 +01001164 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001165 struct ich_desc_region *r = &desc->region;
1166
1167 /* Test if bit-fields are working as expected.
1168 * FIXME: Replace this with dynamic bitfield fixup
1169 */
1170 for (i = 0; i < 4; i++)
1171 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001172 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1173 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1174 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1175 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001176 msg_pdbg("The combination of compiler and CPU architecture used"
1177 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001178 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1179 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1180 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1181 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1182 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1183 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1184 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1185 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001186 return ICH_RET_ERR;
1187 }
1188
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001189 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001190 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001191 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1192 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1193 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1194 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001195
1196 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001197 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1198 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1199 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001200
1201 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001202 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1203 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001204 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001205 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001206 return ICH_RET_ERR;
1207 }
Nico Huberfa622942017-03-24 17:25:37 +01001208 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001209 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001210
1211 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001212 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1213 if (nm < 0) {
1214 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1215 __func__, desc->content.NM + 1);
1216 return ICH_RET_ERR;
1217 }
1218 for (i = 0; i < nm; i++)
1219 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001220
1221 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1222 * reading the upper map is impossible on all chipsets, so don't bother.
1223 */
1224
1225 msg_pdbg2(" done.\n");
1226 return ICH_RET_OK;
1227}
Nico Huber8d494992017-06-19 12:18:33 +02001228#endif
Nico Huber305f4172013-06-14 11:55:26 +02001229
1230/**
1231 * @brief Read a layout from the dump of an Intel ICH descriptor.
1232 *
1233 * @param layout Pointer where to store the layout.
1234 * @param dump The descriptor dump to read from.
1235 * @param len The length of the descriptor dump.
1236 *
1237 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001238 * 1 if the descriptor couldn't be parsed,
1239 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001240 */
1241int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1242{
Nico Huberfa622942017-03-24 17:25:37 +01001243 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001244 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1245 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001246 };
Nico Huber305f4172013-06-14 11:55:26 +02001247
1248 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001249 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1250 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001251 return 1;
1252
1253 memset(layout, 0x00, sizeof(*layout));
1254
Nico Huberfa622942017-03-24 17:25:37 +01001255 ssize_t i, j;
Nico Huber519be662018-12-23 20:03:35 +01001256 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
1257 for (i = 0, j = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001258 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001259 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001260 if (limit <= base)
1261 continue;
1262 layout->entries[j].start = base;
1263 layout->entries[j].end = limit;
1264 layout->entries[j].included = false;
Nico Huber70461a92019-06-15 14:56:19 +02001265 layout->entries[j].name = strdup(regions[i]);
1266 if (!layout->entries[j].name)
1267 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001268 ++j;
1269 }
1270 layout->base.entries = layout->entries;
1271 layout->base.num_entries = j;
1272 return 0;
1273}
1274
Nico Huberad186312016-05-02 15:15:29 +02001275#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */