blob: 56e846f00b88e60da95c6bd204d3033829a529f0 [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;
72 default:
73 if (cont->NM < MAX_NUM_MASTERS)
74 return cont->NM + 1;
75 }
76
77 return -1;
Nico Huberfa622942017-03-24 17:25:37 +010078}
79
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000080void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000081{
82 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
83 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
84 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
85 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000086 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
87 if (print_vcl)
88 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
89 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000090}
91
92#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
93#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
94#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
95#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
96#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
97
Nico Huber67d71792017-06-17 03:10:15 +020098void prettyprint_ich_chipset(enum ich_chipset cs)
99{
100 static const char *const chipset_names[] = {
101 "Unknown ICH", "ICH8", "ICH9", "ICH10",
102 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
103 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
104 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
David Hendricksa5216362017-08-08 20:02:22 -0700105 "C620 series Lewisburg",
Nico Huber67d71792017-06-17 03:10:15 +0200106 };
107 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
108 cs = 0;
109 else
110 cs = cs - CHIPSET_ICH8 + 1;
111 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
112}
113
Stefan Tauner1e146392011-09-15 23:52:55 +0000114void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
115{
Nico Huberfa622942017-03-24 17:25:37 +0100116 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000117 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100118 prettyprint_ich_descriptor_region(cs, desc);
119 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200120#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000121 if (cs >= CHIPSET_ICH8) {
122 prettyprint_ich_descriptor_upper_map(&desc->upper);
123 prettyprint_ich_descriptor_straps(cs, desc);
124 }
Nico Huberad186312016-05-02 15:15:29 +0200125#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000126}
127
Nico Huberfa622942017-03-24 17:25:37 +0100128void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000129{
130 msg_pdbg2("=== Content Section ===\n");
131 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
132 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
133 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
134 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
135 msg_pdbg2("\n");
136
137 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100138 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
139 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
140 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
141 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
142 msg_pdbg2("ISL (ICH/PCH Strap Length): %5d\n", cont->ISL);
143 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH Strap Base Address): 0x%03x\n", getFISBA(cont));
144 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
145 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
146 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
147 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000148 msg_pdbg2("\n");
149}
150
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000151static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
152{
153 if (idx > 1) {
154 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
155 return NULL;
156 }
157
158 if (desc->content.NC == 0 && idx > 0)
159 return "unused";
160
161 static const char * const size_str[] = {
162 "512 kB", /* 0000 */
163 "1 MB", /* 0001 */
164 "2 MB", /* 0010 */
165 "4 MB", /* 0011 */
166 "8 MB", /* 0100 */
167 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
168 "32 MB", /* 0110 */
169 "64 MB", /* 0111 */
170 };
171
172 switch (cs) {
173 case CHIPSET_ICH8:
174 case CHIPSET_ICH9:
175 case CHIPSET_ICH10:
176 case CHIPSET_5_SERIES_IBEX_PEAK:
177 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000178 case CHIPSET_7_SERIES_PANTHER_POINT:
179 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000180 uint8_t size_enc;
181 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000182 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000183 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000184 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000185 }
186 if (size_enc > 5)
187 return "reserved";
188 return size_str[size_enc];
189 }
190 case CHIPSET_8_SERIES_LYNX_POINT:
191 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000192 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100193 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100194 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
David Hendricksa5216362017-08-08 20:02:22 -0700195 case CHIPSET_100_SERIES_SUNRISE_POINT:
196 case CHIPSET_C620_SERIES_LEWISBURG: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000197 uint8_t size_enc;
198 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000199 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000200 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000201 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000202 }
203 if (size_enc > 7)
204 return "reserved";
205 return size_str[size_enc];
206 }
207 case CHIPSET_ICH_UNKNOWN:
208 default:
209 return "unknown";
210 }
211}
212
213static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000214{
Nico Huberfa622942017-03-24 17:25:37 +0100215 static const char *const freq_str[2][8] = { {
Stefan Tauner1e146392011-09-15 23:52:55 +0000216 "20 MHz", /* 000 */
217 "33 MHz", /* 001 */
218 "reserved", /* 010 */
219 "reserved", /* 011 */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000220 "50 MHz", /* 100 */ /* New since Ibex Peak */
Stefan Tauner1e146392011-09-15 23:52:55 +0000221 "reserved", /* 101 */
222 "reserved", /* 110 */
223 "reserved" /* 111 */
Nico Huberfa622942017-03-24 17:25:37 +0100224 }, {
225 "reserved", /* 000 */
226 "reserved", /* 001 */
227 "48 MHz", /* 010 */
228 "reserved", /* 011 */
229 "30 MHz", /* 100 */
230 "reserved", /* 101 */
231 "17 MHz", /* 110 */
232 "reserved" /* 111 */
233 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000234
235 switch (cs) {
236 case CHIPSET_ICH8:
237 case CHIPSET_ICH9:
238 case CHIPSET_ICH10:
239 if (value > 1)
240 return "reserved";
241 case CHIPSET_5_SERIES_IBEX_PEAK:
242 case CHIPSET_6_SERIES_COUGAR_POINT:
243 case CHIPSET_7_SERIES_PANTHER_POINT:
244 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000245 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000246 case CHIPSET_8_SERIES_LYNX_POINT_LP:
247 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000248 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100249 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100250 return freq_str[0][value];
251 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700252 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberfa622942017-03-24 17:25:37 +0100253 return freq_str[1][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000254 case CHIPSET_ICH_UNKNOWN:
255 default:
256 return "unknown";
257 }
258}
259
260void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
261{
Stefan Tauner1e146392011-09-15 23:52:55 +0000262
263 msg_pdbg2("=== Component Section ===\n");
264 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
265 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
David Hendricksa5216362017-08-08 20:02:22 -0700266 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG)
Nico Huberfa622942017-03-24 17:25:37 +0100267 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000268 msg_pdbg2("\n");
269
270 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000271 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000272 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000273 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000274 else
275 msg_pdbg2("Component 2 is not used.\n");
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000276 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
277 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
278 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
279 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
280 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000281 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000282 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000283 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
284 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000285 desc->component.modes.dual_output ? "dis" : "en");
David Hendricksa5216362017-08-08 20:02:22 -0700286
287 int has_forbidden_opcode = 0;
288 if (desc->component.FLILL != 0) {
289 has_forbidden_opcode = 1;
Stefan Tauner1e146392011-09-15 23:52:55 +0000290 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
291 desc->component.invalid_instr0);
292 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
293 desc->component.invalid_instr1);
294 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
295 desc->component.invalid_instr2);
296 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
297 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700298 }
299 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG) {
300 if (desc->component.FLILL1 != 0) {
301 has_forbidden_opcode = 1;
Nico Huberfa622942017-03-24 17:25:37 +0100302 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
303 desc->component.invalid_instr4);
304 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
305 desc->component.invalid_instr5);
306 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
307 desc->component.invalid_instr6);
308 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
309 desc->component.invalid_instr7);
310 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000311 }
David Hendricksa5216362017-08-08 20:02:22 -0700312 if (!has_forbidden_opcode)
313 msg_pdbg2("No forbidden opcodes.\n");
314
Stefan Tauner1e146392011-09-15 23:52:55 +0000315 msg_pdbg2("\n");
316}
317
318static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
319{
Nico Huberfa622942017-03-24 17:25:37 +0100320 static const char *const region_names[] = {
David Hendricksa5216362017-08-08 20:02:22 -0700321 "Descr.", "BIOS", "ME", "GbE", "Platf.", "unknown", "BIOS2", "unknown",
322 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000323 };
Nico Huberfa622942017-03-24 17:25:37 +0100324 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000325 msg_pdbg2("%s: region index too high.\n", __func__);
326 return;
327 }
328 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
329 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100330 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000331 if (base > limit)
332 msg_pdbg2("is unused.\n");
333 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200334 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000335}
336
Nico Huberfa622942017-03-24 17:25:37 +0100337void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000338{
Nico Huberfa622942017-03-24 17:25:37 +0100339 size_t i;
340 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000341 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100342 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000343 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100344 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000345 return;
346 }
Nico Huberfa622942017-03-24 17:25:37 +0100347 for (i = 0; i < nr; i++)
348 msg_pdbg2("FLREG%zu 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000349 msg_pdbg2("\n");
350
351 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100352 for (i = 0; i < nr; i++)
Stefan Tauner1e146392011-09-15 23:52:55 +0000353 pprint_freg(&desc->region, i);
354 msg_pdbg2("\n");
355}
356
Nico Huberfa622942017-03-24 17:25:37 +0100357void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000358{
Nico Huberfa622942017-03-24 17:25:37 +0100359 size_t i;
360 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000361 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100362 if (nm < 0) {
363 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
364 desc->content.NM + 1);
365 return;
366 }
367 for (i = 0; i < nm; i++)
368 msg_pdbg2("FLMSTR%zu 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000369 msg_pdbg2("\n");
370
371 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100372 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
373 const char *const master_names[] = {
374 "BIOS", "ME", "GbE", "unknown", "EC",
375 };
376 if (nm >= ARRAY_SIZE(master_names)) {
377 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
378 desc->content.NM + 1);
379 return;
380 }
381
382 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9\n");
383 for (i = 0; i < nm; i++) {
384 size_t j;
385 msg_pdbg2("%-4s", master_names[i]);
386 for (j = 0; j < 10; j++)
387 msg_pdbg2(" %c%c ",
388 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
389 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
390 msg_pdbg2("\n");
391 }
David Hendricksa5216362017-08-08 20:02:22 -0700392 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
393 const char *const master_names[] = {
394 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
395 };
396 /* NM starts at 1 instead of 0 for LBG */
397 if (nm > ARRAY_SIZE(master_names)) {
398 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
399 desc->content.NM);
400 return;
401 }
402
403 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
404 " ", /* width of master name (4 chars minimum) */
405 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
406 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
407 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
408 "Reg15");
409 for (i = 0; i < nm; i++) {
410 size_t j;
411 msg_pdbg2("%-4s", master_names[i]);
412 for (j = 0; j < 16; j++)
413 msg_pdbg2(" %c%c ",
414 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
415 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
416 msg_pdbg2("\n");
417 }
Nico Huberfa622942017-03-24 17:25:37 +0100418 } else {
419 const struct ich_desc_master *const mstr = &desc->master;
420 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
421 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
422 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
423 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
424 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
425 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
426 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
427 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
428 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
429 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
430 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
431 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
432 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
433 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
434 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
435 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
436 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
437 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
438 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
439 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000440 msg_pdbg2("\n");
441}
442
Stefan Taunerb3850962011-12-24 00:00:32 +0000443void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
444{
445 static const char * const str_GPIO12[4] = {
446 "GPIO12",
447 "LAN PHY Power Control Function (Native Output)",
448 "GLAN_DOCK# (Native Input)",
449 "invalid configuration",
450 };
451
452 msg_pdbg2("--- MCH details ---\n");
453 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
454 msg_pdbg2("\n");
455
456 msg_pdbg2("--- ICH details ---\n");
457 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
458 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
459 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
460 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
461 msg_pdbg2("SPI CS1 is used for %s.\n",
462 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
463 "LAN PHY Power Control Function" :
464 "SPI Chip Select");
465 msg_pdbg2("GPIO12 is used as %s.\n",
466 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
467 msg_pdbg2("PCIe Port 6 is used for %s.\n",
468 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
469 msg_pdbg2("%sn BMC Mode: "
470 "Intel AMT SMBus Controller 1 is connected to %s.\n",
471 desc->south.ich8.BMCMODE ? "I" : "Not i",
472 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
473 msg_pdbg2("TCO is in %s Mode.\n",
474 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
475 msg_pdbg2("ME A is %sabled.\n",
476 desc->south.ich8.ME_DISABLE ? "dis" : "en");
477 msg_pdbg2("\n");
478}
479
480static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
481{
482 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
483
484 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000485 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000486 case 0:
487 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
488 break;
489 case 1:
490 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
491 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
492 break;
493 case 2:
494 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
495 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
496 break;
497 case 3:
498 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
499 1+off, 2+off, 4+off);
500 break;
501 }
502 msg_pdbg2("\n");
503}
504
505void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
506{
507 /* PCHSTRP4 */
508 msg_pdbg2("Intel PHY is %s.\n",
509 (s->ibex.PHYCON == 2) ? "connected" :
510 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
511 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
512 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
513 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
514 s->ibex.GBEMAC_SMBUS_ADDR);
515 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
516 s->ibex.GBEPHY_SMBUS_ADDR);
517
518 /* PCHSTRP5 */
519 /* PCHSTRP6 */
520 /* PCHSTRP7 */
521 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
522 s->ibex.MESMA2UDID_VENDOR);
523 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
524 s->ibex.MESMA2UDID_VENDOR);
525
526 /* PCHSTRP8 */
527}
528
529void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
530{
531 /* PCHSTRP11 */
532 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
533 s->ibex.SML1GPAEN ? "en" : "dis");
534 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
535 s->ibex.SML1GPA);
536 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
537 s->ibex.SML1I2CAEN ? "en" : "dis");
538 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
539 s->ibex.SML1I2CA);
540
541 /* PCHSTRP12 */
542 /* PCHSTRP13 */
543}
544
545void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
546{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000547 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000548 100,
549 50,
550 5,
551 1
552 };
553
554 msg_pdbg2("--- PCH ---\n");
555
556 /* PCHSTRP0 */
557 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
558 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
559 s->ibex.SMB_EN ? "en" : "dis");
560 msg_pdbg2("SMLink0 segment is %sabled.\n",
561 s->ibex.SML0_EN ? "en" : "dis");
562 msg_pdbg2("SMLink1 segment is %sabled.\n",
563 s->ibex.SML1_EN ? "en" : "dis");
564 msg_pdbg2("SMLink1 Frequency: %s\n",
565 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
566 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
567 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
568 msg_pdbg2("SMLink0 Frequency: %s\n",
569 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
570 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
571 "LAN_PHY_PWR_CTRL" : "general purpose output");
572 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
573 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
574 s->ibex.DMI_REQID_DIS ? "en" : "dis");
575 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
576 1 << (6 + s->ibex.BBBS));
577
578 /* PCHSTRP1 */
579 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
580
581 /* PCHSTRP2 */
582 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
583 s->ibex.MESMASDEN ? "en" : "dis");
584 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
585 s->ibex.MESMASDA);
586 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
587 s->ibex.MESMI2CEN ? "en" : "dis");
588 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
589 s->ibex.MESMI2CA);
590
591 /* PCHSTRP3 */
592 prettyprint_ich_descriptor_pchstraps45678_56(s);
593 /* PCHSTRP9 */
594 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
595 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
596 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
597 s->ibex.PCIELR1 ? "" : "not ");
598 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
599 s->ibex.PCIELR2 ? "" : "not ");
600 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
601 s->ibex.DMILR ? "" : "not ");
602 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
603 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
604 s->ibex.PHY_PCIE_EN ? "en" : "dis");
605
606 /* PCHSTRP10 */
607 msg_pdbg2("Management Engine will boot from %sflash.\n",
608 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
609 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
610 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
611 s->ibex.VE_EN ? "en" : "dis");
612 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
613 s->ibex.MMDDE ? "en" : "dis");
614 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
615 s->ibex.MMADDR);
616 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
617 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
618 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
619 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
620 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
621
622 prettyprint_ich_descriptor_pchstraps111213_56(s);
623
624 /* PCHSTRP14 */
625 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
626 s->ibex.VE_EN2 ? "en" : "dis");
627 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
628 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
629 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
630 s->ibex.BW_SSD ? "en" : "dis");
631 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
632 s->ibex.NVMHCI_EN ? "en" : "dis");
633
634 /* PCHSTRP15 */
635 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
636 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
637 s->ibex.IWL_EN ? "en" : "dis");
638 msg_pdbg2("t209 min Timing: %d ms\n",
639 dec_t209min[s->ibex.t209min]);
640 msg_pdbg2("\n");
641}
642
643void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
644{
645 msg_pdbg2("--- PCH ---\n");
646
647 /* PCHSTRP0 */
648 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
649 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
650 s->ibex.SMB_EN ? "en" : "dis");
651 msg_pdbg2("SMLink0 segment is %sabled.\n",
652 s->ibex.SML0_EN ? "en" : "dis");
653 msg_pdbg2("SMLink1 segment is %sabled.\n",
654 s->ibex.SML1_EN ? "en" : "dis");
655 msg_pdbg2("SMLink1 Frequency: %s\n",
656 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
657 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
658 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
659 msg_pdbg2("SMLink0 Frequency: %s\n",
660 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
661 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
662 "LAN_PHY_PWR_CTRL" : "general purpose output");
663 msg_pdbg2("LinkSec is %sabled.\n",
664 s->cougar.LINKSEC_DIS ? "en" : "dis");
665 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
666 s->ibex.DMI_REQID_DIS ? "en" : "dis");
667 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
668 1 << (6 + s->ibex.BBBS));
669
670 /* PCHSTRP1 */
671 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
672 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
673
674 /* PCHSTRP2 */
675 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
676 s->ibex.MESMASDEN ? "en" : "dis");
677 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
678 s->ibex.MESMASDA);
679 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
680 s->cougar.MESMMCTPAEN ? "en" : "dis");
681 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
682 s->cougar.MESMMCTPA);
683 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
684 s->ibex.MESMI2CEN ? "en" : "dis");
685 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
686 s->ibex.MESMI2CA);
687
688 /* PCHSTRP3 */
689 prettyprint_ich_descriptor_pchstraps45678_56(s);
690 /* PCHSTRP9 */
691 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
692 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
693 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
694 s->ibex.PCIELR1 ? "" : "not ");
695 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
696 s->ibex.PCIELR2 ? "" : "not ");
697 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
698 s->ibex.DMILR ? "" : "not ");
699 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
700 s->cougar.MDSMBE_EN ? "en" : "dis");
701 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
702 s->cougar.MDSMBE_ADD);
703 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
704 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
705 s->ibex.PHY_PCIE_EN ? "en" : "dis");
706 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
707 s->cougar.SUB_DECODE_EN ? "en" : "dis");
708 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
709 "PCHHOT#" : "SML1ALERT#");
710
711 /* PCHSTRP10 */
712 msg_pdbg2("Management Engine will boot from %sflash.\n",
713 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
714
715 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
716 s->cougar.MDSMBE_EN ? "en" : "dis");
717 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
718 s->cougar.MDSMBE_ADD);
719
720 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
721 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000722 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
723 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000724 msg_pdbg2("ICC Profile is selected by %s.\n",
725 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
726 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
727 s->cougar.Deep_SX_EN ? "not " : "");
728 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
729 s->cougar.ME_DBG_LAN ? "en" : "dis");
730
731 prettyprint_ich_descriptor_pchstraps111213_56(s);
732
733 /* PCHSTRP14 */
734 /* PCHSTRP15 */
735 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
736 msg_pdbg2("Integrated wired LAN is %sabled.\n",
737 s->cougar.IWL_EN ? "en" : "dis");
738 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
739 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000740 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000741 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
742 "general purpose output" : "SLP_LAN#");
743
744 /* PCHSTRP16 */
745 /* PCHSTRP17 */
746 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
747 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
748 msg_pdbg2("\n");
749}
750
751void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
752{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000753 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000754 msg_pdbg2("=== Softstraps ===\n");
755
Nico Huberd7c75522017-03-29 16:31:49 +0200756 max_count = min(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
757 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000758 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200759 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000760 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200761 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000762
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000763 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
764 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000765 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
766 msg_pdbg2("\n");
767
Nico Huberd7c75522017-03-29 16:31:49 +0200768 max_count = min(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
769 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000770 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
771 desc->content.ISL, max_count);
772 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200773 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000774
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000775 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
776 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000777 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
778 msg_pdbg2("\n");
779
780 switch (cs) {
781 case CHIPSET_ICH8:
782 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
783 msg_pdbg2("Detailed North/MCH/PROC information is "
784 "probably not reliable, printing anyway.\n");
785 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
786 msg_pdbg2("Detailed South/ICH/PCH information is "
787 "probably not reliable, printing anyway.\n");
788 prettyprint_ich_descriptor_straps_ich8(desc);
789 break;
790 case CHIPSET_5_SERIES_IBEX_PEAK:
791 /* PCH straps only. PROCSTRPs are unknown. */
792 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
793 msg_pdbg2("Detailed South/ICH/PCH information is "
794 "probably not reliable, printing anyway.\n");
795 prettyprint_ich_descriptor_straps_ibex(&desc->south);
796 break;
797 case CHIPSET_6_SERIES_COUGAR_POINT:
798 /* PCH straps only. PROCSTRP0 is "reserved". */
799 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
800 msg_pdbg2("Detailed South/ICH/PCH information is "
801 "probably not reliable, printing anyway.\n");
802 prettyprint_ich_descriptor_straps_cougar(&desc->south);
803 break;
804 case CHIPSET_ICH_UNKNOWN:
805 break;
806 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000807 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000808 break;
809 }
810}
811
812void prettyprint_rdid(uint32_t reg_val)
813{
814 uint8_t mid = reg_val & 0xFF;
815 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
816 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
817}
818
819void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
820{
821 int i;
822 msg_pdbg2("=== Upper Map Section ===\n");
823 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
824 msg_pdbg2("\n");
825
826 msg_pdbg2("--- Details ---\n");
827 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
828 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
829 msg_pdbg2("\n");
830
831 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000832 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000833 uint32_t jid = umap->vscc_table[i].JID;
834 uint32_t vscc = umap->vscc_table[i].VSCC;
835 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
836 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
837 msg_pdbg2(" "); /* indention */
838 prettyprint_rdid(jid);
839 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000840 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000841 }
842 msg_pdbg2("\n");
843}
844
Nico Huber1dc3d422017-06-17 00:09:31 +0200845/*
846 * Guesses a minimum chipset version based on the maximum number of
847 * soft straps per generation.
848 */
849static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
850{
851 if (content->ICCRIBA == 0x00) {
852 if (content->MSL == 0 && content->ISL <= 2)
853 return CHIPSET_ICH8;
854 else if (content->ISL <= 2)
855 return CHIPSET_ICH9;
856 else if (content->ISL <= 10)
857 return CHIPSET_ICH10;
858 else if (content->ISL <= 16)
859 return CHIPSET_5_SERIES_IBEX_PEAK;
860 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
861 return CHIPSET_5_SERIES_IBEX_PEAK;
862 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
863 if (content->MSL == 0 && content->ISL <= 17)
864 return CHIPSET_BAYTRAIL;
865 else if (content->MSL <= 1 && content->ISL <= 18)
866 return CHIPSET_6_SERIES_COUGAR_POINT;
867 else if (content->MSL <= 1 && content->ISL <= 21)
868 return CHIPSET_8_SERIES_LYNX_POINT;
869 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
870 return CHIPSET_9_SERIES_WILDCAT_POINT;
David Hendricksa5216362017-08-08 20:02:22 -0700871 } else if (content->NM == 6) {
872 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber1dc3d422017-06-17 00:09:31 +0200873 } else {
874 return CHIPSET_100_SERIES_SUNRISE_POINT;
875 }
876}
877
878/*
879 * As an additional measure, we check the read frequency like `ifdtool`.
880 * The frequency value 6 (17MHz) was reserved before Skylake and is the
881 * only valid value since. Skylake is currently the most important dis-
882 * tinction because of the dropped number of regions field (NR).
883 */
Nico Huberfa622942017-03-24 17:25:37 +0100884static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
885 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200886{
887 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
888
889 if (component->modes.freq_read == 6) {
David Hendricksa5216362017-08-08 20:02:22 -0700890 if ((guess != CHIPSET_100_SERIES_SUNRISE_POINT) && (guess != CHIPSET_C620_SERIES_LEWISBURG)) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200891 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
892 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
893 "Please report this message, the output of `ich_descriptors_tool` for\n"
894 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -0700895 return CHIPSET_100_SERIES_SUNRISE_POINT;
896 }
897 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +0200898 } else {
David Hendricksa5216362017-08-08 20:02:22 -0700899 if (guess == CHIPSET_100_SERIES_SUNRISE_POINT || guess == CHIPSET_C620_SERIES_LEWISBURG) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200900 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
901 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
902 "Please report this message, the output of `ich_descriptors_tool` for\n"
903 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
904 return CHIPSET_9_SERIES_WILDCAT_POINT;
905 }
906 }
907
908 return guess;
909}
910
Stefan Taunerb3850962011-12-24 00:00:32 +0000911/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +0100912int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
913 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000914{
Nico Huberfa622942017-03-24 17:25:37 +0100915 size_t i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000916 uint8_t pch_bug_offset = 0;
917
918 if (dump == NULL || desc == NULL)
919 return ICH_RET_PARAM;
920
921 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
922 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
923 pch_bug_offset = 4;
924 else
925 return ICH_RET_ERR;
926 }
927
928 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +0200929 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000930 return ICH_RET_OOB;
931 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
932 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
933 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
934 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
935
936 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +0200937 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000938 return ICH_RET_OOB;
939 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
940 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
941 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
942
Nico Huber67d71792017-06-17 03:10:15 +0200943 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +0100944 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +0200945 prettyprint_ich_chipset(*cs);
946 }
Nico Huberfa622942017-03-24 17:25:37 +0100947
Stefan Taunerb3850962011-12-24 00:00:32 +0000948 /* region */
Nico Huberfa622942017-03-24 17:25:37 +0100949 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
950 if (nr < 0 || len < getFRBA(&desc->content) + nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000951 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +0100952 for (i = 0; i < nr; i++)
953 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000954
955 /* master */
Nico Huberfa622942017-03-24 17:25:37 +0100956 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
957 if (nm < 0 || len < getFMBA(&desc->content) + nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000958 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +0100959 for (i = 0; i < nm; i++)
960 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000961
962 /* upper map */
963 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
964
965 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
966 * "Identifies the 1s based number of DWORDS contained in the VSCC
967 * Table. Each SPI component entry in the table is 2 DWORDS long." So
968 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
969 * check ensures that the maximum offset actually accessed is available.
970 */
Nico Huber9e14aed2017-03-28 17:08:46 +0200971 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +0000972 return ICH_RET_OOB;
973
974 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000975 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
976 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +0000977 }
978
979 /* MCH/PROC (aka. North) straps */
980 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
981 return ICH_RET_OOB;
982
983 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000984 max_count = min(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
985 for (i = 0; i < max_count; i++)
986 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000987
988 /* ICH/PCH (aka. South) straps */
989 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
990 return ICH_RET_OOB;
991
992 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000993 max_count = min(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
994 for (i = 0; i < max_count; i++)
995 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000996
997 return ICH_RET_OK;
998}
999
Nico Huberad186312016-05-02 15:15:29 +02001000#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001001
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001002/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001003\em idx in bytes or -1 if the correct size can not be determined. */
1004int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001005{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001006 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001007 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001008 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001009 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001010
1011 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001012 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001013
1014 uint8_t size_enc;
1015 uint8_t size_max;
1016
1017 switch (cs) {
1018 case CHIPSET_ICH8:
1019 case CHIPSET_ICH9:
1020 case CHIPSET_ICH10:
1021 case CHIPSET_5_SERIES_IBEX_PEAK:
1022 case CHIPSET_6_SERIES_COUGAR_POINT:
1023 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001024 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001025 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001026 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001027 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001028 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001029 }
1030 size_max = 5;
1031 break;
1032 case CHIPSET_8_SERIES_LYNX_POINT:
1033 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1034 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001035 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001036 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001037 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001038 case CHIPSET_C620_SERIES_LEWISBURG:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001039 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001040 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001041 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001042 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001043 }
1044 size_max = 7;
1045 break;
1046 case CHIPSET_ICH_UNKNOWN:
1047 default:
1048 msg_pwarn("Density encoding is unknown on this chipset.\n");
1049 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001050 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001051
1052 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001053 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001054 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1055 idx, size_enc, size_max);
1056 return -1;
1057 }
1058
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001059 return (1 << (19 + size_enc));
1060}
1061
Nico Huber8d494992017-06-19 12:18:33 +02001062/* Only used by ichspi.c */
1063#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001064static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001065{
1066 uint32_t control = 0;
1067 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1068 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
David Hendricksa5216362017-08-08 20:02:22 -07001069 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG) {
Nico Huberd54e4f42017-03-23 23:45:47 +01001070 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1071 return mmio_le_readl(spibar + PCH100_REG_FDOD);
1072 } else {
1073 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1074 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1075 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001076}
1077
Nico Huberd54e4f42017-03-23 23:45:47 +01001078int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001079{
Nico Huberfa622942017-03-24 17:25:37 +01001080 size_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001081 struct ich_desc_region *r = &desc->region;
1082
1083 /* Test if bit-fields are working as expected.
1084 * FIXME: Replace this with dynamic bitfield fixup
1085 */
1086 for (i = 0; i < 4; i++)
1087 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001088 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1089 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1090 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1091 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001092 msg_pdbg("The combination of compiler and CPU architecture used"
1093 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001094 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1095 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1096 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1097 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1098 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1099 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1100 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1101 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001102 return ICH_RET_ERR;
1103 }
1104
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001105 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001106 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001107 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1108 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1109 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1110 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001111
1112 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001113 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1114 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1115 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001116
1117 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001118 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1119 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001120 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001121 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001122 return ICH_RET_ERR;
1123 }
Nico Huberfa622942017-03-24 17:25:37 +01001124 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001125 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001126
1127 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001128 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1129 if (nm < 0) {
1130 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1131 __func__, desc->content.NM + 1);
1132 return ICH_RET_ERR;
1133 }
1134 for (i = 0; i < nm; i++)
1135 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001136
1137 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1138 * reading the upper map is impossible on all chipsets, so don't bother.
1139 */
1140
1141 msg_pdbg2(" done.\n");
1142 return ICH_RET_OK;
1143}
Nico Huber8d494992017-06-19 12:18:33 +02001144#endif
Nico Huber305f4172013-06-14 11:55:26 +02001145
1146/**
1147 * @brief Read a layout from the dump of an Intel ICH descriptor.
1148 *
1149 * @param layout Pointer where to store the layout.
1150 * @param dump The descriptor dump to read from.
1151 * @param len The length of the descriptor dump.
1152 *
1153 * @return 0 on success,
1154 * 1 if the descriptor couldn't be parsed.
1155 */
1156int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1157{
Nico Huberfa622942017-03-24 17:25:37 +01001158 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001159 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1160 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001161 };
Nico Huber305f4172013-06-14 11:55:26 +02001162
1163 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001164 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1165 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001166 return 1;
1167
1168 memset(layout, 0x00, sizeof(*layout));
1169
Nico Huberfa622942017-03-24 17:25:37 +01001170 ssize_t i, j;
1171 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 +02001172 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001173 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001174 if (limit <= base)
1175 continue;
1176 layout->entries[j].start = base;
1177 layout->entries[j].end = limit;
1178 layout->entries[j].included = false;
1179 snprintf(layout->entries[j].name, sizeof(layout->entries[j].name), "%s", regions[i]);
1180 ++j;
1181 }
1182 layout->base.entries = layout->entries;
1183 layout->base.num_entries = j;
1184 return 0;
1185}
1186
Nico Huberad186312016-05-02 15:15:29 +02001187#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */