blob: 251f6369f5f84eb98ca646ed67bee76b08e76823 [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) {
David Hendricksa5216362017-08-08 20:02:22 -070045 case CHIPSET_C620_SERIES_LEWISBURG:
46 return 16;
Nico Huberfa622942017-03-24 17:25:37 +010047 case CHIPSET_100_SERIES_SUNRISE_POINT:
48 return 10;
49 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
50 case CHIPSET_9_SERIES_WILDCAT_POINT:
51 case CHIPSET_8_SERIES_LYNX_POINT_LP:
52 case CHIPSET_8_SERIES_LYNX_POINT:
53 case CHIPSET_8_SERIES_WELLSBURG:
54 if (cont->NR <= 6)
55 return cont->NR + 1;
56 else
57 return -1;
58 default:
59 if (cont->NR <= 4)
60 return cont->NR + 1;
61 else
62 return -1;
63 }
64}
65
66ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
67{
David Hendricksa5216362017-08-08 20:02:22 -070068 switch (cs) {
69 case CHIPSET_C620_SERIES_LEWISBURG:
70 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",
David Hendricksa5216362017-08-08 20:02:22 -0700106 "C620 series Lewisburg",
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));
143 msg_pdbg2("ISL (ICH/PCH Strap Length): %5d\n", cont->ISL);
144 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH Strap Base Address): 0x%03x\n", getFISBA(cont));
145 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:
197 case CHIPSET_C620_SERIES_LEWISBURG: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000198 uint8_t size_enc;
199 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000200 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000201 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000202 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000203 }
204 if (size_enc > 7)
205 return "reserved";
206 return size_str[size_enc];
207 }
208 case CHIPSET_ICH_UNKNOWN:
209 default:
210 return "unknown";
211 }
212}
213
214static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000215{
Nico Huberfa622942017-03-24 17:25:37 +0100216 static const char *const freq_str[2][8] = { {
Nico Huber129e9382019-06-06 15:43:27 +0200217 "20 MHz",
218 "33 MHz",
219 "reserved",
220 "reserved",
221 "50 MHz", /* New since Ibex Peak */
222 "reserved",
223 "reserved",
224 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100225 }, {
Nico Huber129e9382019-06-06 15:43:27 +0200226 "reserved",
227 "reserved",
228 "48 MHz",
229 "reserved",
230 "30 MHz",
231 "reserved",
232 "17 MHz",
233 "reserved"
Nico Huberfa622942017-03-24 17:25:37 +0100234 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000235
236 switch (cs) {
237 case CHIPSET_ICH8:
238 case CHIPSET_ICH9:
239 case CHIPSET_ICH10:
240 if (value > 1)
241 return "reserved";
Richard Hughesdb7482b2018-12-19 12:04:30 +0000242 /* Fall through. */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000243 case CHIPSET_5_SERIES_IBEX_PEAK:
244 case CHIPSET_6_SERIES_COUGAR_POINT:
245 case CHIPSET_7_SERIES_PANTHER_POINT:
246 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000247 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000248 case CHIPSET_8_SERIES_LYNX_POINT_LP:
249 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000250 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100251 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100252 return freq_str[0][value];
253 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700254 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberfa622942017-03-24 17:25:37 +0100255 return freq_str[1][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000256 case CHIPSET_ICH_UNKNOWN:
257 default:
258 return "unknown";
259 }
260}
261
262void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
263{
Stefan Tauner1e146392011-09-15 23:52:55 +0000264
265 msg_pdbg2("=== Component Section ===\n");
266 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
267 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
David Hendricksa5216362017-08-08 20:02:22 -0700268 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG)
Nico Huberfa622942017-03-24 17:25:37 +0100269 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000270 msg_pdbg2("\n");
271
272 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000273 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000274 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000275 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000276 else
277 msg_pdbg2("Component 2 is not used.\n");
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000278 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
279 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
280 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
281 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
282 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000283 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000284 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000285 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
286 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000287 desc->component.modes.dual_output ? "dis" : "en");
David Hendricksa5216362017-08-08 20:02:22 -0700288
289 int has_forbidden_opcode = 0;
290 if (desc->component.FLILL != 0) {
291 has_forbidden_opcode = 1;
Stefan Tauner1e146392011-09-15 23:52:55 +0000292 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
293 desc->component.invalid_instr0);
294 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
295 desc->component.invalid_instr1);
296 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
297 desc->component.invalid_instr2);
298 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
299 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700300 }
301 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG) {
302 if (desc->component.FLILL1 != 0) {
303 has_forbidden_opcode = 1;
Nico Huberfa622942017-03-24 17:25:37 +0100304 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
305 desc->component.invalid_instr4);
306 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
307 desc->component.invalid_instr5);
308 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
309 desc->component.invalid_instr6);
310 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
311 desc->component.invalid_instr7);
312 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000313 }
David Hendricksa5216362017-08-08 20:02:22 -0700314 if (!has_forbidden_opcode)
315 msg_pdbg2("No forbidden opcodes.\n");
316
Stefan Tauner1e146392011-09-15 23:52:55 +0000317 msg_pdbg2("\n");
318}
319
320static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
321{
Nico Huberfa622942017-03-24 17:25:37 +0100322 static const char *const region_names[] = {
David Hendricksa5216362017-08-08 20:02:22 -0700323 "Descr.", "BIOS", "ME", "GbE", "Platf.", "unknown", "BIOS2", "unknown",
324 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000325 };
Nico Huberfa622942017-03-24 17:25:37 +0100326 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000327 msg_pdbg2("%s: region index too high.\n", __func__);
328 return;
329 }
330 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
331 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100332 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000333 if (base > limit)
334 msg_pdbg2("is unused.\n");
335 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200336 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000337}
338
Nico Huberfa622942017-03-24 17:25:37 +0100339void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000340{
Nico Huberfa622942017-03-24 17:25:37 +0100341 size_t i;
342 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000343 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100344 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000345 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100346 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000347 return;
348 }
Nico Huberfa622942017-03-24 17:25:37 +0100349 for (i = 0; i < nr; i++)
350 msg_pdbg2("FLREG%zu 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000351 msg_pdbg2("\n");
352
353 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100354 for (i = 0; i < nr; i++)
Stefan Tauner1e146392011-09-15 23:52:55 +0000355 pprint_freg(&desc->region, i);
356 msg_pdbg2("\n");
357}
358
Nico Huberfa622942017-03-24 17:25:37 +0100359void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000360{
Nico Huberfa622942017-03-24 17:25:37 +0100361 size_t i;
362 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000363 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100364 if (nm < 0) {
365 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
366 desc->content.NM + 1);
367 return;
368 }
369 for (i = 0; i < nm; i++)
370 msg_pdbg2("FLMSTR%zu 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000371 msg_pdbg2("\n");
372
373 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100374 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
375 const char *const master_names[] = {
376 "BIOS", "ME", "GbE", "unknown", "EC",
377 };
378 if (nm >= ARRAY_SIZE(master_names)) {
379 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
380 desc->content.NM + 1);
381 return;
382 }
383
384 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9\n");
385 for (i = 0; i < nm; i++) {
386 size_t j;
387 msg_pdbg2("%-4s", master_names[i]);
388 for (j = 0; j < 10; j++)
389 msg_pdbg2(" %c%c ",
390 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
391 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
392 msg_pdbg2("\n");
393 }
David Hendricksa5216362017-08-08 20:02:22 -0700394 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
395 const char *const master_names[] = {
396 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
397 };
398 /* NM starts at 1 instead of 0 for LBG */
399 if (nm > ARRAY_SIZE(master_names)) {
400 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
401 desc->content.NM);
402 return;
403 }
404
405 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
406 " ", /* width of master name (4 chars minimum) */
407 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
408 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
409 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
410 "Reg15");
411 for (i = 0; i < nm; i++) {
412 size_t j;
413 msg_pdbg2("%-4s", master_names[i]);
414 for (j = 0; j < 16; j++)
415 msg_pdbg2(" %c%c ",
416 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
417 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
418 msg_pdbg2("\n");
419 }
Nico Huberfa622942017-03-24 17:25:37 +0100420 } else {
421 const struct ich_desc_master *const mstr = &desc->master;
422 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
423 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
424 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
425 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
426 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
427 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
428 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
429 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
430 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
431 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
432 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
433 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
434 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
435 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
436 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
437 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
438 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
439 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
440 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
441 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000442 msg_pdbg2("\n");
443}
444
Stefan Taunerb3850962011-12-24 00:00:32 +0000445void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
446{
447 static const char * const str_GPIO12[4] = {
448 "GPIO12",
449 "LAN PHY Power Control Function (Native Output)",
450 "GLAN_DOCK# (Native Input)",
451 "invalid configuration",
452 };
453
454 msg_pdbg2("--- MCH details ---\n");
455 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
456 msg_pdbg2("\n");
457
458 msg_pdbg2("--- ICH details ---\n");
459 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
460 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
461 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
462 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
463 msg_pdbg2("SPI CS1 is used for %s.\n",
464 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
465 "LAN PHY Power Control Function" :
466 "SPI Chip Select");
467 msg_pdbg2("GPIO12 is used as %s.\n",
468 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
469 msg_pdbg2("PCIe Port 6 is used for %s.\n",
470 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
471 msg_pdbg2("%sn BMC Mode: "
472 "Intel AMT SMBus Controller 1 is connected to %s.\n",
473 desc->south.ich8.BMCMODE ? "I" : "Not i",
474 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
475 msg_pdbg2("TCO is in %s Mode.\n",
476 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
477 msg_pdbg2("ME A is %sabled.\n",
478 desc->south.ich8.ME_DISABLE ? "dis" : "en");
479 msg_pdbg2("\n");
480}
481
482static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
483{
484 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
485
486 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000487 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000488 case 0:
489 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
490 break;
491 case 1:
492 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
493 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
494 break;
495 case 2:
496 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
497 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
498 break;
499 case 3:
500 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
501 1+off, 2+off, 4+off);
502 break;
503 }
504 msg_pdbg2("\n");
505}
506
507void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
508{
509 /* PCHSTRP4 */
510 msg_pdbg2("Intel PHY is %s.\n",
511 (s->ibex.PHYCON == 2) ? "connected" :
512 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
513 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
514 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
515 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
516 s->ibex.GBEMAC_SMBUS_ADDR);
517 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
518 s->ibex.GBEPHY_SMBUS_ADDR);
519
520 /* PCHSTRP5 */
521 /* PCHSTRP6 */
522 /* PCHSTRP7 */
523 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
524 s->ibex.MESMA2UDID_VENDOR);
525 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
526 s->ibex.MESMA2UDID_VENDOR);
527
528 /* PCHSTRP8 */
529}
530
531void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
532{
533 /* PCHSTRP11 */
534 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
535 s->ibex.SML1GPAEN ? "en" : "dis");
536 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
537 s->ibex.SML1GPA);
538 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
539 s->ibex.SML1I2CAEN ? "en" : "dis");
540 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
541 s->ibex.SML1I2CA);
542
543 /* PCHSTRP12 */
544 /* PCHSTRP13 */
545}
546
547void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
548{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000549 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000550 100,
551 50,
552 5,
553 1
554 };
555
556 msg_pdbg2("--- PCH ---\n");
557
558 /* PCHSTRP0 */
559 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
560 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
561 s->ibex.SMB_EN ? "en" : "dis");
562 msg_pdbg2("SMLink0 segment is %sabled.\n",
563 s->ibex.SML0_EN ? "en" : "dis");
564 msg_pdbg2("SMLink1 segment is %sabled.\n",
565 s->ibex.SML1_EN ? "en" : "dis");
566 msg_pdbg2("SMLink1 Frequency: %s\n",
567 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
568 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
569 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
570 msg_pdbg2("SMLink0 Frequency: %s\n",
571 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
572 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
573 "LAN_PHY_PWR_CTRL" : "general purpose output");
574 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
575 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
576 s->ibex.DMI_REQID_DIS ? "en" : "dis");
577 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
578 1 << (6 + s->ibex.BBBS));
579
580 /* PCHSTRP1 */
581 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
582
583 /* PCHSTRP2 */
584 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
585 s->ibex.MESMASDEN ? "en" : "dis");
586 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
587 s->ibex.MESMASDA);
588 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
589 s->ibex.MESMI2CEN ? "en" : "dis");
590 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
591 s->ibex.MESMI2CA);
592
593 /* PCHSTRP3 */
594 prettyprint_ich_descriptor_pchstraps45678_56(s);
595 /* PCHSTRP9 */
596 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
597 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
598 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
599 s->ibex.PCIELR1 ? "" : "not ");
600 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
601 s->ibex.PCIELR2 ? "" : "not ");
602 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
603 s->ibex.DMILR ? "" : "not ");
604 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
605 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
606 s->ibex.PHY_PCIE_EN ? "en" : "dis");
607
608 /* PCHSTRP10 */
609 msg_pdbg2("Management Engine will boot from %sflash.\n",
610 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
611 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
612 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
613 s->ibex.VE_EN ? "en" : "dis");
614 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
615 s->ibex.MMDDE ? "en" : "dis");
616 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
617 s->ibex.MMADDR);
618 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
619 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
620 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
621 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
622 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
623
624 prettyprint_ich_descriptor_pchstraps111213_56(s);
625
626 /* PCHSTRP14 */
627 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
628 s->ibex.VE_EN2 ? "en" : "dis");
629 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
630 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
631 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
632 s->ibex.BW_SSD ? "en" : "dis");
633 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
634 s->ibex.NVMHCI_EN ? "en" : "dis");
635
636 /* PCHSTRP15 */
637 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
638 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
639 s->ibex.IWL_EN ? "en" : "dis");
640 msg_pdbg2("t209 min Timing: %d ms\n",
641 dec_t209min[s->ibex.t209min]);
642 msg_pdbg2("\n");
643}
644
645void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
646{
647 msg_pdbg2("--- PCH ---\n");
648
649 /* PCHSTRP0 */
650 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
651 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
652 s->ibex.SMB_EN ? "en" : "dis");
653 msg_pdbg2("SMLink0 segment is %sabled.\n",
654 s->ibex.SML0_EN ? "en" : "dis");
655 msg_pdbg2("SMLink1 segment is %sabled.\n",
656 s->ibex.SML1_EN ? "en" : "dis");
657 msg_pdbg2("SMLink1 Frequency: %s\n",
658 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
659 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
660 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
661 msg_pdbg2("SMLink0 Frequency: %s\n",
662 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
663 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
664 "LAN_PHY_PWR_CTRL" : "general purpose output");
665 msg_pdbg2("LinkSec is %sabled.\n",
666 s->cougar.LINKSEC_DIS ? "en" : "dis");
667 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
668 s->ibex.DMI_REQID_DIS ? "en" : "dis");
669 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
670 1 << (6 + s->ibex.BBBS));
671
672 /* PCHSTRP1 */
673 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
674 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
675
676 /* PCHSTRP2 */
677 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
678 s->ibex.MESMASDEN ? "en" : "dis");
679 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
680 s->ibex.MESMASDA);
681 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
682 s->cougar.MESMMCTPAEN ? "en" : "dis");
683 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
684 s->cougar.MESMMCTPA);
685 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
686 s->ibex.MESMI2CEN ? "en" : "dis");
687 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
688 s->ibex.MESMI2CA);
689
690 /* PCHSTRP3 */
691 prettyprint_ich_descriptor_pchstraps45678_56(s);
692 /* PCHSTRP9 */
693 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
694 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
695 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
696 s->ibex.PCIELR1 ? "" : "not ");
697 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
698 s->ibex.PCIELR2 ? "" : "not ");
699 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
700 s->ibex.DMILR ? "" : "not ");
701 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
702 s->cougar.MDSMBE_EN ? "en" : "dis");
703 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
704 s->cougar.MDSMBE_ADD);
705 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
706 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
707 s->ibex.PHY_PCIE_EN ? "en" : "dis");
708 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
709 s->cougar.SUB_DECODE_EN ? "en" : "dis");
710 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
711 "PCHHOT#" : "SML1ALERT#");
712
713 /* PCHSTRP10 */
714 msg_pdbg2("Management Engine will boot from %sflash.\n",
715 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
716
717 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
718 s->cougar.MDSMBE_EN ? "en" : "dis");
719 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
720 s->cougar.MDSMBE_ADD);
721
722 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
723 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000724 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
725 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000726 msg_pdbg2("ICC Profile is selected by %s.\n",
727 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
728 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
729 s->cougar.Deep_SX_EN ? "not " : "");
730 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
731 s->cougar.ME_DBG_LAN ? "en" : "dis");
732
733 prettyprint_ich_descriptor_pchstraps111213_56(s);
734
735 /* PCHSTRP14 */
736 /* PCHSTRP15 */
737 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
738 msg_pdbg2("Integrated wired LAN is %sabled.\n",
739 s->cougar.IWL_EN ? "en" : "dis");
740 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
741 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000742 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000743 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
744 "general purpose output" : "SLP_LAN#");
745
746 /* PCHSTRP16 */
747 /* PCHSTRP17 */
748 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
749 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
750 msg_pdbg2("\n");
751}
752
753void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
754{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000755 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000756 msg_pdbg2("=== Softstraps ===\n");
757
Nico Huberd7c75522017-03-29 16:31:49 +0200758 max_count = min(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
759 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000760 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200761 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000762 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200763 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000764
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000765 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
766 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000767 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
768 msg_pdbg2("\n");
769
Nico Huberd7c75522017-03-29 16:31:49 +0200770 max_count = min(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
771 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000772 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
773 desc->content.ISL, max_count);
774 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200775 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000776
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000777 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
778 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000779 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
780 msg_pdbg2("\n");
781
782 switch (cs) {
783 case CHIPSET_ICH8:
784 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
785 msg_pdbg2("Detailed North/MCH/PROC information is "
786 "probably not reliable, printing anyway.\n");
787 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
788 msg_pdbg2("Detailed South/ICH/PCH information is "
789 "probably not reliable, printing anyway.\n");
790 prettyprint_ich_descriptor_straps_ich8(desc);
791 break;
792 case CHIPSET_5_SERIES_IBEX_PEAK:
793 /* PCH straps only. PROCSTRPs are unknown. */
794 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
795 msg_pdbg2("Detailed South/ICH/PCH information is "
796 "probably not reliable, printing anyway.\n");
797 prettyprint_ich_descriptor_straps_ibex(&desc->south);
798 break;
799 case CHIPSET_6_SERIES_COUGAR_POINT:
800 /* PCH straps only. PROCSTRP0 is "reserved". */
801 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
802 msg_pdbg2("Detailed South/ICH/PCH information is "
803 "probably not reliable, printing anyway.\n");
804 prettyprint_ich_descriptor_straps_cougar(&desc->south);
805 break;
806 case CHIPSET_ICH_UNKNOWN:
807 break;
808 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000809 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000810 break;
811 }
812}
813
814void prettyprint_rdid(uint32_t reg_val)
815{
816 uint8_t mid = reg_val & 0xFF;
817 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
818 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
819}
820
821void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
822{
823 int i;
824 msg_pdbg2("=== Upper Map Section ===\n");
825 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
826 msg_pdbg2("\n");
827
828 msg_pdbg2("--- Details ---\n");
829 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
830 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
831 msg_pdbg2("\n");
832
833 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000834 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000835 uint32_t jid = umap->vscc_table[i].JID;
836 uint32_t vscc = umap->vscc_table[i].VSCC;
837 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
838 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
839 msg_pdbg2(" "); /* indention */
840 prettyprint_rdid(jid);
841 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000842 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000843 }
844 msg_pdbg2("\n");
845}
846
Nico Huber1dc3d422017-06-17 00:09:31 +0200847/*
848 * Guesses a minimum chipset version based on the maximum number of
849 * soft straps per generation.
850 */
851static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
852{
853 if (content->ICCRIBA == 0x00) {
854 if (content->MSL == 0 && content->ISL <= 2)
855 return CHIPSET_ICH8;
856 else if (content->ISL <= 2)
857 return CHIPSET_ICH9;
858 else if (content->ISL <= 10)
859 return CHIPSET_ICH10;
860 else if (content->ISL <= 16)
861 return CHIPSET_5_SERIES_IBEX_PEAK;
862 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
863 return CHIPSET_5_SERIES_IBEX_PEAK;
864 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
865 if (content->MSL == 0 && content->ISL <= 17)
866 return CHIPSET_BAYTRAIL;
867 else if (content->MSL <= 1 && content->ISL <= 18)
868 return CHIPSET_6_SERIES_COUGAR_POINT;
869 else if (content->MSL <= 1 && content->ISL <= 21)
870 return CHIPSET_8_SERIES_LYNX_POINT;
871 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
872 return CHIPSET_9_SERIES_WILDCAT_POINT;
David Hendricksa5216362017-08-08 20:02:22 -0700873 } else if (content->NM == 6) {
874 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber1dc3d422017-06-17 00:09:31 +0200875 } else {
876 return CHIPSET_100_SERIES_SUNRISE_POINT;
877 }
878}
879
880/*
881 * As an additional measure, we check the read frequency like `ifdtool`.
882 * The frequency value 6 (17MHz) was reserved before Skylake and is the
883 * only valid value since. Skylake is currently the most important dis-
884 * tinction because of the dropped number of regions field (NR).
885 */
Nico Huberfa622942017-03-24 17:25:37 +0100886static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
887 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200888{
889 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
890
891 if (component->modes.freq_read == 6) {
David Hendricksa5216362017-08-08 20:02:22 -0700892 if ((guess != CHIPSET_100_SERIES_SUNRISE_POINT) && (guess != CHIPSET_C620_SERIES_LEWISBURG)) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200893 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
894 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
895 "Please report this message, the output of `ich_descriptors_tool` for\n"
896 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -0700897 return CHIPSET_100_SERIES_SUNRISE_POINT;
898 }
899 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +0200900 } else {
David Hendricksa5216362017-08-08 20:02:22 -0700901 if (guess == CHIPSET_100_SERIES_SUNRISE_POINT || guess == CHIPSET_C620_SERIES_LEWISBURG) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200902 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
903 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
904 "Please report this message, the output of `ich_descriptors_tool` for\n"
905 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
906 return CHIPSET_9_SERIES_WILDCAT_POINT;
907 }
908 }
909
910 return guess;
911}
912
Stefan Taunerb3850962011-12-24 00:00:32 +0000913/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +0100914int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
915 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000916{
Nico Huberfa622942017-03-24 17:25:37 +0100917 size_t i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000918 uint8_t pch_bug_offset = 0;
919
920 if (dump == NULL || desc == NULL)
921 return ICH_RET_PARAM;
922
923 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
924 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
925 pch_bug_offset = 4;
926 else
927 return ICH_RET_ERR;
928 }
929
930 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +0200931 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000932 return ICH_RET_OOB;
933 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
934 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
935 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
936 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
937
938 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +0200939 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000940 return ICH_RET_OOB;
941 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
942 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
943 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
944
Nico Huber67d71792017-06-17 03:10:15 +0200945 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +0100946 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +0200947 prettyprint_ich_chipset(*cs);
948 }
Nico Huberfa622942017-03-24 17:25:37 +0100949
Stefan Taunerb3850962011-12-24 00:00:32 +0000950 /* region */
Nico Huberfa622942017-03-24 17:25:37 +0100951 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
952 if (nr < 0 || len < getFRBA(&desc->content) + nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000953 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +0100954 for (i = 0; i < nr; i++)
955 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000956
957 /* master */
Nico Huberfa622942017-03-24 17:25:37 +0100958 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
959 if (nm < 0 || len < getFMBA(&desc->content) + nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000960 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +0100961 for (i = 0; i < nm; i++)
962 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000963
964 /* upper map */
965 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
966
967 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
968 * "Identifies the 1s based number of DWORDS contained in the VSCC
969 * Table. Each SPI component entry in the table is 2 DWORDS long." So
970 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
971 * check ensures that the maximum offset actually accessed is available.
972 */
Nico Huber9e14aed2017-03-28 17:08:46 +0200973 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +0000974 return ICH_RET_OOB;
975
976 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000977 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
978 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +0000979 }
980
981 /* MCH/PROC (aka. North) straps */
982 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
983 return ICH_RET_OOB;
984
985 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000986 max_count = min(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
987 for (i = 0; i < max_count; i++)
988 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000989
990 /* ICH/PCH (aka. South) straps */
991 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
992 return ICH_RET_OOB;
993
994 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000995 max_count = min(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
996 for (i = 0; i < max_count; i++)
997 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000998
999 return ICH_RET_OK;
1000}
1001
Nico Huberad186312016-05-02 15:15:29 +02001002#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001003
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001004/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001005\em idx in bytes or -1 if the correct size can not be determined. */
1006int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001007{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001008 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001009 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001010 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001011 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001012
1013 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001014 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001015
1016 uint8_t size_enc;
1017 uint8_t size_max;
1018
1019 switch (cs) {
1020 case CHIPSET_ICH8:
1021 case CHIPSET_ICH9:
1022 case CHIPSET_ICH10:
1023 case CHIPSET_5_SERIES_IBEX_PEAK:
1024 case CHIPSET_6_SERIES_COUGAR_POINT:
1025 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001026 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001027 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001028 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001029 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001030 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001031 }
1032 size_max = 5;
1033 break;
1034 case CHIPSET_8_SERIES_LYNX_POINT:
1035 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1036 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001037 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001038 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001039 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001040 case CHIPSET_C620_SERIES_LEWISBURG:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001041 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001042 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001043 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001044 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001045 }
1046 size_max = 7;
1047 break;
1048 case CHIPSET_ICH_UNKNOWN:
1049 default:
1050 msg_pwarn("Density encoding is unknown on this chipset.\n");
1051 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001052 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001053
1054 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001055 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001056 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1057 idx, size_enc, size_max);
1058 return -1;
1059 }
1060
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001061 return (1 << (19 + size_enc));
1062}
1063
Nico Huber8d494992017-06-19 12:18:33 +02001064/* Only used by ichspi.c */
1065#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001066static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001067{
1068 uint32_t control = 0;
1069 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1070 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
David Hendricksa5216362017-08-08 20:02:22 -07001071 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG) {
Nico Huberd54e4f42017-03-23 23:45:47 +01001072 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1073 return mmio_le_readl(spibar + PCH100_REG_FDOD);
1074 } else {
1075 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1076 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1077 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001078}
1079
Nico Huberd54e4f42017-03-23 23:45:47 +01001080int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001081{
Nico Huberfa622942017-03-24 17:25:37 +01001082 size_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001083 struct ich_desc_region *r = &desc->region;
1084
1085 /* Test if bit-fields are working as expected.
1086 * FIXME: Replace this with dynamic bitfield fixup
1087 */
1088 for (i = 0; i < 4; i++)
1089 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001090 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1091 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1092 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1093 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001094 msg_pdbg("The combination of compiler and CPU architecture used"
1095 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001096 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1097 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1098 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1099 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1100 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1101 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1102 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1103 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001104 return ICH_RET_ERR;
1105 }
1106
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001107 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001108 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001109 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1110 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1111 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1112 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001113
1114 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001115 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1116 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1117 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001118
1119 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001120 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1121 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001122 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001123 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001124 return ICH_RET_ERR;
1125 }
Nico Huberfa622942017-03-24 17:25:37 +01001126 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001127 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001128
1129 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001130 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1131 if (nm < 0) {
1132 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1133 __func__, desc->content.NM + 1);
1134 return ICH_RET_ERR;
1135 }
1136 for (i = 0; i < nm; i++)
1137 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001138
1139 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1140 * reading the upper map is impossible on all chipsets, so don't bother.
1141 */
1142
1143 msg_pdbg2(" done.\n");
1144 return ICH_RET_OK;
1145}
Nico Huber8d494992017-06-19 12:18:33 +02001146#endif
Nico Huber305f4172013-06-14 11:55:26 +02001147
1148/**
1149 * @brief Read a layout from the dump of an Intel ICH descriptor.
1150 *
1151 * @param layout Pointer where to store the layout.
1152 * @param dump The descriptor dump to read from.
1153 * @param len The length of the descriptor dump.
1154 *
1155 * @return 0 on success,
1156 * 1 if the descriptor couldn't be parsed.
1157 */
1158int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1159{
Nico Huberfa622942017-03-24 17:25:37 +01001160 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001161 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1162 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001163 };
Nico Huber305f4172013-06-14 11:55:26 +02001164
1165 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001166 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1167 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001168 return 1;
1169
1170 memset(layout, 0x00, sizeof(*layout));
1171
Nico Huberfa622942017-03-24 17:25:37 +01001172 ssize_t i, j;
1173 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 +02001174 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001175 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001176 if (limit <= base)
1177 continue;
1178 layout->entries[j].start = base;
1179 layout->entries[j].end = limit;
1180 layout->entries[j].included = false;
1181 snprintf(layout->entries[j].name, sizeof(layout->entries[j].name), "%s", regions[i]);
1182 ++j;
1183 }
1184 layout->base.entries = layout->entries;
1185 layout->base.num_entries = j;
1186 return 0;
1187}
1188
Nico Huberad186312016-05-02 15:15:29 +02001189#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */