blob: 69fcd75d3ea846d6ec2f454b86e16962528da05b [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.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
Stefan Tauner1e146392011-09-15 23:52:55 +000022#include "ich_descriptors.h"
Stefan Taunerb3850962011-12-24 00:00:32 +000023
Nico Huberad186312016-05-02 15:15:29 +020024#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +000025#include <stdio.h>
Nico Huber305f4172013-06-14 11:55:26 +020026#include <string.h>
Stefan Taunerb3850962011-12-24 00:00:32 +000027#define print(t, ...) printf(__VA_ARGS__)
Nico Huberad186312016-05-02 15:15:29 +020028#endif
29
Stefan Taunerb3850962011-12-24 00:00:32 +000030#define DESCRIPTOR_MODE_SIGNATURE 0x0ff0a55a
31/* The upper map is located in the word before the 256B-long OEM section at the
32 * end of the 4kB-long flash descriptor.
33 */
34#define UPPER_MAP_OFFSET (4096 - 256 - 4)
35#define getVTBA(flumap) (((flumap)->FLUMAP1 << 4) & 0x00000ff0)
36
Nico Huber4d440a72017-08-15 11:26:48 +020037#include <sys/types.h>
Nico Huberad186312016-05-02 15:15:29 +020038#include <string.h>
Stefan Tauner1e146392011-09-15 23:52:55 +000039#include "flash.h" /* for msg_* */
40#include "programmer.h"
41
Stefan Taunerb3850962011-12-24 00:00:32 +000042#ifndef min
Nico Huber305f4172013-06-14 11:55:26 +020043#define min(a, b) (((a) < (b)) ? (a) : (b))
Stefan Taunerb3850962011-12-24 00:00:32 +000044#endif
45
Nico Huberfa622942017-03-24 17:25:37 +010046ssize_t ich_number_of_regions(const enum ich_chipset cs, const struct ich_desc_content *const cont)
47{
48 switch (cs) {
David Hendricksa5216362017-08-08 20:02:22 -070049 case CHIPSET_C620_SERIES_LEWISBURG:
50 return 16;
Nico Huberfa622942017-03-24 17:25:37 +010051 case CHIPSET_100_SERIES_SUNRISE_POINT:
52 return 10;
53 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
54 case CHIPSET_9_SERIES_WILDCAT_POINT:
55 case CHIPSET_8_SERIES_LYNX_POINT_LP:
56 case CHIPSET_8_SERIES_LYNX_POINT:
57 case CHIPSET_8_SERIES_WELLSBURG:
58 if (cont->NR <= 6)
59 return cont->NR + 1;
60 else
61 return -1;
62 default:
63 if (cont->NR <= 4)
64 return cont->NR + 1;
65 else
66 return -1;
67 }
68}
69
70ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
71{
David Hendricksa5216362017-08-08 20:02:22 -070072 switch (cs) {
73 case CHIPSET_C620_SERIES_LEWISBURG:
74 if (cont->NM <= MAX_NUM_MASTERS)
75 return cont->NM;
76 default:
77 if (cont->NM < MAX_NUM_MASTERS)
78 return cont->NM + 1;
79 }
80
81 return -1;
Nico Huberfa622942017-03-24 17:25:37 +010082}
83
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000084void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000085{
86 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
87 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
88 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
89 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000090 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
91 if (print_vcl)
92 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
93 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000094}
95
96#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
97#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
98#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
99#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
100#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
101
Nico Huber67d71792017-06-17 03:10:15 +0200102void prettyprint_ich_chipset(enum ich_chipset cs)
103{
104 static const char *const chipset_names[] = {
105 "Unknown ICH", "ICH8", "ICH9", "ICH10",
106 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
107 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
108 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
David Hendricksa5216362017-08-08 20:02:22 -0700109 "C620 series Lewisburg",
Nico Huber67d71792017-06-17 03:10:15 +0200110 };
111 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
112 cs = 0;
113 else
114 cs = cs - CHIPSET_ICH8 + 1;
115 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
116}
117
Stefan Tauner1e146392011-09-15 23:52:55 +0000118void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
119{
Nico Huberfa622942017-03-24 17:25:37 +0100120 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000121 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100122 prettyprint_ich_descriptor_region(cs, desc);
123 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200124#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000125 if (cs >= CHIPSET_ICH8) {
126 prettyprint_ich_descriptor_upper_map(&desc->upper);
127 prettyprint_ich_descriptor_straps(cs, desc);
128 }
Nico Huberad186312016-05-02 15:15:29 +0200129#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000130}
131
Nico Huberfa622942017-03-24 17:25:37 +0100132void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000133{
134 msg_pdbg2("=== Content Section ===\n");
135 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
136 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
137 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
138 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
139 msg_pdbg2("\n");
140
141 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100142 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
143 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
144 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
145 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
146 msg_pdbg2("ISL (ICH/PCH Strap Length): %5d\n", cont->ISL);
147 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH Strap Base Address): 0x%03x\n", getFISBA(cont));
148 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
149 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
150 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
151 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000152 msg_pdbg2("\n");
153}
154
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000155static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
156{
157 if (idx > 1) {
158 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
159 return NULL;
160 }
161
162 if (desc->content.NC == 0 && idx > 0)
163 return "unused";
164
165 static const char * const size_str[] = {
166 "512 kB", /* 0000 */
167 "1 MB", /* 0001 */
168 "2 MB", /* 0010 */
169 "4 MB", /* 0011 */
170 "8 MB", /* 0100 */
171 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
172 "32 MB", /* 0110 */
173 "64 MB", /* 0111 */
174 };
175
176 switch (cs) {
177 case CHIPSET_ICH8:
178 case CHIPSET_ICH9:
179 case CHIPSET_ICH10:
180 case CHIPSET_5_SERIES_IBEX_PEAK:
181 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000182 case CHIPSET_7_SERIES_PANTHER_POINT:
183 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000184 uint8_t size_enc;
185 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000186 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000187 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000188 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000189 }
190 if (size_enc > 5)
191 return "reserved";
192 return size_str[size_enc];
193 }
194 case CHIPSET_8_SERIES_LYNX_POINT:
195 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000196 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100197 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100198 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
David Hendricksa5216362017-08-08 20:02:22 -0700199 case CHIPSET_100_SERIES_SUNRISE_POINT:
200 case CHIPSET_C620_SERIES_LEWISBURG: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000201 uint8_t size_enc;
202 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000203 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000204 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000205 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000206 }
207 if (size_enc > 7)
208 return "reserved";
209 return size_str[size_enc];
210 }
211 case CHIPSET_ICH_UNKNOWN:
212 default:
213 return "unknown";
214 }
215}
216
217static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000218{
Nico Huberfa622942017-03-24 17:25:37 +0100219 static const char *const freq_str[2][8] = { {
Stefan Tauner1e146392011-09-15 23:52:55 +0000220 "20 MHz", /* 000 */
221 "33 MHz", /* 001 */
222 "reserved", /* 010 */
223 "reserved", /* 011 */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000224 "50 MHz", /* 100 */ /* New since Ibex Peak */
Stefan Tauner1e146392011-09-15 23:52:55 +0000225 "reserved", /* 101 */
226 "reserved", /* 110 */
227 "reserved" /* 111 */
Nico Huberfa622942017-03-24 17:25:37 +0100228 }, {
229 "reserved", /* 000 */
230 "reserved", /* 001 */
231 "48 MHz", /* 010 */
232 "reserved", /* 011 */
233 "30 MHz", /* 100 */
234 "reserved", /* 101 */
235 "17 MHz", /* 110 */
236 "reserved" /* 111 */
237 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000238
239 switch (cs) {
240 case CHIPSET_ICH8:
241 case CHIPSET_ICH9:
242 case CHIPSET_ICH10:
243 if (value > 1)
244 return "reserved";
245 case CHIPSET_5_SERIES_IBEX_PEAK:
246 case CHIPSET_6_SERIES_COUGAR_POINT:
247 case CHIPSET_7_SERIES_PANTHER_POINT:
248 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000249 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000250 case CHIPSET_8_SERIES_LYNX_POINT_LP:
251 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000252 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100253 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100254 return freq_str[0][value];
255 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -0700256 case CHIPSET_C620_SERIES_LEWISBURG:
Nico Huberfa622942017-03-24 17:25:37 +0100257 return freq_str[1][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000258 case CHIPSET_ICH_UNKNOWN:
259 default:
260 return "unknown";
261 }
262}
263
264void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
265{
Stefan Tauner1e146392011-09-15 23:52:55 +0000266
267 msg_pdbg2("=== Component Section ===\n");
268 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
269 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
David Hendricksa5216362017-08-08 20:02:22 -0700270 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG)
Nico Huberfa622942017-03-24 17:25:37 +0100271 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000272 msg_pdbg2("\n");
273
274 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000275 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000276 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000277 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000278 else
279 msg_pdbg2("Component 2 is not used.\n");
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000280 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
281 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
282 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
283 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
284 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000285 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000286 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000287 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
288 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000289 desc->component.modes.dual_output ? "dis" : "en");
David Hendricksa5216362017-08-08 20:02:22 -0700290
291 int has_forbidden_opcode = 0;
292 if (desc->component.FLILL != 0) {
293 has_forbidden_opcode = 1;
Stefan Tauner1e146392011-09-15 23:52:55 +0000294 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
295 desc->component.invalid_instr0);
296 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
297 desc->component.invalid_instr1);
298 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
299 desc->component.invalid_instr2);
300 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
301 desc->component.invalid_instr3);
David Hendricksa5216362017-08-08 20:02:22 -0700302 }
303 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG) {
304 if (desc->component.FLILL1 != 0) {
305 has_forbidden_opcode = 1;
Nico Huberfa622942017-03-24 17:25:37 +0100306 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
307 desc->component.invalid_instr4);
308 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
309 desc->component.invalid_instr5);
310 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
311 desc->component.invalid_instr6);
312 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
313 desc->component.invalid_instr7);
314 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000315 }
David Hendricksa5216362017-08-08 20:02:22 -0700316 if (!has_forbidden_opcode)
317 msg_pdbg2("No forbidden opcodes.\n");
318
Stefan Tauner1e146392011-09-15 23:52:55 +0000319 msg_pdbg2("\n");
320}
321
322static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
323{
Nico Huberfa622942017-03-24 17:25:37 +0100324 static const char *const region_names[] = {
David Hendricksa5216362017-08-08 20:02:22 -0700325 "Descr.", "BIOS", "ME", "GbE", "Platf.", "unknown", "BIOS2", "unknown",
326 "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown"
Stefan Tauner1e146392011-09-15 23:52:55 +0000327 };
Nico Huberfa622942017-03-24 17:25:37 +0100328 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000329 msg_pdbg2("%s: region index too high.\n", __func__);
330 return;
331 }
332 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
333 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100334 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000335 if (base > limit)
336 msg_pdbg2("is unused.\n");
337 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200338 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000339}
340
Nico Huberfa622942017-03-24 17:25:37 +0100341void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000342{
Nico Huberfa622942017-03-24 17:25:37 +0100343 size_t i;
344 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000345 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100346 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000347 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100348 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000349 return;
350 }
Nico Huberfa622942017-03-24 17:25:37 +0100351 for (i = 0; i < nr; i++)
352 msg_pdbg2("FLREG%zu 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000353 msg_pdbg2("\n");
354
355 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100356 for (i = 0; i < nr; i++)
Stefan Tauner1e146392011-09-15 23:52:55 +0000357 pprint_freg(&desc->region, i);
358 msg_pdbg2("\n");
359}
360
Nico Huberfa622942017-03-24 17:25:37 +0100361void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000362{
Nico Huberfa622942017-03-24 17:25:37 +0100363 size_t i;
364 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000365 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100366 if (nm < 0) {
367 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
368 desc->content.NM + 1);
369 return;
370 }
371 for (i = 0; i < nm; i++)
372 msg_pdbg2("FLMSTR%zu 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000373 msg_pdbg2("\n");
374
375 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100376 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
377 const char *const master_names[] = {
378 "BIOS", "ME", "GbE", "unknown", "EC",
379 };
380 if (nm >= ARRAY_SIZE(master_names)) {
381 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
382 desc->content.NM + 1);
383 return;
384 }
385
386 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9\n");
387 for (i = 0; i < nm; i++) {
388 size_t j;
389 msg_pdbg2("%-4s", master_names[i]);
390 for (j = 0; j < 10; j++)
391 msg_pdbg2(" %c%c ",
392 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
393 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
394 msg_pdbg2("\n");
395 }
David Hendricksa5216362017-08-08 20:02:22 -0700396 } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) {
397 const char *const master_names[] = {
398 "BIOS", "ME", "GbE", "DE", "BMC", "IE",
399 };
400 /* NM starts at 1 instead of 0 for LBG */
401 if (nm > ARRAY_SIZE(master_names)) {
402 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
403 desc->content.NM);
404 return;
405 }
406
407 msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
408 " ", /* width of master name (4 chars minimum) */
409 " FD ", " BIOS", " ME ", " GbE ", " Pltf",
410 " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ",
411 " IE ", "10GbE", "OpROM", "Reg13", "Reg14",
412 "Reg15");
413 for (i = 0; i < nm; i++) {
414 size_t j;
415 msg_pdbg2("%-4s", master_names[i]);
416 for (j = 0; j < 16; j++)
417 msg_pdbg2(" %c%c ",
418 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
419 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
420 msg_pdbg2("\n");
421 }
Nico Huberfa622942017-03-24 17:25:37 +0100422 } else {
423 const struct ich_desc_master *const mstr = &desc->master;
424 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
425 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
426 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
427 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
428 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
429 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
430 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
431 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
432 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
433 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
434 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
435 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
436 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
437 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
438 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
439 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
440 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
441 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
442 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
443 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000444 msg_pdbg2("\n");
445}
446
Stefan Taunerb3850962011-12-24 00:00:32 +0000447void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
448{
449 static const char * const str_GPIO12[4] = {
450 "GPIO12",
451 "LAN PHY Power Control Function (Native Output)",
452 "GLAN_DOCK# (Native Input)",
453 "invalid configuration",
454 };
455
456 msg_pdbg2("--- MCH details ---\n");
457 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
458 msg_pdbg2("\n");
459
460 msg_pdbg2("--- ICH details ---\n");
461 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
462 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
463 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
464 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
465 msg_pdbg2("SPI CS1 is used for %s.\n",
466 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
467 "LAN PHY Power Control Function" :
468 "SPI Chip Select");
469 msg_pdbg2("GPIO12 is used as %s.\n",
470 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
471 msg_pdbg2("PCIe Port 6 is used for %s.\n",
472 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
473 msg_pdbg2("%sn BMC Mode: "
474 "Intel AMT SMBus Controller 1 is connected to %s.\n",
475 desc->south.ich8.BMCMODE ? "I" : "Not i",
476 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
477 msg_pdbg2("TCO is in %s Mode.\n",
478 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
479 msg_pdbg2("ME A is %sabled.\n",
480 desc->south.ich8.ME_DISABLE ? "dis" : "en");
481 msg_pdbg2("\n");
482}
483
484static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
485{
486 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
487
488 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000489 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000490 case 0:
491 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
492 break;
493 case 1:
494 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
495 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
496 break;
497 case 2:
498 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
499 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
500 break;
501 case 3:
502 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
503 1+off, 2+off, 4+off);
504 break;
505 }
506 msg_pdbg2("\n");
507}
508
509void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
510{
511 /* PCHSTRP4 */
512 msg_pdbg2("Intel PHY is %s.\n",
513 (s->ibex.PHYCON == 2) ? "connected" :
514 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
515 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
516 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
517 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
518 s->ibex.GBEMAC_SMBUS_ADDR);
519 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
520 s->ibex.GBEPHY_SMBUS_ADDR);
521
522 /* PCHSTRP5 */
523 /* PCHSTRP6 */
524 /* PCHSTRP7 */
525 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
526 s->ibex.MESMA2UDID_VENDOR);
527 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
528 s->ibex.MESMA2UDID_VENDOR);
529
530 /* PCHSTRP8 */
531}
532
533void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
534{
535 /* PCHSTRP11 */
536 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
537 s->ibex.SML1GPAEN ? "en" : "dis");
538 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
539 s->ibex.SML1GPA);
540 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
541 s->ibex.SML1I2CAEN ? "en" : "dis");
542 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
543 s->ibex.SML1I2CA);
544
545 /* PCHSTRP12 */
546 /* PCHSTRP13 */
547}
548
549void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
550{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000551 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000552 100,
553 50,
554 5,
555 1
556 };
557
558 msg_pdbg2("--- PCH ---\n");
559
560 /* PCHSTRP0 */
561 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
562 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
563 s->ibex.SMB_EN ? "en" : "dis");
564 msg_pdbg2("SMLink0 segment is %sabled.\n",
565 s->ibex.SML0_EN ? "en" : "dis");
566 msg_pdbg2("SMLink1 segment is %sabled.\n",
567 s->ibex.SML1_EN ? "en" : "dis");
568 msg_pdbg2("SMLink1 Frequency: %s\n",
569 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
570 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
571 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
572 msg_pdbg2("SMLink0 Frequency: %s\n",
573 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
574 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
575 "LAN_PHY_PWR_CTRL" : "general purpose output");
576 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
577 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
578 s->ibex.DMI_REQID_DIS ? "en" : "dis");
579 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
580 1 << (6 + s->ibex.BBBS));
581
582 /* PCHSTRP1 */
583 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
584
585 /* PCHSTRP2 */
586 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
587 s->ibex.MESMASDEN ? "en" : "dis");
588 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
589 s->ibex.MESMASDA);
590 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
591 s->ibex.MESMI2CEN ? "en" : "dis");
592 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
593 s->ibex.MESMI2CA);
594
595 /* PCHSTRP3 */
596 prettyprint_ich_descriptor_pchstraps45678_56(s);
597 /* PCHSTRP9 */
598 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
599 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
600 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
601 s->ibex.PCIELR1 ? "" : "not ");
602 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
603 s->ibex.PCIELR2 ? "" : "not ");
604 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
605 s->ibex.DMILR ? "" : "not ");
606 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
607 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
608 s->ibex.PHY_PCIE_EN ? "en" : "dis");
609
610 /* PCHSTRP10 */
611 msg_pdbg2("Management Engine will boot from %sflash.\n",
612 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
613 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
614 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
615 s->ibex.VE_EN ? "en" : "dis");
616 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
617 s->ibex.MMDDE ? "en" : "dis");
618 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
619 s->ibex.MMADDR);
620 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
621 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
622 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
623 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
624 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
625
626 prettyprint_ich_descriptor_pchstraps111213_56(s);
627
628 /* PCHSTRP14 */
629 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
630 s->ibex.VE_EN2 ? "en" : "dis");
631 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
632 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
633 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
634 s->ibex.BW_SSD ? "en" : "dis");
635 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
636 s->ibex.NVMHCI_EN ? "en" : "dis");
637
638 /* PCHSTRP15 */
639 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
640 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
641 s->ibex.IWL_EN ? "en" : "dis");
642 msg_pdbg2("t209 min Timing: %d ms\n",
643 dec_t209min[s->ibex.t209min]);
644 msg_pdbg2("\n");
645}
646
647void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
648{
649 msg_pdbg2("--- PCH ---\n");
650
651 /* PCHSTRP0 */
652 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
653 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
654 s->ibex.SMB_EN ? "en" : "dis");
655 msg_pdbg2("SMLink0 segment is %sabled.\n",
656 s->ibex.SML0_EN ? "en" : "dis");
657 msg_pdbg2("SMLink1 segment is %sabled.\n",
658 s->ibex.SML1_EN ? "en" : "dis");
659 msg_pdbg2("SMLink1 Frequency: %s\n",
660 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
661 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
662 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
663 msg_pdbg2("SMLink0 Frequency: %s\n",
664 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
665 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
666 "LAN_PHY_PWR_CTRL" : "general purpose output");
667 msg_pdbg2("LinkSec is %sabled.\n",
668 s->cougar.LINKSEC_DIS ? "en" : "dis");
669 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
670 s->ibex.DMI_REQID_DIS ? "en" : "dis");
671 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
672 1 << (6 + s->ibex.BBBS));
673
674 /* PCHSTRP1 */
675 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
676 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
677
678 /* PCHSTRP2 */
679 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
680 s->ibex.MESMASDEN ? "en" : "dis");
681 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
682 s->ibex.MESMASDA);
683 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
684 s->cougar.MESMMCTPAEN ? "en" : "dis");
685 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
686 s->cougar.MESMMCTPA);
687 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
688 s->ibex.MESMI2CEN ? "en" : "dis");
689 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
690 s->ibex.MESMI2CA);
691
692 /* PCHSTRP3 */
693 prettyprint_ich_descriptor_pchstraps45678_56(s);
694 /* PCHSTRP9 */
695 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
696 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
697 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
698 s->ibex.PCIELR1 ? "" : "not ");
699 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
700 s->ibex.PCIELR2 ? "" : "not ");
701 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
702 s->ibex.DMILR ? "" : "not ");
703 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
704 s->cougar.MDSMBE_EN ? "en" : "dis");
705 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
706 s->cougar.MDSMBE_ADD);
707 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
708 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
709 s->ibex.PHY_PCIE_EN ? "en" : "dis");
710 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
711 s->cougar.SUB_DECODE_EN ? "en" : "dis");
712 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
713 "PCHHOT#" : "SML1ALERT#");
714
715 /* PCHSTRP10 */
716 msg_pdbg2("Management Engine will boot from %sflash.\n",
717 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
718
719 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
720 s->cougar.MDSMBE_EN ? "en" : "dis");
721 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
722 s->cougar.MDSMBE_ADD);
723
724 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
725 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000726 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
727 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000728 msg_pdbg2("ICC Profile is selected by %s.\n",
729 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
730 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
731 s->cougar.Deep_SX_EN ? "not " : "");
732 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
733 s->cougar.ME_DBG_LAN ? "en" : "dis");
734
735 prettyprint_ich_descriptor_pchstraps111213_56(s);
736
737 /* PCHSTRP14 */
738 /* PCHSTRP15 */
739 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
740 msg_pdbg2("Integrated wired LAN is %sabled.\n",
741 s->cougar.IWL_EN ? "en" : "dis");
742 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
743 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000744 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000745 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
746 "general purpose output" : "SLP_LAN#");
747
748 /* PCHSTRP16 */
749 /* PCHSTRP17 */
750 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
751 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
752 msg_pdbg2("\n");
753}
754
755void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
756{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000757 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000758 msg_pdbg2("=== Softstraps ===\n");
759
Nico Huberd7c75522017-03-29 16:31:49 +0200760 max_count = min(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
761 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000762 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200763 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000764 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200765 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000766
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000767 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
768 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000769 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
770 msg_pdbg2("\n");
771
Nico Huberd7c75522017-03-29 16:31:49 +0200772 max_count = min(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
773 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000774 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
775 desc->content.ISL, max_count);
776 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200777 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000778
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000779 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
780 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000781 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
782 msg_pdbg2("\n");
783
784 switch (cs) {
785 case CHIPSET_ICH8:
786 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
787 msg_pdbg2("Detailed North/MCH/PROC information is "
788 "probably not reliable, printing anyway.\n");
789 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
790 msg_pdbg2("Detailed South/ICH/PCH information is "
791 "probably not reliable, printing anyway.\n");
792 prettyprint_ich_descriptor_straps_ich8(desc);
793 break;
794 case CHIPSET_5_SERIES_IBEX_PEAK:
795 /* PCH straps only. PROCSTRPs are unknown. */
796 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
797 msg_pdbg2("Detailed South/ICH/PCH information is "
798 "probably not reliable, printing anyway.\n");
799 prettyprint_ich_descriptor_straps_ibex(&desc->south);
800 break;
801 case CHIPSET_6_SERIES_COUGAR_POINT:
802 /* PCH straps only. PROCSTRP0 is "reserved". */
803 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
804 msg_pdbg2("Detailed South/ICH/PCH information is "
805 "probably not reliable, printing anyway.\n");
806 prettyprint_ich_descriptor_straps_cougar(&desc->south);
807 break;
808 case CHIPSET_ICH_UNKNOWN:
809 break;
810 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000811 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000812 break;
813 }
814}
815
816void prettyprint_rdid(uint32_t reg_val)
817{
818 uint8_t mid = reg_val & 0xFF;
819 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
820 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
821}
822
823void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
824{
825 int i;
826 msg_pdbg2("=== Upper Map Section ===\n");
827 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
828 msg_pdbg2("\n");
829
830 msg_pdbg2("--- Details ---\n");
831 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
832 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
833 msg_pdbg2("\n");
834
835 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000836 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000837 uint32_t jid = umap->vscc_table[i].JID;
838 uint32_t vscc = umap->vscc_table[i].VSCC;
839 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
840 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
841 msg_pdbg2(" "); /* indention */
842 prettyprint_rdid(jid);
843 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000844 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000845 }
846 msg_pdbg2("\n");
847}
848
Nico Huber1dc3d422017-06-17 00:09:31 +0200849/*
850 * Guesses a minimum chipset version based on the maximum number of
851 * soft straps per generation.
852 */
853static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
854{
855 if (content->ICCRIBA == 0x00) {
856 if (content->MSL == 0 && content->ISL <= 2)
857 return CHIPSET_ICH8;
858 else if (content->ISL <= 2)
859 return CHIPSET_ICH9;
860 else if (content->ISL <= 10)
861 return CHIPSET_ICH10;
862 else if (content->ISL <= 16)
863 return CHIPSET_5_SERIES_IBEX_PEAK;
864 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
865 return CHIPSET_5_SERIES_IBEX_PEAK;
866 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
867 if (content->MSL == 0 && content->ISL <= 17)
868 return CHIPSET_BAYTRAIL;
869 else if (content->MSL <= 1 && content->ISL <= 18)
870 return CHIPSET_6_SERIES_COUGAR_POINT;
871 else if (content->MSL <= 1 && content->ISL <= 21)
872 return CHIPSET_8_SERIES_LYNX_POINT;
873 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
874 return CHIPSET_9_SERIES_WILDCAT_POINT;
David Hendricksa5216362017-08-08 20:02:22 -0700875 } else if (content->NM == 6) {
876 return CHIPSET_C620_SERIES_LEWISBURG;
Nico Huber1dc3d422017-06-17 00:09:31 +0200877 } else {
878 return CHIPSET_100_SERIES_SUNRISE_POINT;
879 }
880}
881
882/*
883 * As an additional measure, we check the read frequency like `ifdtool`.
884 * The frequency value 6 (17MHz) was reserved before Skylake and is the
885 * only valid value since. Skylake is currently the most important dis-
886 * tinction because of the dropped number of regions field (NR).
887 */
Nico Huberfa622942017-03-24 17:25:37 +0100888static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
889 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200890{
891 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
892
893 if (component->modes.freq_read == 6) {
David Hendricksa5216362017-08-08 20:02:22 -0700894 if ((guess != CHIPSET_100_SERIES_SUNRISE_POINT) && (guess != CHIPSET_C620_SERIES_LEWISBURG)) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200895 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
896 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
897 "Please report this message, the output of `ich_descriptors_tool` for\n"
898 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
David Hendricksa5216362017-08-08 20:02:22 -0700899 return CHIPSET_100_SERIES_SUNRISE_POINT;
900 }
901 return guess;
Nico Huber1dc3d422017-06-17 00:09:31 +0200902 } else {
David Hendricksa5216362017-08-08 20:02:22 -0700903 if (guess == CHIPSET_100_SERIES_SUNRISE_POINT || guess == CHIPSET_C620_SERIES_LEWISBURG) {
Nico Huber1dc3d422017-06-17 00:09:31 +0200904 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
905 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
906 "Please report this message, the output of `ich_descriptors_tool` for\n"
907 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
908 return CHIPSET_9_SERIES_WILDCAT_POINT;
909 }
910 }
911
912 return guess;
913}
914
Stefan Taunerb3850962011-12-24 00:00:32 +0000915/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +0100916int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
917 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000918{
Nico Huberfa622942017-03-24 17:25:37 +0100919 size_t i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000920 uint8_t pch_bug_offset = 0;
921
922 if (dump == NULL || desc == NULL)
923 return ICH_RET_PARAM;
924
925 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
926 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
927 pch_bug_offset = 4;
928 else
929 return ICH_RET_ERR;
930 }
931
932 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +0200933 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000934 return ICH_RET_OOB;
935 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
936 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
937 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
938 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
939
940 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +0200941 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000942 return ICH_RET_OOB;
943 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
944 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
945 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
946
Nico Huber67d71792017-06-17 03:10:15 +0200947 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +0100948 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +0200949 prettyprint_ich_chipset(*cs);
950 }
Nico Huberfa622942017-03-24 17:25:37 +0100951
Stefan Taunerb3850962011-12-24 00:00:32 +0000952 /* region */
Nico Huberfa622942017-03-24 17:25:37 +0100953 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
954 if (nr < 0 || len < getFRBA(&desc->content) + nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000955 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +0100956 for (i = 0; i < nr; i++)
957 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000958
959 /* master */
Nico Huberfa622942017-03-24 17:25:37 +0100960 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
961 if (nm < 0 || len < getFMBA(&desc->content) + nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000962 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +0100963 for (i = 0; i < nm; i++)
964 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000965
966 /* upper map */
967 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
968
969 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
970 * "Identifies the 1s based number of DWORDS contained in the VSCC
971 * Table. Each SPI component entry in the table is 2 DWORDS long." So
972 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
973 * check ensures that the maximum offset actually accessed is available.
974 */
Nico Huber9e14aed2017-03-28 17:08:46 +0200975 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +0000976 return ICH_RET_OOB;
977
978 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000979 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
980 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +0000981 }
982
983 /* MCH/PROC (aka. North) straps */
984 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
985 return ICH_RET_OOB;
986
987 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000988 max_count = min(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
989 for (i = 0; i < max_count; i++)
990 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000991
992 /* ICH/PCH (aka. South) straps */
993 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
994 return ICH_RET_OOB;
995
996 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000997 max_count = min(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
998 for (i = 0; i < max_count; i++)
999 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +00001000
1001 return ICH_RET_OK;
1002}
1003
Nico Huberad186312016-05-02 15:15:29 +02001004#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +00001005
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001006/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001007\em idx in bytes or -1 if the correct size can not be determined. */
1008int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001009{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001010 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001011 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001012 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001013 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001014
1015 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001016 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001017
1018 uint8_t size_enc;
1019 uint8_t size_max;
1020
1021 switch (cs) {
1022 case CHIPSET_ICH8:
1023 case CHIPSET_ICH9:
1024 case CHIPSET_ICH10:
1025 case CHIPSET_5_SERIES_IBEX_PEAK:
1026 case CHIPSET_6_SERIES_COUGAR_POINT:
1027 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001028 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001029 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001030 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001031 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001032 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001033 }
1034 size_max = 5;
1035 break;
1036 case CHIPSET_8_SERIES_LYNX_POINT:
1037 case CHIPSET_8_SERIES_LYNX_POINT_LP:
1038 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +00001039 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +01001040 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +01001041 case CHIPSET_100_SERIES_SUNRISE_POINT:
David Hendricksa5216362017-08-08 20:02:22 -07001042 case CHIPSET_C620_SERIES_LEWISBURG:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001043 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001044 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001045 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001046 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001047 }
1048 size_max = 7;
1049 break;
1050 case CHIPSET_ICH_UNKNOWN:
1051 default:
1052 msg_pwarn("Density encoding is unknown on this chipset.\n");
1053 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001054 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001055
1056 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001057 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001058 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1059 idx, size_enc, size_max);
1060 return -1;
1061 }
1062
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001063 return (1 << (19 + size_enc));
1064}
1065
Nico Huber8d494992017-06-19 12:18:33 +02001066/* Only used by ichspi.c */
1067#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001068static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001069{
1070 uint32_t control = 0;
1071 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1072 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
David Hendricksa5216362017-08-08 20:02:22 -07001073 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG) {
Nico Huberd54e4f42017-03-23 23:45:47 +01001074 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1075 return mmio_le_readl(spibar + PCH100_REG_FDOD);
1076 } else {
1077 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1078 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1079 }
Stefan Tauner1e146392011-09-15 23:52:55 +00001080}
1081
Nico Huberd54e4f42017-03-23 23:45:47 +01001082int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001083{
Nico Huberfa622942017-03-24 17:25:37 +01001084 size_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001085 struct ich_desc_region *r = &desc->region;
1086
1087 /* Test if bit-fields are working as expected.
1088 * FIXME: Replace this with dynamic bitfield fixup
1089 */
1090 for (i = 0; i < 4; i++)
1091 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001092 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1093 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1094 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1095 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001096 msg_pdbg("The combination of compiler and CPU architecture used"
1097 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001098 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1099 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1100 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1101 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1102 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1103 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1104 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1105 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001106 return ICH_RET_ERR;
1107 }
1108
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001109 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001110 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001111 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1112 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1113 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1114 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001115
1116 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001117 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1118 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1119 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001120
1121 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001122 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1123 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001124 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001125 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001126 return ICH_RET_ERR;
1127 }
Nico Huberfa622942017-03-24 17:25:37 +01001128 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001129 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001130
1131 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001132 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1133 if (nm < 0) {
1134 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1135 __func__, desc->content.NM + 1);
1136 return ICH_RET_ERR;
1137 }
1138 for (i = 0; i < nm; i++)
1139 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001140
1141 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1142 * reading the upper map is impossible on all chipsets, so don't bother.
1143 */
1144
1145 msg_pdbg2(" done.\n");
1146 return ICH_RET_OK;
1147}
Nico Huber8d494992017-06-19 12:18:33 +02001148#endif
Nico Huber305f4172013-06-14 11:55:26 +02001149
1150/**
1151 * @brief Read a layout from the dump of an Intel ICH descriptor.
1152 *
1153 * @param layout Pointer where to store the layout.
1154 * @param dump The descriptor dump to read from.
1155 * @param len The length of the descriptor dump.
1156 *
1157 * @return 0 on success,
1158 * 1 if the descriptor couldn't be parsed.
1159 */
1160int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1161{
Nico Huberfa622942017-03-24 17:25:37 +01001162 static const char *const regions[] = {
David Hendricksa5216362017-08-08 20:02:22 -07001163 "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie",
1164 "10gbe", "reg12", "reg13", "reg14", "reg15"
Nico Huberfa622942017-03-24 17:25:37 +01001165 };
Nico Huber305f4172013-06-14 11:55:26 +02001166
1167 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001168 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1169 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001170 return 1;
1171
1172 memset(layout, 0x00, sizeof(*layout));
1173
Nico Huberfa622942017-03-24 17:25:37 +01001174 ssize_t i, j;
1175 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 +02001176 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001177 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001178 if (limit <= base)
1179 continue;
1180 layout->entries[j].start = base;
1181 layout->entries[j].end = limit;
1182 layout->entries[j].included = false;
1183 snprintf(layout->entries[j].name, sizeof(layout->entries[j].name), "%s", regions[i]);
1184 ++j;
1185 }
1186 layout->base.entries = layout->entries;
1187 layout->base.num_entries = j;
1188 return 0;
1189}
1190
Nico Huberad186312016-05-02 15:15:29 +02001191#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */