blob: 120d3feab8e107c76ba4beca563abe5687940dd5 [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;
Nico Huber1dc3d422017-06-17 00:09:31 +0200940 } else {
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200941 if (content->ICCRIBA > 0x34)
942 msg_pwarn("Unknown firmware descriptor, assuming 300 series compatibility.\n");
943 return CHIPSET_300_SERIES_CANNON_POINT;
Nico Huber1dc3d422017-06-17 00:09:31 +0200944 }
945}
946
947/*
948 * As an additional measure, we check the read frequency like `ifdtool`.
949 * The frequency value 6 (17MHz) was reserved before Skylake and is the
950 * only valid value since. Skylake is currently the most important dis-
951 * tinction because of the dropped number of regions field (NR).
952 */
Nico Huberfa622942017-03-24 17:25:37 +0100953static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
954 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200955{
956 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
957
Nico Huberd2d39932019-01-18 16:49:37 +0100958 switch (guess) {
Nico Huber2a5dfaf2019-07-04 16:01:51 +0200959 case CHIPSET_300_SERIES_CANNON_POINT:
960 /* `freq_read` was repurposed, so can't check on it any more. */
961 return guess;
Nico Huberd2d39932019-01-18 16:49:37 +0100962 case CHIPSET_100_SERIES_SUNRISE_POINT:
963 case CHIPSET_C620_SERIES_LEWISBURG:
964 case CHIPSET_APOLLO_LAKE:
965 if (component->modes.freq_read != 6) {
966 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
967 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
968 "Please report this message, the output of `ich_descriptors_tool` for\n"
969 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
970 return CHIPSET_9_SERIES_WILDCAT_POINT;
971 }
972 return guess;
973 default:
974 if (component->modes.freq_read == 6) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200975 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
976 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
977 "Please report this message, the output of `ich_descriptors_tool` for\n"
978 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -0700979 return CHIPSET_100_SERIES_SUNRISE_POINT;
980 }
981 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +0200982 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200983}
984
Stefan Taunerb3850962011-12-24 00:00:32 +0000985/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +0100986int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
987 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000988{
Nico Huber519be662018-12-23 20:03:35 +0100989 ssize_t i, max_count;
990 size_t pch_bug_offset = 0;
Stefan Taunerb3850962011-12-24 00:00:32 +0000991
992 if (dump == NULL || desc == NULL)
993 return ICH_RET_PARAM;
994
995 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
996 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
997 pch_bug_offset = 4;
998 else
999 return ICH_RET_ERR;
1000 }
1001
1002 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +02001003 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001004 return ICH_RET_OOB;
1005 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
1006 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
1007 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
1008 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
1009
1010 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +02001011 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001012 return ICH_RET_OOB;
1013 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
1014 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
1015 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
1016
Nico Huber67d71792017-06-17 03:10:15 +02001017 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +01001018 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +02001019 prettyprint_ich_chipset(*cs);
1020 }
Nico Huberfa622942017-03-24 17:25:37 +01001021
Stefan Taunerb3850962011-12-24 00:00:32 +00001022 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001023 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001024 if (nr < 0 || len < getFRBA(&desc->content) + (size_t)nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001025 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001026 for (i = 0; i < nr; i++)
1027 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001028
1029 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001030 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
Nico Huber519be662018-12-23 20:03:35 +01001031 if (nm < 0 || len < getFMBA(&desc->content) + (size_t)nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001032 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001033 for (i = 0; i < nm; i++)
1034 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001035
1036 /* upper map */
1037 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1038
1039 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1040 * "Identifies the 1s based number of DWORDS contained in the VSCC
1041 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1042 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1043 * check ensures that the maximum offset actually accessed is available.
1044 */
Nico Huber9e14aed2017-03-28 17:08:46 +02001045 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +00001046 return ICH_RET_OOB;
1047
1048 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001049 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1050 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +00001051 }
1052
1053 /* MCH/PROC (aka. North) straps */
1054 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1055 return ICH_RET_OOB;
1056
1057 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001058 max_count = MIN(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001059 for (i = 0; i < max_count; i++)
1060 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001061
1062 /* ICH/PCH (aka. South) straps */
1063 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1064 return ICH_RET_OOB;
1065
1066 /* limit the range to be written */
Nico Huber519be662018-12-23 20:03:35 +01001067 max_count = MIN(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001068 for (i = 0; i < max_count; i++)
1069 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001070
1071 return ICH_RET_OK;
1072}
1073
Nico Huberad186312016-05-02 15:15:29 +02001074#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001075
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001076/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001077\em idx in bytes or -1 if the correct size can not be determined. */
1078int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001079{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001080 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001081 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001082 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001083 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001084
1085 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001086 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001087
1088 uint8_t size_enc;
1089 uint8_t size_max;
1090
1091 switch (cs) {
1092 case CHIPSET_ICH8:
1093 case CHIPSET_ICH9:
1094 case CHIPSET_ICH10:
1095 case CHIPSET_5_SERIES_IBEX_PEAK:
1096 case CHIPSET_6_SERIES_COUGAR_POINT:
1097 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001098 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001099 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001100 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001101 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001102 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001103 }
1104 size_max = 5;
1105 break;
1106 case CHIPSET_8_SERIES_LYNX_POINT:
1107 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1108 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001109 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001110 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001111 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001112 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001113 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001114 case CHIPSET_APOLLO_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001115 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001116 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001117 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001118 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001119 }
1120 size_max = 7;
1121 break;
1122 case CHIPSET_ICH_UNKNOWN:
1123 default:
1124 msg_pwarn("Density encoding is unknown on this chipset.\n");
1125 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001126 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001127
1128 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001129 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001130 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1131 idx, size_enc, size_max);
1132 return -1;
1133 }
1134
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001135 return (1 << (19 + size_enc));
1136}
1137
Nico Huber8d494992017-06-19 12:18:33 +02001138/* Only used by ichspi.c */
1139#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001140static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001141{
1142 uint32_t control = 0;
1143 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1144 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001145 switch (cs) {
1146 case CHIPSET_100_SERIES_SUNRISE_POINT:
1147 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huber2a5dfaf2019-07-04 16:01:51 +02001148 case CHIPSET_300_SERIES_CANNON_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +01001149 case CHIPSET_APOLLO_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001150 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1151 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001152 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001153 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1154 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1155 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001156}
1157
Nico Huberd54e4f42017-03-23 23:45:47 +01001158int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001159{
Nico Huber519be662018-12-23 20:03:35 +01001160 ssize_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001161 struct ich_desc_region *r = &desc->region;
1162
1163 /* Test if bit-fields are working as expected.
1164 * FIXME: Replace this with dynamic bitfield fixup
1165 */
1166 for (i = 0; i < 4; i++)
1167 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001168 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1169 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1170 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1171 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001172 msg_pdbg("The combination of compiler and CPU architecture used"
1173 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001174 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1175 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1176 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1177 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1178 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1179 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1180 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1181 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001182 return ICH_RET_ERR;
1183 }
1184
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001185 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001186 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001187 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1188 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1189 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1190 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001191
1192 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001193 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1194 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1195 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001196
1197 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001198 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1199 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001200 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001201 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001202 return ICH_RET_ERR;
1203 }
Nico Huberfa622942017-03-24 17:25:37 +01001204 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001205 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001206
1207 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001208 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1209 if (nm < 0) {
1210 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1211 __func__, desc->content.NM + 1);
1212 return ICH_RET_ERR;
1213 }
1214 for (i = 0; i < nm; i++)
1215 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001216
1217 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1218 * reading the upper map is impossible on all chipsets, so don't bother.
1219 */
1220
1221 msg_pdbg2(" done.\n");
1222 return ICH_RET_OK;
1223}
Nico Huber8d494992017-06-19 12:18:33 +02001224#endif
Nico Huber305f4172013-06-14 11:55:26 +02001225
1226/**
1227 * @brief Read a layout from the dump of an Intel ICH descriptor.
1228 *
1229 * @param layout Pointer where to store the layout.
1230 * @param dump The descriptor dump to read from.
1231 * @param len The length of the descriptor dump.
1232 *
1233 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001234 * 1 if the descriptor couldn't be parsed,
1235 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001236 */
1237int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1238{
Nico Huberfa622942017-03-24 17:25:37 +01001239 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001240 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1241 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001242 };
Nico Huber305f4172013-06-14 11:55:26 +02001243
1244 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001245 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1246 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001247 return 1;
1248
1249 memset(layout, 0x00, sizeof(*layout));
1250
Nico Huberfa622942017-03-24 17:25:37 +01001251 ssize_t i, j;
Nico Huber519be662018-12-23 20:03:35 +01001252 const ssize_t nr = MIN(ich_number_of_regions(cs, &desc.content), (ssize_t)ARRAY_SIZE(regions));
1253 for (i = 0, j = 0; i < nr; ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001254 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001255 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001256 if (limit <= base)
1257 continue;
1258 layout->entries[j].start = base;
1259 layout->entries[j].end = limit;
1260 layout->entries[j].included = false;
Nico Huber70461a92019-06-15 14:56:19 +02001261 layout->entries[j].name = strdup(regions[i]);
1262 if (!layout->entries[j].name)
1263 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001264 ++j;
1265 }
1266 layout->base.entries = layout->entries;
1267 layout->base.num_entries = j;
1268 return 0;
1269}
1270
Nico Huberad186312016-05-02 15:15:29 +02001271#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */