blob: a757addd367a353d1b5f16cd4a4862d92368721b [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
Stefan Taunerb3850962011-12-24 00:00:32 +000038#ifndef min
Nico Huber305f4172013-06-14 11:55:26 +020039#define min(a, b) (((a) < (b)) ? (a) : (b))
Stefan Taunerb3850962011-12-24 00:00:32 +000040#endif
41
Nico Huberfa622942017-03-24 17:25:37 +010042ssize_t ich_number_of_regions(const enum ich_chipset cs, const struct ich_desc_content *const cont)
43{
44 switch (cs) {
Nico Huberd2d39932019-01-18 16:49:37 +010045 case CHIPSET_APOLLO_LAKE:
46 return 6;
David Hendricksa5216362017-08-08 20:02:22 -070047 case CHIPSET_C620_SERIES_LEWISBURG:
48 return 16;
Nico Huberfa622942017-03-24 17:25:37 +010049 case CHIPSET_100_SERIES_SUNRISE_POINT:
50 return 10;
51 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
52 case CHIPSET_9_SERIES_WILDCAT_POINT:
53 case CHIPSET_8_SERIES_LYNX_POINT_LP:
54 case CHIPSET_8_SERIES_LYNX_POINT:
55 case CHIPSET_8_SERIES_WELLSBURG:
56 if (cont->NR <= 6)
57 return cont->NR + 1;
58 else
59 return -1;
60 default:
61 if (cont->NR <= 4)
62 return cont->NR + 1;
63 else
64 return -1;
65 }
66}
67
68ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
69{
David Hendricksa5216362017-08-08 20:02:22 -070070 switch (cs) {
71 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberd2d39932019-01-18 16:49:37 +010072 case CHIPSET_APOLLO_LAKE:
David Hendricksa5216362017-08-08 20:02:22 -070073 if (cont->NM <= MAX_NUM_MASTERS)
74 return cont->NM;
Richard Hughesdb7482b2018-12-19 12:04:30 +000075 break;
David Hendricksa5216362017-08-08 20:02:22 -070076 default:
77 if (cont->NM < MAX_NUM_MASTERS)
78 return cont->NM + 1;
79 }
80
81 return -1;
Nico Huberfa622942017-03-24 17:25:37 +010082}
83
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000084void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000085{
86 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
87 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
88 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
89 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000090 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
91 if (print_vcl)
92 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
93 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000094}
95
96#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
97#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
98#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
99#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
100#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
101
Nico Huber67d71792017-06-17 03:10:15 +0200102void prettyprint_ich_chipset(enum ich_chipset cs)
103{
104 static const char *const chipset_names[] = {
105 "Unknown ICH", "ICH8", "ICH9", "ICH10",
106 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
107 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
108 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
Nico Huberd2d39932019-01-18 16:49:37 +0100109 "C620 series Lewisburg", "Apollo Lake",
Nico Huber67d71792017-06-17 03:10:15 +0200110 };
111 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
112 cs = 0;
113 else
114 cs = cs - CHIPSET_ICH8 + 1;
115 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
116}
117
Stefan Tauner1e146392011-09-15 23:52:55 +0000118void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
119{
Nico Huberfa622942017-03-24 17:25:37 +0100120 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000121 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100122 prettyprint_ich_descriptor_region(cs, desc);
123 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200124#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000125 if (cs >= CHIPSET_ICH8) {
126 prettyprint_ich_descriptor_upper_map(&desc->upper);
127 prettyprint_ich_descriptor_straps(cs, desc);
128 }
Nico Huberad186312016-05-02 15:15:29 +0200129#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000130}
131
Nico Huberfa622942017-03-24 17:25:37 +0100132void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000133{
134 msg_pdbg2("=== Content Section ===\n");
135 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
136 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
137 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
138 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
139 msg_pdbg2("\n");
140
141 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100142 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
143 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
144 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
145 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
Nico Huberd2d39932019-01-18 16:49:37 +0100146 msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL);
147 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont));
Nico Huberfa622942017-03-24 17:25:37 +0100148 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
149 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
150 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
151 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000152 msg_pdbg2("\n");
153}
154
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000155static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
156{
157 if (idx > 1) {
158 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
159 return NULL;
160 }
161
162 if (desc->content.NC == 0 && idx > 0)
163 return "unused";
164
165 static const char * const size_str[] = {
166 "512 kB", /* 0000 */
167 "1 MB", /* 0001 */
168 "2 MB", /* 0010 */
169 "4 MB", /* 0011 */
170 "8 MB", /* 0100 */
171 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
172 "32 MB", /* 0110 */
173 "64 MB", /* 0111 */
174 };
175
176 switch (cs) {
177 case CHIPSET_ICH8:
178 case CHIPSET_ICH9:
179 case CHIPSET_ICH10:
180 case CHIPSET_5_SERIES_IBEX_PEAK:
181 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000182 case CHIPSET_7_SERIES_PANTHER_POINT:
183 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000184 uint8_t size_enc;
185 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000186 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000187 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000188 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000189 }
190 if (size_enc > 5)
191 return "reserved";
192 return size_str[size_enc];
193 }
194 case CHIPSET_8_SERIES_LYNX_POINT:
195 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000196 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100197 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100198 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
David Hendricksa5216362017-08-08 20:02:22 -0700199 case CHIPSET_100_SERIES_SUNRISE_POINT:
Nico Huberd2d39932019-01-18 16:49:37 +0100200 case CHIPSET_C620_SERIES_LEWISBURG:
201 case CHIPSET_APOLLO_LAKE: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000202 uint8_t size_enc;
203 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000204 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000205 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000206 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000207 }
208 if (size_enc > 7)
209 return "reserved";
210 return size_str[size_enc];
211 }
212 case CHIPSET_ICH_UNKNOWN:
213 default:
214 return "unknown";
215 }
216}
217
218static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000219{
Nico Huberd2d39932019-01-18 16:49:37 +0100220 static const char *const freq_str[3][8] = { {
Nico Huber129e9382019-06-06 15:43:27 +0200221 "20 MHz",
222 "33 MHz",
223 "reserved",
224 "reserved",
225 "50 MHz", /* New since Ibex Peak */
226 "reserved",
227 "reserved",
228 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100229 }, {
Nico Huber129e9382019-06-06 15:43:27 +0200230 "reserved",
231 "reserved",
232 "48 MHz",
233 "reserved",
234 "30 MHz",
235 "reserved",
236 "17 MHz",
237 "reserved"
Nico Huberd2d39932019-01-18 16:49:37 +0100238 }, {
239 "reserved",
240 "50 MHz",
241 "40 MHz",
242 "reserved",
243 "25 MHz",
244 "reserved",
245 "14 MHz / 17 MHz",
246 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100247 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000248
249 switch (cs) {
250 case CHIPSET_ICH8:
251 case CHIPSET_ICH9:
252 case CHIPSET_ICH10:
253 if (value > 1)
254 return "reserved";
Richard Hughesdb7482b2018-12-19 12:04:30 +0000255 /* Fall through. */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000256 case CHIPSET_5_SERIES_IBEX_PEAK:
257 case CHIPSET_6_SERIES_COUGAR_POINT:
258 case CHIPSET_7_SERIES_PANTHER_POINT:
259 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000260 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000261 case CHIPSET_8_SERIES_LYNX_POINT_LP:
262 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000263 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100264 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100265 return freq_str[0][value];
266 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700267 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberfa622942017-03-24 17:25:37 +0100268 return freq_str[1][value];
Nico Huberd2d39932019-01-18 16:49:37 +0100269 case CHIPSET_APOLLO_LAKE:
270 return freq_str[2][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000271 case CHIPSET_ICH_UNKNOWN:
272 default:
273 return "unknown";
274 }
275}
276
277void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
278{
Nico Huberd2d39932019-01-18 16:49:37 +0100279 bool has_flill1;
280
281 switch (cs) {
282 case CHIPSET_100_SERIES_SUNRISE_POINT:
283 case CHIPSET_C620_SERIES_LEWISBURG:
284 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 Huberfa622942017-03-24 17:25:37 +0100368 size_t i;
369 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++)
377 msg_pdbg2("FLREG%zu 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++)
Stefan Tauner1e146392011-09-15 23:52:55 +0000382 pprint_freg(&desc->region, i);
383 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 Huberfa622942017-03-24 17:25:37 +0100388 size_t i;
389 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++)
397 msg_pdbg2("FLMSTR%zu 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 Huberfa622942017-03-24 17:25:37 +0100401 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
402 const char *const master_names[] = {
403 "BIOS", "ME", "GbE", "unknown", "EC",
404 };
405 if (nm >= ARRAY_SIZE(master_names)) {
406 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
407 desc->content.NM + 1);
408 return;
409 }
410
411 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9\n");
412 for (i = 0; i < nm; i++) {
413 size_t j;
414 msg_pdbg2("%-4s", master_names[i]);
415 for (j = 0; j < 10; j++)
416 msg_pdbg2(" %c%c ",
417 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
418 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
419 msg_pdbg2("\n");
420 }
David Hendricksa5216362017-08-08 20:02:22 -0700421 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
422 const char *const master_names[] = {
423 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
424 };
425 /* NM starts at 1 instead of 0 for LBG */
426 if (nm > ARRAY_SIZE(master_names)) {
427 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
428 desc->content.NM);
429 return;
430 }
431
432 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
433 " ", /* width of master name (4 chars minimum) */
434 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
435 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
436 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
437 "Reg15");
438 for (i = 0; i < nm; i++) {
439 size_t j;
440 msg_pdbg2("%-4s", master_names[i]);
441 for (j = 0; j < 16; j++)
442 msg_pdbg2(" %c%c ",
443 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
444 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
445 msg_pdbg2("\n");
446 }
Nico Huberd2d39932019-01-18 16:49:37 +0100447 } else if (cs == CHIPSET_APOLLO_LAKE) {
448 const char *const master_names[] = { "BIOS", "TXE", };
449 if (nm > ARRAY_SIZE(master_names)) {
450 msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM);
451 return;
452 }
453
454 msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n");
455 for (i = 0; i < nm; i++) {
456 size_t j;
457 msg_pdbg2("%-4s", master_names[i]);
458 for (j = 0; j < ich_number_of_regions(cs, &desc->content); j++)
459 msg_pdbg2(" %c%c ",
460 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
461 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
462 msg_pdbg2("\n");
463 }
Nico Huberfa622942017-03-24 17:25:37 +0100464 } else {
465 const struct ich_desc_master *const mstr = &desc->master;
466 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
467 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
468 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
469 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
470 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
471 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
472 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
473 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
474 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
475 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
476 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
477 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
478 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
479 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
480 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
481 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
482 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
483 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
484 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
485 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000486 msg_pdbg2("\n");
487}
488
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600489static void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000490{
491 static const char * const str_GPIO12[4] = {
492 "GPIO12",
493 "LAN PHY Power Control Function (Native Output)",
494 "GLAN_DOCK# (Native Input)",
495 "invalid configuration",
496 };
497
498 msg_pdbg2("--- MCH details ---\n");
499 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
500 msg_pdbg2("\n");
501
502 msg_pdbg2("--- ICH details ---\n");
503 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
504 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
505 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
506 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
507 msg_pdbg2("SPI CS1 is used for %s.\n",
508 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
509 "LAN PHY Power Control Function" :
510 "SPI Chip Select");
511 msg_pdbg2("GPIO12 is used as %s.\n",
512 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
513 msg_pdbg2("PCIe Port 6 is used for %s.\n",
514 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
515 msg_pdbg2("%sn BMC Mode: "
516 "Intel AMT SMBus Controller 1 is connected to %s.\n",
517 desc->south.ich8.BMCMODE ? "I" : "Not i",
518 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
519 msg_pdbg2("TCO is in %s Mode.\n",
520 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
521 msg_pdbg2("ME A is %sabled.\n",
522 desc->south.ich8.ME_DISABLE ? "dis" : "en");
523 msg_pdbg2("\n");
524}
525
526static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
527{
528 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
529
530 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000531 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000532 case 0:
533 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
534 break;
535 case 1:
536 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
537 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
538 break;
539 case 2:
540 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
541 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
542 break;
543 case 3:
544 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
545 1+off, 2+off, 4+off);
546 break;
547 }
548 msg_pdbg2("\n");
549}
550
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600551static void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000552{
553 /* PCHSTRP4 */
554 msg_pdbg2("Intel PHY is %s.\n",
555 (s->ibex.PHYCON == 2) ? "connected" :
556 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
557 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
558 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
559 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
560 s->ibex.GBEMAC_SMBUS_ADDR);
561 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
562 s->ibex.GBEPHY_SMBUS_ADDR);
563
564 /* PCHSTRP5 */
565 /* PCHSTRP6 */
566 /* PCHSTRP7 */
567 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
568 s->ibex.MESMA2UDID_VENDOR);
569 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
570 s->ibex.MESMA2UDID_VENDOR);
571
572 /* PCHSTRP8 */
573}
574
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600575static void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000576{
577 /* PCHSTRP11 */
578 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
579 s->ibex.SML1GPAEN ? "en" : "dis");
580 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
581 s->ibex.SML1GPA);
582 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
583 s->ibex.SML1I2CAEN ? "en" : "dis");
584 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
585 s->ibex.SML1I2CA);
586
587 /* PCHSTRP12 */
588 /* PCHSTRP13 */
589}
590
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600591static void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000592{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000593 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000594 100,
595 50,
596 5,
597 1
598 };
599
600 msg_pdbg2("--- PCH ---\n");
601
602 /* PCHSTRP0 */
603 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
604 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
605 s->ibex.SMB_EN ? "en" : "dis");
606 msg_pdbg2("SMLink0 segment is %sabled.\n",
607 s->ibex.SML0_EN ? "en" : "dis");
608 msg_pdbg2("SMLink1 segment is %sabled.\n",
609 s->ibex.SML1_EN ? "en" : "dis");
610 msg_pdbg2("SMLink1 Frequency: %s\n",
611 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
612 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
613 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
614 msg_pdbg2("SMLink0 Frequency: %s\n",
615 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
616 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
617 "LAN_PHY_PWR_CTRL" : "general purpose output");
618 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
619 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
620 s->ibex.DMI_REQID_DIS ? "en" : "dis");
621 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
622 1 << (6 + s->ibex.BBBS));
623
624 /* PCHSTRP1 */
625 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
626
627 /* PCHSTRP2 */
628 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
629 s->ibex.MESMASDEN ? "en" : "dis");
630 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
631 s->ibex.MESMASDA);
632 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
633 s->ibex.MESMI2CEN ? "en" : "dis");
634 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
635 s->ibex.MESMI2CA);
636
637 /* PCHSTRP3 */
638 prettyprint_ich_descriptor_pchstraps45678_56(s);
639 /* PCHSTRP9 */
640 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
641 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
642 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
643 s->ibex.PCIELR1 ? "" : "not ");
644 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
645 s->ibex.PCIELR2 ? "" : "not ");
646 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
647 s->ibex.DMILR ? "" : "not ");
648 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
649 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
650 s->ibex.PHY_PCIE_EN ? "en" : "dis");
651
652 /* PCHSTRP10 */
653 msg_pdbg2("Management Engine will boot from %sflash.\n",
654 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
655 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
656 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
657 s->ibex.VE_EN ? "en" : "dis");
658 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
659 s->ibex.MMDDE ? "en" : "dis");
660 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
661 s->ibex.MMADDR);
662 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
663 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
664 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
665 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
666 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
667
668 prettyprint_ich_descriptor_pchstraps111213_56(s);
669
670 /* PCHSTRP14 */
671 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
672 s->ibex.VE_EN2 ? "en" : "dis");
673 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
674 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
675 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
676 s->ibex.BW_SSD ? "en" : "dis");
677 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
678 s->ibex.NVMHCI_EN ? "en" : "dis");
679
680 /* PCHSTRP15 */
681 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
682 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
683 s->ibex.IWL_EN ? "en" : "dis");
684 msg_pdbg2("t209 min Timing: %d ms\n",
685 dec_t209min[s->ibex.t209min]);
686 msg_pdbg2("\n");
687}
688
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600689static void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
Stefan Taunerb3850962011-12-24 00:00:32 +0000690{
691 msg_pdbg2("--- PCH ---\n");
692
693 /* PCHSTRP0 */
694 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
695 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
696 s->ibex.SMB_EN ? "en" : "dis");
697 msg_pdbg2("SMLink0 segment is %sabled.\n",
698 s->ibex.SML0_EN ? "en" : "dis");
699 msg_pdbg2("SMLink1 segment is %sabled.\n",
700 s->ibex.SML1_EN ? "en" : "dis");
701 msg_pdbg2("SMLink1 Frequency: %s\n",
702 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
703 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
704 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
705 msg_pdbg2("SMLink0 Frequency: %s\n",
706 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
707 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
708 "LAN_PHY_PWR_CTRL" : "general purpose output");
709 msg_pdbg2("LinkSec is %sabled.\n",
710 s->cougar.LINKSEC_DIS ? "en" : "dis");
711 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
712 s->ibex.DMI_REQID_DIS ? "en" : "dis");
713 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
714 1 << (6 + s->ibex.BBBS));
715
716 /* PCHSTRP1 */
717 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
718 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
719
720 /* PCHSTRP2 */
721 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
722 s->ibex.MESMASDEN ? "en" : "dis");
723 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
724 s->ibex.MESMASDA);
725 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
726 s->cougar.MESMMCTPAEN ? "en" : "dis");
727 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
728 s->cougar.MESMMCTPA);
729 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
730 s->ibex.MESMI2CEN ? "en" : "dis");
731 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
732 s->ibex.MESMI2CA);
733
734 /* PCHSTRP3 */
735 prettyprint_ich_descriptor_pchstraps45678_56(s);
736 /* PCHSTRP9 */
737 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
738 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
739 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
740 s->ibex.PCIELR1 ? "" : "not ");
741 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
742 s->ibex.PCIELR2 ? "" : "not ");
743 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
744 s->ibex.DMILR ? "" : "not ");
745 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
746 s->cougar.MDSMBE_EN ? "en" : "dis");
747 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
748 s->cougar.MDSMBE_ADD);
749 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
750 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
751 s->ibex.PHY_PCIE_EN ? "en" : "dis");
752 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
753 s->cougar.SUB_DECODE_EN ? "en" : "dis");
754 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
755 "PCHHOT#" : "SML1ALERT#");
756
757 /* PCHSTRP10 */
758 msg_pdbg2("Management Engine will boot from %sflash.\n",
759 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
760
761 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
762 s->cougar.MDSMBE_EN ? "en" : "dis");
763 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
764 s->cougar.MDSMBE_ADD);
765
766 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
767 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000768 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
769 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000770 msg_pdbg2("ICC Profile is selected by %s.\n",
771 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
772 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
773 s->cougar.Deep_SX_EN ? "not " : "");
774 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
775 s->cougar.ME_DBG_LAN ? "en" : "dis");
776
777 prettyprint_ich_descriptor_pchstraps111213_56(s);
778
779 /* PCHSTRP14 */
780 /* PCHSTRP15 */
781 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
782 msg_pdbg2("Integrated wired LAN is %sabled.\n",
783 s->cougar.IWL_EN ? "en" : "dis");
784 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
785 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000786 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000787 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
788 "general purpose output" : "SLP_LAN#");
789
790 /* PCHSTRP16 */
791 /* PCHSTRP17 */
792 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
793 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
794 msg_pdbg2("\n");
795}
796
797void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
798{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000799 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000800 msg_pdbg2("=== Softstraps ===\n");
801
Nico Huberd7c75522017-03-29 16:31:49 +0200802 max_count = min(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
803 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000804 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200805 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000806 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200807 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000808
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000809 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
810 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000811 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
812 msg_pdbg2("\n");
813
Nico Huberd7c75522017-03-29 16:31:49 +0200814 max_count = min(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
815 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000816 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
817 desc->content.ISL, max_count);
818 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200819 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000820
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000821 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
822 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000823 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
824 msg_pdbg2("\n");
825
826 switch (cs) {
827 case CHIPSET_ICH8:
828 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
829 msg_pdbg2("Detailed North/MCH/PROC information is "
830 "probably not reliable, printing anyway.\n");
831 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
832 msg_pdbg2("Detailed South/ICH/PCH information is "
833 "probably not reliable, printing anyway.\n");
834 prettyprint_ich_descriptor_straps_ich8(desc);
835 break;
836 case CHIPSET_5_SERIES_IBEX_PEAK:
837 /* PCH straps only. PROCSTRPs are unknown. */
838 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
839 msg_pdbg2("Detailed South/ICH/PCH information is "
840 "probably not reliable, printing anyway.\n");
841 prettyprint_ich_descriptor_straps_ibex(&desc->south);
842 break;
843 case CHIPSET_6_SERIES_COUGAR_POINT:
844 /* PCH straps only. PROCSTRP0 is "reserved". */
845 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
846 msg_pdbg2("Detailed South/ICH/PCH information is "
847 "probably not reliable, printing anyway.\n");
848 prettyprint_ich_descriptor_straps_cougar(&desc->south);
849 break;
850 case CHIPSET_ICH_UNKNOWN:
851 break;
852 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000853 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000854 break;
855 }
856}
857
Jacob Garberbeeb8bc2019-06-21 15:24:17 -0600858static void prettyprint_rdid(uint32_t reg_val)
Stefan Taunerb3850962011-12-24 00:00:32 +0000859{
860 uint8_t mid = reg_val & 0xFF;
861 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
862 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
863}
864
865void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
866{
867 int i;
868 msg_pdbg2("=== Upper Map Section ===\n");
869 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
870 msg_pdbg2("\n");
871
872 msg_pdbg2("--- Details ---\n");
873 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
874 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
875 msg_pdbg2("\n");
876
877 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000878 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000879 uint32_t jid = umap->vscc_table[i].JID;
880 uint32_t vscc = umap->vscc_table[i].VSCC;
881 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
882 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
883 msg_pdbg2(" "); /* indention */
884 prettyprint_rdid(jid);
885 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000886 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000887 }
888 msg_pdbg2("\n");
889}
890
Nico Huber1dc3d422017-06-17 00:09:31 +0200891/*
892 * Guesses a minimum chipset version based on the maximum number of
893 * soft straps per generation.
894 */
895static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
896{
897 if (content->ICCRIBA == 0x00) {
898 if (content->MSL == 0 && content->ISL <= 2)
899 return CHIPSET_ICH8;
900 else if (content->ISL <= 2)
901 return CHIPSET_ICH9;
902 else if (content->ISL <= 10)
903 return CHIPSET_ICH10;
904 else if (content->ISL <= 16)
905 return CHIPSET_5_SERIES_IBEX_PEAK;
Nico Huberd2d39932019-01-18 16:49:37 +0100906 else if (content->FLMAP2 == 0) {
907 if (content->ISL != 19)
908 msg_pwarn("Peculiar firmware descriptor, assuming Apollo Lake compatibility.\n");
909 return CHIPSET_APOLLO_LAKE;
910 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200911 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
912 return CHIPSET_5_SERIES_IBEX_PEAK;
913 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
914 if (content->MSL == 0 && content->ISL <= 17)
915 return CHIPSET_BAYTRAIL;
916 else if (content->MSL <= 1 && content->ISL <= 18)
917 return CHIPSET_6_SERIES_COUGAR_POINT;
918 else if (content->MSL <= 1 && content->ISL <= 21)
919 return CHIPSET_8_SERIES_LYNX_POINT;
920 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
921 return CHIPSET_9_SERIES_WILDCAT_POINT;
David Hendricksa5216362017-08-08 20:02:22 -0700922 } else if (content->NM == 6) {
923 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber1dc3d422017-06-17 00:09:31 +0200924 } else {
925 return CHIPSET_100_SERIES_SUNRISE_POINT;
926 }
927}
928
929/*
930 * As an additional measure, we check the read frequency like `ifdtool`.
931 * The frequency value 6 (17MHz) was reserved before Skylake and is the
932 * only valid value since. Skylake is currently the most important dis-
933 * tinction because of the dropped number of regions field (NR).
934 */
Nico Huberfa622942017-03-24 17:25:37 +0100935static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
936 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200937{
938 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
939
Nico Huberd2d39932019-01-18 16:49:37 +0100940 switch (guess) {
941 case CHIPSET_100_SERIES_SUNRISE_POINT:
942 case CHIPSET_C620_SERIES_LEWISBURG:
943 case CHIPSET_APOLLO_LAKE:
944 if (component->modes.freq_read != 6) {
945 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
946 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
947 "Please report this message, the output of `ich_descriptors_tool` for\n"
948 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
949 return CHIPSET_9_SERIES_WILDCAT_POINT;
950 }
951 return guess;
952 default:
953 if (component->modes.freq_read == 6) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200954 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
955 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
956 "Please report this message, the output of `ich_descriptors_tool` for\n"
957 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -0700958 return CHIPSET_100_SERIES_SUNRISE_POINT;
959 }
960 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +0200961 }
Nico Huber1dc3d422017-06-17 00:09:31 +0200962}
963
Stefan Taunerb3850962011-12-24 00:00:32 +0000964/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +0100965int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
966 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000967{
Nico Huberfa622942017-03-24 17:25:37 +0100968 size_t i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000969 uint8_t pch_bug_offset = 0;
970
971 if (dump == NULL || desc == NULL)
972 return ICH_RET_PARAM;
973
974 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
975 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
976 pch_bug_offset = 4;
977 else
978 return ICH_RET_ERR;
979 }
980
981 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +0200982 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000983 return ICH_RET_OOB;
984 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
985 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
986 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
987 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
988
989 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +0200990 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000991 return ICH_RET_OOB;
992 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
993 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
994 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
995
Nico Huber67d71792017-06-17 03:10:15 +0200996 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +0100997 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +0200998 prettyprint_ich_chipset(*cs);
999 }
Nico Huberfa622942017-03-24 17:25:37 +01001000
Stefan Taunerb3850962011-12-24 00:00:32 +00001001 /* region */
Nico Huberfa622942017-03-24 17:25:37 +01001002 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
1003 if (nr < 0 || len < getFRBA(&desc->content) + nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001004 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001005 for (i = 0; i < nr; i++)
1006 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001007
1008 /* master */
Nico Huberfa622942017-03-24 17:25:37 +01001009 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
1010 if (nm < 0 || len < getFMBA(&desc->content) + nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +00001011 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +01001012 for (i = 0; i < nm; i++)
1013 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001014
1015 /* upper map */
1016 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
1017
1018 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
1019 * "Identifies the 1s based number of DWORDS contained in the VSCC
1020 * Table. Each SPI component entry in the table is 2 DWORDS long." So
1021 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
1022 * check ensures that the maximum offset actually accessed is available.
1023 */
Nico Huber9e14aed2017-03-28 17:08:46 +02001024 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +00001025 return ICH_RET_OOB;
1026
1027 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001028 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
1029 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +00001030 }
1031
1032 /* MCH/PROC (aka. North) straps */
1033 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
1034 return ICH_RET_OOB;
1035
1036 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001037 max_count = min(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
1038 for (i = 0; i < max_count; i++)
1039 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001040
1041 /* ICH/PCH (aka. South) straps */
1042 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
1043 return ICH_RET_OOB;
1044
1045 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001046 max_count = min(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
1047 for (i = 0; i < max_count; i++)
1048 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001049
1050 return ICH_RET_OK;
1051}
1052
Nico Huberad186312016-05-02 15:15:29 +02001053#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001054
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001055/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001056\em idx in bytes or -1 if the correct size can not be determined. */
1057int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001058{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001059 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001060 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001061 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001062 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001063
1064 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001065 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001066
1067 uint8_t size_enc;
1068 uint8_t size_max;
1069
1070 switch (cs) {
1071 case CHIPSET_ICH8:
1072 case CHIPSET_ICH9:
1073 case CHIPSET_ICH10:
1074 case CHIPSET_5_SERIES_IBEX_PEAK:
1075 case CHIPSET_6_SERIES_COUGAR_POINT:
1076 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001077 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001078 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001079 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001080 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001081 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001082 }
1083 size_max = 5;
1084 break;
1085 case CHIPSET_8_SERIES_LYNX_POINT:
1086 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1087 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001088 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001089 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001090 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001091 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberd2d39932019-01-18 16:49:37 +01001092 case CHIPSET_APOLLO_LAKE:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001093 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001094 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001095 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001096 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001097 }
1098 size_max = 7;
1099 break;
1100 case CHIPSET_ICH_UNKNOWN:
1101 default:
1102 msg_pwarn("Density encoding is unknown on this chipset.\n");
1103 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001104 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001105
1106 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001107 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001108 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1109 idx, size_enc, size_max);
1110 return -1;
1111 }
1112
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001113 return (1 << (19 + size_enc));
1114}
1115
Nico Huber8d494992017-06-19 12:18:33 +02001116/* Only used by ichspi.c */
1117#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001118static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001119{
1120 uint32_t control = 0;
1121 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1122 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd2d39932019-01-18 16:49:37 +01001123 switch (cs) {
1124 case CHIPSET_100_SERIES_SUNRISE_POINT:
1125 case CHIPSET_C620_SERIES_LEWISBURG:
1126 case CHIPSET_APOLLO_LAKE:
Nico Huberd54e4f42017-03-23 23:45:47 +01001127 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1128 return mmio_le_readl(spibar + PCH100_REG_FDOD);
Nico Huberd2d39932019-01-18 16:49:37 +01001129 default:
Nico Huberd54e4f42017-03-23 23:45:47 +01001130 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1131 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1132 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001133}
1134
Nico Huberd54e4f42017-03-23 23:45:47 +01001135int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001136{
Nico Huberfa622942017-03-24 17:25:37 +01001137 size_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001138 struct ich_desc_region *r = &desc->region;
1139
1140 /* Test if bit-fields are working as expected.
1141 * FIXME: Replace this with dynamic bitfield fixup
1142 */
1143 for (i = 0; i < 4; i++)
1144 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001145 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1146 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1147 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1148 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001149 msg_pdbg("The combination of compiler and CPU architecture used"
1150 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001151 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1152 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1153 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1154 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1155 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1156 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1157 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1158 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001159 return ICH_RET_ERR;
1160 }
1161
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001162 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001163 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001164 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1165 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1166 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1167 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001168
1169 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001170 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1171 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1172 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001173
1174 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001175 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1176 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001177 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001178 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001179 return ICH_RET_ERR;
1180 }
Nico Huberfa622942017-03-24 17:25:37 +01001181 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001182 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001183
1184 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001185 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1186 if (nm < 0) {
1187 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1188 __func__, desc->content.NM + 1);
1189 return ICH_RET_ERR;
1190 }
1191 for (i = 0; i < nm; i++)
1192 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001193
1194 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1195 * reading the upper map is impossible on all chipsets, so don't bother.
1196 */
1197
1198 msg_pdbg2(" done.\n");
1199 return ICH_RET_OK;
1200}
Nico Huber8d494992017-06-19 12:18:33 +02001201#endif
Nico Huber305f4172013-06-14 11:55:26 +02001202
1203/**
1204 * @brief Read a layout from the dump of an Intel ICH descriptor.
1205 *
1206 * @param layout Pointer where to store the layout.
1207 * @param dump The descriptor dump to read from.
1208 * @param len The length of the descriptor dump.
1209 *
1210 * @return 0 on success,
Nico Huber70461a92019-06-15 14:56:19 +02001211 * 1 if the descriptor couldn't be parsed,
1212 * 2 when out of memory.
Nico Huber305f4172013-06-14 11:55:26 +02001213 */
1214int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1215{
Nico Huberfa622942017-03-24 17:25:37 +01001216 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001217 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1218 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001219 };
Nico Huber305f4172013-06-14 11:55:26 +02001220
1221 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001222 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1223 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001224 return 1;
1225
1226 memset(layout, 0x00, sizeof(*layout));
1227
Nico Huberfa622942017-03-24 17:25:37 +01001228 ssize_t i, j;
1229 for (i = 0, j = 0; i < min(ich_number_of_regions(cs, &desc.content), ARRAY_SIZE(regions)); ++i) {
Nico Huber305f4172013-06-14 11:55:26 +02001230 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001231 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001232 if (limit <= base)
1233 continue;
1234 layout->entries[j].start = base;
1235 layout->entries[j].end = limit;
1236 layout->entries[j].included = false;
Nico Huber70461a92019-06-15 14:56:19 +02001237 layout->entries[j].name = strdup(regions[i]);
1238 if (!layout->entries[j].name)
1239 return 2;
Nico Huber305f4172013-06-14 11:55:26 +02001240 ++j;
1241 }
1242 layout->base.entries = layout->entries;
1243 layout->base.num_entries = j;
1244 return 0;
1245}
1246
Nico Huberad186312016-05-02 15:15:29 +02001247#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */