blob: a2f8edf3ca443c7b8d14842f7f29ff64c10202e7 [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 Huberad186312016-05-02 15:15:29 +020037#include <string.h>
Stefan Tauner1e146392011-09-15 23:52:55 +000038#include "flash.h" /* for msg_* */
39#include "programmer.h"
40
Stefan Taunerb3850962011-12-24 00:00:32 +000041#ifndef min
Nico Huber305f4172013-06-14 11:55:26 +020042#define min(a, b) (((a) < (b)) ? (a) : (b))
Stefan Taunerb3850962011-12-24 00:00:32 +000043#endif
44
Nico Huberfa622942017-03-24 17:25:37 +010045ssize_t ich_number_of_regions(const enum ich_chipset cs, const struct ich_desc_content *const cont)
46{
47 switch (cs) {
48 case CHIPSET_100_SERIES_SUNRISE_POINT:
49 return 10;
50 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
51 case CHIPSET_9_SERIES_WILDCAT_POINT:
52 case CHIPSET_8_SERIES_LYNX_POINT_LP:
53 case CHIPSET_8_SERIES_LYNX_POINT:
54 case CHIPSET_8_SERIES_WELLSBURG:
55 if (cont->NR <= 6)
56 return cont->NR + 1;
57 else
58 return -1;
59 default:
60 if (cont->NR <= 4)
61 return cont->NR + 1;
62 else
63 return -1;
64 }
65}
66
67ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
68{
69 if (cont->NM < MAX_NUM_MASTERS)
70 return cont->NM + 1;
71 else
72 return -1;
73}
74
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000075void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000076{
77 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
78 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
79 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
80 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000081 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
82 if (print_vcl)
83 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
84 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000085}
86
87#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
88#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
89#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
90#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
91#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
92
Nico Huber67d71792017-06-17 03:10:15 +020093void prettyprint_ich_chipset(enum ich_chipset cs)
94{
95 static const char *const chipset_names[] = {
96 "Unknown ICH", "ICH8", "ICH9", "ICH10",
97 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
98 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
99 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
100 };
101 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
102 cs = 0;
103 else
104 cs = cs - CHIPSET_ICH8 + 1;
105 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
106}
107
Stefan Tauner1e146392011-09-15 23:52:55 +0000108void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
109{
Nico Huberfa622942017-03-24 17:25:37 +0100110 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000111 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100112 prettyprint_ich_descriptor_region(cs, desc);
113 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200114#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000115 if (cs >= CHIPSET_ICH8) {
116 prettyprint_ich_descriptor_upper_map(&desc->upper);
117 prettyprint_ich_descriptor_straps(cs, desc);
118 }
Nico Huberad186312016-05-02 15:15:29 +0200119#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000120}
121
Nico Huberfa622942017-03-24 17:25:37 +0100122void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000123{
124 msg_pdbg2("=== Content Section ===\n");
125 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
126 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
127 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
128 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
129 msg_pdbg2("\n");
130
131 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100132 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
133 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
134 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
135 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
136 msg_pdbg2("ISL (ICH/PCH Strap Length): %5d\n", cont->ISL);
137 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH Strap Base Address): 0x%03x\n", getFISBA(cont));
138 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
139 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
140 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
141 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000142 msg_pdbg2("\n");
143}
144
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000145static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
146{
147 if (idx > 1) {
148 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
149 return NULL;
150 }
151
152 if (desc->content.NC == 0 && idx > 0)
153 return "unused";
154
155 static const char * const size_str[] = {
156 "512 kB", /* 0000 */
157 "1 MB", /* 0001 */
158 "2 MB", /* 0010 */
159 "4 MB", /* 0011 */
160 "8 MB", /* 0100 */
161 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
162 "32 MB", /* 0110 */
163 "64 MB", /* 0111 */
164 };
165
166 switch (cs) {
167 case CHIPSET_ICH8:
168 case CHIPSET_ICH9:
169 case CHIPSET_ICH10:
170 case CHIPSET_5_SERIES_IBEX_PEAK:
171 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000172 case CHIPSET_7_SERIES_PANTHER_POINT:
173 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000174 uint8_t size_enc;
175 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000176 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000177 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000178 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000179 }
180 if (size_enc > 5)
181 return "reserved";
182 return size_str[size_enc];
183 }
184 case CHIPSET_8_SERIES_LYNX_POINT:
185 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000186 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100187 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100188 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
189 case CHIPSET_100_SERIES_SUNRISE_POINT: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000190 uint8_t size_enc;
191 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000192 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000193 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000194 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000195 }
196 if (size_enc > 7)
197 return "reserved";
198 return size_str[size_enc];
199 }
200 case CHIPSET_ICH_UNKNOWN:
201 default:
202 return "unknown";
203 }
204}
205
206static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000207{
Nico Huberfa622942017-03-24 17:25:37 +0100208 static const char *const freq_str[2][8] = { {
Stefan Tauner1e146392011-09-15 23:52:55 +0000209 "20 MHz", /* 000 */
210 "33 MHz", /* 001 */
211 "reserved", /* 010 */
212 "reserved", /* 011 */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000213 "50 MHz", /* 100 */ /* New since Ibex Peak */
Stefan Tauner1e146392011-09-15 23:52:55 +0000214 "reserved", /* 101 */
215 "reserved", /* 110 */
216 "reserved" /* 111 */
Nico Huberfa622942017-03-24 17:25:37 +0100217 }, {
218 "reserved", /* 000 */
219 "reserved", /* 001 */
220 "48 MHz", /* 010 */
221 "reserved", /* 011 */
222 "30 MHz", /* 100 */
223 "reserved", /* 101 */
224 "17 MHz", /* 110 */
225 "reserved" /* 111 */
226 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000227
228 switch (cs) {
229 case CHIPSET_ICH8:
230 case CHIPSET_ICH9:
231 case CHIPSET_ICH10:
232 if (value > 1)
233 return "reserved";
234 case CHIPSET_5_SERIES_IBEX_PEAK:
235 case CHIPSET_6_SERIES_COUGAR_POINT:
236 case CHIPSET_7_SERIES_PANTHER_POINT:
237 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000238 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000239 case CHIPSET_8_SERIES_LYNX_POINT_LP:
240 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000241 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100242 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100243 return freq_str[0][value];
244 case CHIPSET_100_SERIES_SUNRISE_POINT:
245 return freq_str[1][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000246 case CHIPSET_ICH_UNKNOWN:
247 default:
248 return "unknown";
249 }
250}
251
252void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
253{
Stefan Tauner1e146392011-09-15 23:52:55 +0000254
255 msg_pdbg2("=== Component Section ===\n");
256 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
257 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberfa622942017-03-24 17:25:37 +0100258 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT)
259 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000260 msg_pdbg2("\n");
261
262 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000263 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000264 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000265 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000266 else
267 msg_pdbg2("Component 2 is not used.\n");
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000268 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
269 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
270 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
271 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
272 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000273 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000274 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000275 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
276 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000277 desc->component.modes.dual_output ? "dis" : "en");
Nico Huberfa622942017-03-24 17:25:37 +0100278 if (desc->component.FLILL == 0 &&
279 (cs != CHIPSET_100_SERIES_SUNRISE_POINT || desc->component.FLILL1 == 0)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000280 msg_pdbg2("No forbidden opcodes.\n");
Nico Huberfa622942017-03-24 17:25:37 +0100281 } else {
Stefan Tauner1e146392011-09-15 23:52:55 +0000282 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
283 desc->component.invalid_instr0);
284 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
285 desc->component.invalid_instr1);
286 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
287 desc->component.invalid_instr2);
288 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
289 desc->component.invalid_instr3);
Nico Huberfa622942017-03-24 17:25:37 +0100290 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
291 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
292 desc->component.invalid_instr4);
293 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
294 desc->component.invalid_instr5);
295 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
296 desc->component.invalid_instr6);
297 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
298 desc->component.invalid_instr7);
299 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000300 }
301 msg_pdbg2("\n");
302}
303
304static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
305{
Nico Huberfa622942017-03-24 17:25:37 +0100306 static const char *const region_names[] = {
307 "Descr.", "BIOS", "ME", "GbE", "Platf.", "unknown", "unknown", "unknown",
308 "EC", "unknown",
Stefan Tauner1e146392011-09-15 23:52:55 +0000309 };
Nico Huberfa622942017-03-24 17:25:37 +0100310 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000311 msg_pdbg2("%s: region index too high.\n", __func__);
312 return;
313 }
314 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
315 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100316 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000317 if (base > limit)
318 msg_pdbg2("is unused.\n");
319 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200320 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000321}
322
Nico Huberfa622942017-03-24 17:25:37 +0100323void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000324{
Nico Huberfa622942017-03-24 17:25:37 +0100325 size_t i;
326 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000327 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100328 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000329 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100330 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000331 return;
332 }
Nico Huberfa622942017-03-24 17:25:37 +0100333 for (i = 0; i < nr; i++)
334 msg_pdbg2("FLREG%zu 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000335 msg_pdbg2("\n");
336
337 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100338 for (i = 0; i < nr; i++)
Stefan Tauner1e146392011-09-15 23:52:55 +0000339 pprint_freg(&desc->region, i);
340 msg_pdbg2("\n");
341}
342
Nico Huberfa622942017-03-24 17:25:37 +0100343void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000344{
Nico Huberfa622942017-03-24 17:25:37 +0100345 size_t i;
346 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000347 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100348 if (nm < 0) {
349 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
350 desc->content.NM + 1);
351 return;
352 }
353 for (i = 0; i < nm; i++)
354 msg_pdbg2("FLMSTR%zu 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000355 msg_pdbg2("\n");
356
357 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100358 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
359 const char *const master_names[] = {
360 "BIOS", "ME", "GbE", "unknown", "EC",
361 };
362 if (nm >= ARRAY_SIZE(master_names)) {
363 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
364 desc->content.NM + 1);
365 return;
366 }
367
368 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9\n");
369 for (i = 0; i < nm; i++) {
370 size_t j;
371 msg_pdbg2("%-4s", master_names[i]);
372 for (j = 0; j < 10; j++)
373 msg_pdbg2(" %c%c ",
374 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
375 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
376 msg_pdbg2("\n");
377 }
378 } else {
379 const struct ich_desc_master *const mstr = &desc->master;
380 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
381 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
382 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
383 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
384 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
385 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
386 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
387 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
388 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
389 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
390 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
391 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
392 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
393 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
394 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
395 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
396 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
397 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
398 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
399 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000400 msg_pdbg2("\n");
401}
402
Stefan Taunerb3850962011-12-24 00:00:32 +0000403void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
404{
405 static const char * const str_GPIO12[4] = {
406 "GPIO12",
407 "LAN PHY Power Control Function (Native Output)",
408 "GLAN_DOCK# (Native Input)",
409 "invalid configuration",
410 };
411
412 msg_pdbg2("--- MCH details ---\n");
413 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
414 msg_pdbg2("\n");
415
416 msg_pdbg2("--- ICH details ---\n");
417 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
418 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
419 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
420 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
421 msg_pdbg2("SPI CS1 is used for %s.\n",
422 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
423 "LAN PHY Power Control Function" :
424 "SPI Chip Select");
425 msg_pdbg2("GPIO12 is used as %s.\n",
426 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
427 msg_pdbg2("PCIe Port 6 is used for %s.\n",
428 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
429 msg_pdbg2("%sn BMC Mode: "
430 "Intel AMT SMBus Controller 1 is connected to %s.\n",
431 desc->south.ich8.BMCMODE ? "I" : "Not i",
432 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
433 msg_pdbg2("TCO is in %s Mode.\n",
434 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
435 msg_pdbg2("ME A is %sabled.\n",
436 desc->south.ich8.ME_DISABLE ? "dis" : "en");
437 msg_pdbg2("\n");
438}
439
440static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
441{
442 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
443
444 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000445 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000446 case 0:
447 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
448 break;
449 case 1:
450 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
451 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
452 break;
453 case 2:
454 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
455 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
456 break;
457 case 3:
458 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
459 1+off, 2+off, 4+off);
460 break;
461 }
462 msg_pdbg2("\n");
463}
464
465void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
466{
467 /* PCHSTRP4 */
468 msg_pdbg2("Intel PHY is %s.\n",
469 (s->ibex.PHYCON == 2) ? "connected" :
470 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
471 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
472 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
473 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
474 s->ibex.GBEMAC_SMBUS_ADDR);
475 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
476 s->ibex.GBEPHY_SMBUS_ADDR);
477
478 /* PCHSTRP5 */
479 /* PCHSTRP6 */
480 /* PCHSTRP7 */
481 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
482 s->ibex.MESMA2UDID_VENDOR);
483 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
484 s->ibex.MESMA2UDID_VENDOR);
485
486 /* PCHSTRP8 */
487}
488
489void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
490{
491 /* PCHSTRP11 */
492 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
493 s->ibex.SML1GPAEN ? "en" : "dis");
494 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
495 s->ibex.SML1GPA);
496 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
497 s->ibex.SML1I2CAEN ? "en" : "dis");
498 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
499 s->ibex.SML1I2CA);
500
501 /* PCHSTRP12 */
502 /* PCHSTRP13 */
503}
504
505void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
506{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000507 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000508 100,
509 50,
510 5,
511 1
512 };
513
514 msg_pdbg2("--- PCH ---\n");
515
516 /* PCHSTRP0 */
517 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
518 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
519 s->ibex.SMB_EN ? "en" : "dis");
520 msg_pdbg2("SMLink0 segment is %sabled.\n",
521 s->ibex.SML0_EN ? "en" : "dis");
522 msg_pdbg2("SMLink1 segment is %sabled.\n",
523 s->ibex.SML1_EN ? "en" : "dis");
524 msg_pdbg2("SMLink1 Frequency: %s\n",
525 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
526 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
527 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
528 msg_pdbg2("SMLink0 Frequency: %s\n",
529 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
530 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
531 "LAN_PHY_PWR_CTRL" : "general purpose output");
532 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
533 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
534 s->ibex.DMI_REQID_DIS ? "en" : "dis");
535 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
536 1 << (6 + s->ibex.BBBS));
537
538 /* PCHSTRP1 */
539 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
540
541 /* PCHSTRP2 */
542 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
543 s->ibex.MESMASDEN ? "en" : "dis");
544 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
545 s->ibex.MESMASDA);
546 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
547 s->ibex.MESMI2CEN ? "en" : "dis");
548 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
549 s->ibex.MESMI2CA);
550
551 /* PCHSTRP3 */
552 prettyprint_ich_descriptor_pchstraps45678_56(s);
553 /* PCHSTRP9 */
554 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
555 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
556 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
557 s->ibex.PCIELR1 ? "" : "not ");
558 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
559 s->ibex.PCIELR2 ? "" : "not ");
560 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
561 s->ibex.DMILR ? "" : "not ");
562 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
563 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
564 s->ibex.PHY_PCIE_EN ? "en" : "dis");
565
566 /* PCHSTRP10 */
567 msg_pdbg2("Management Engine will boot from %sflash.\n",
568 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
569 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
570 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
571 s->ibex.VE_EN ? "en" : "dis");
572 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
573 s->ibex.MMDDE ? "en" : "dis");
574 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
575 s->ibex.MMADDR);
576 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
577 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
578 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
579 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
580 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
581
582 prettyprint_ich_descriptor_pchstraps111213_56(s);
583
584 /* PCHSTRP14 */
585 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
586 s->ibex.VE_EN2 ? "en" : "dis");
587 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
588 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
589 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
590 s->ibex.BW_SSD ? "en" : "dis");
591 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
592 s->ibex.NVMHCI_EN ? "en" : "dis");
593
594 /* PCHSTRP15 */
595 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
596 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
597 s->ibex.IWL_EN ? "en" : "dis");
598 msg_pdbg2("t209 min Timing: %d ms\n",
599 dec_t209min[s->ibex.t209min]);
600 msg_pdbg2("\n");
601}
602
603void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
604{
605 msg_pdbg2("--- PCH ---\n");
606
607 /* PCHSTRP0 */
608 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
609 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
610 s->ibex.SMB_EN ? "en" : "dis");
611 msg_pdbg2("SMLink0 segment is %sabled.\n",
612 s->ibex.SML0_EN ? "en" : "dis");
613 msg_pdbg2("SMLink1 segment is %sabled.\n",
614 s->ibex.SML1_EN ? "en" : "dis");
615 msg_pdbg2("SMLink1 Frequency: %s\n",
616 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
617 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
618 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
619 msg_pdbg2("SMLink0 Frequency: %s\n",
620 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
621 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
622 "LAN_PHY_PWR_CTRL" : "general purpose output");
623 msg_pdbg2("LinkSec is %sabled.\n",
624 s->cougar.LINKSEC_DIS ? "en" : "dis");
625 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
626 s->ibex.DMI_REQID_DIS ? "en" : "dis");
627 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
628 1 << (6 + s->ibex.BBBS));
629
630 /* PCHSTRP1 */
631 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
632 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
633
634 /* PCHSTRP2 */
635 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
636 s->ibex.MESMASDEN ? "en" : "dis");
637 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
638 s->ibex.MESMASDA);
639 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
640 s->cougar.MESMMCTPAEN ? "en" : "dis");
641 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
642 s->cougar.MESMMCTPA);
643 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
644 s->ibex.MESMI2CEN ? "en" : "dis");
645 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
646 s->ibex.MESMI2CA);
647
648 /* PCHSTRP3 */
649 prettyprint_ich_descriptor_pchstraps45678_56(s);
650 /* PCHSTRP9 */
651 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
652 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
653 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
654 s->ibex.PCIELR1 ? "" : "not ");
655 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
656 s->ibex.PCIELR2 ? "" : "not ");
657 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
658 s->ibex.DMILR ? "" : "not ");
659 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
660 s->cougar.MDSMBE_EN ? "en" : "dis");
661 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
662 s->cougar.MDSMBE_ADD);
663 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
664 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
665 s->ibex.PHY_PCIE_EN ? "en" : "dis");
666 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
667 s->cougar.SUB_DECODE_EN ? "en" : "dis");
668 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
669 "PCHHOT#" : "SML1ALERT#");
670
671 /* PCHSTRP10 */
672 msg_pdbg2("Management Engine will boot from %sflash.\n",
673 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
674
675 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
676 s->cougar.MDSMBE_EN ? "en" : "dis");
677 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
678 s->cougar.MDSMBE_ADD);
679
680 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
681 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000682 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
683 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000684 msg_pdbg2("ICC Profile is selected by %s.\n",
685 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
686 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
687 s->cougar.Deep_SX_EN ? "not " : "");
688 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
689 s->cougar.ME_DBG_LAN ? "en" : "dis");
690
691 prettyprint_ich_descriptor_pchstraps111213_56(s);
692
693 /* PCHSTRP14 */
694 /* PCHSTRP15 */
695 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
696 msg_pdbg2("Integrated wired LAN is %sabled.\n",
697 s->cougar.IWL_EN ? "en" : "dis");
698 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
699 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000700 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000701 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
702 "general purpose output" : "SLP_LAN#");
703
704 /* PCHSTRP16 */
705 /* PCHSTRP17 */
706 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
707 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
708 msg_pdbg2("\n");
709}
710
711void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
712{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000713 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000714 msg_pdbg2("=== Softstraps ===\n");
715
Nico Huberd7c75522017-03-29 16:31:49 +0200716 max_count = min(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
717 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000718 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200719 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000720 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200721 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000722
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000723 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
724 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000725 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
726 msg_pdbg2("\n");
727
Nico Huberd7c75522017-03-29 16:31:49 +0200728 max_count = min(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
729 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000730 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
731 desc->content.ISL, max_count);
732 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200733 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000734
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000735 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
736 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000737 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
738 msg_pdbg2("\n");
739
740 switch (cs) {
741 case CHIPSET_ICH8:
742 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
743 msg_pdbg2("Detailed North/MCH/PROC information is "
744 "probably not reliable, printing anyway.\n");
745 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
746 msg_pdbg2("Detailed South/ICH/PCH information is "
747 "probably not reliable, printing anyway.\n");
748 prettyprint_ich_descriptor_straps_ich8(desc);
749 break;
750 case CHIPSET_5_SERIES_IBEX_PEAK:
751 /* PCH straps only. PROCSTRPs are unknown. */
752 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
753 msg_pdbg2("Detailed South/ICH/PCH information is "
754 "probably not reliable, printing anyway.\n");
755 prettyprint_ich_descriptor_straps_ibex(&desc->south);
756 break;
757 case CHIPSET_6_SERIES_COUGAR_POINT:
758 /* PCH straps only. PROCSTRP0 is "reserved". */
759 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
760 msg_pdbg2("Detailed South/ICH/PCH information is "
761 "probably not reliable, printing anyway.\n");
762 prettyprint_ich_descriptor_straps_cougar(&desc->south);
763 break;
764 case CHIPSET_ICH_UNKNOWN:
765 break;
766 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000767 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000768 break;
769 }
770}
771
772void prettyprint_rdid(uint32_t reg_val)
773{
774 uint8_t mid = reg_val & 0xFF;
775 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
776 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
777}
778
779void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
780{
781 int i;
782 msg_pdbg2("=== Upper Map Section ===\n");
783 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
784 msg_pdbg2("\n");
785
786 msg_pdbg2("--- Details ---\n");
787 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
788 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
789 msg_pdbg2("\n");
790
791 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000792 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000793 uint32_t jid = umap->vscc_table[i].JID;
794 uint32_t vscc = umap->vscc_table[i].VSCC;
795 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
796 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
797 msg_pdbg2(" "); /* indention */
798 prettyprint_rdid(jid);
799 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000800 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000801 }
802 msg_pdbg2("\n");
803}
804
Nico Huber1dc3d422017-06-17 00:09:31 +0200805/*
806 * Guesses a minimum chipset version based on the maximum number of
807 * soft straps per generation.
808 */
809static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
810{
811 if (content->ICCRIBA == 0x00) {
812 if (content->MSL == 0 && content->ISL <= 2)
813 return CHIPSET_ICH8;
814 else if (content->ISL <= 2)
815 return CHIPSET_ICH9;
816 else if (content->ISL <= 10)
817 return CHIPSET_ICH10;
818 else if (content->ISL <= 16)
819 return CHIPSET_5_SERIES_IBEX_PEAK;
820 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
821 return CHIPSET_5_SERIES_IBEX_PEAK;
822 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
823 if (content->MSL == 0 && content->ISL <= 17)
824 return CHIPSET_BAYTRAIL;
825 else if (content->MSL <= 1 && content->ISL <= 18)
826 return CHIPSET_6_SERIES_COUGAR_POINT;
827 else if (content->MSL <= 1 && content->ISL <= 21)
828 return CHIPSET_8_SERIES_LYNX_POINT;
829 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
830 return CHIPSET_9_SERIES_WILDCAT_POINT;
831 } else {
832 return CHIPSET_100_SERIES_SUNRISE_POINT;
833 }
834}
835
836/*
837 * As an additional measure, we check the read frequency like `ifdtool`.
838 * The frequency value 6 (17MHz) was reserved before Skylake and is the
839 * only valid value since. Skylake is currently the most important dis-
840 * tinction because of the dropped number of regions field (NR).
841 */
Nico Huberfa622942017-03-24 17:25:37 +0100842static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
843 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200844{
845 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
846
847 if (component->modes.freq_read == 6) {
848 if (guess != CHIPSET_100_SERIES_SUNRISE_POINT)
849 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
850 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
851 "Please report this message, the output of `ich_descriptors_tool` for\n"
852 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
853 return CHIPSET_100_SERIES_SUNRISE_POINT;
854 } else {
855 if (guess == CHIPSET_100_SERIES_SUNRISE_POINT) {
856 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
857 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
858 "Please report this message, the output of `ich_descriptors_tool` for\n"
859 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
860 return CHIPSET_9_SERIES_WILDCAT_POINT;
861 }
862 }
863
864 return guess;
865}
866
Stefan Taunerb3850962011-12-24 00:00:32 +0000867/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +0100868int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
869 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000870{
Nico Huberfa622942017-03-24 17:25:37 +0100871 size_t i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000872 uint8_t pch_bug_offset = 0;
873
874 if (dump == NULL || desc == NULL)
875 return ICH_RET_PARAM;
876
877 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
878 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
879 pch_bug_offset = 4;
880 else
881 return ICH_RET_ERR;
882 }
883
884 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +0200885 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000886 return ICH_RET_OOB;
887 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
888 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
889 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
890 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
891
892 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +0200893 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000894 return ICH_RET_OOB;
895 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
896 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
897 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
898
Nico Huber67d71792017-06-17 03:10:15 +0200899 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +0100900 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +0200901 prettyprint_ich_chipset(*cs);
902 }
Nico Huberfa622942017-03-24 17:25:37 +0100903
Stefan Taunerb3850962011-12-24 00:00:32 +0000904 /* region */
Nico Huberfa622942017-03-24 17:25:37 +0100905 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
906 if (nr < 0 || len < getFRBA(&desc->content) + nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000907 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +0100908 for (i = 0; i < nr; i++)
909 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000910
911 /* master */
Nico Huberfa622942017-03-24 17:25:37 +0100912 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
913 if (nm < 0 || len < getFMBA(&desc->content) + nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000914 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +0100915 for (i = 0; i < nm; i++)
916 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000917
918 /* upper map */
919 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
920
921 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
922 * "Identifies the 1s based number of DWORDS contained in the VSCC
923 * Table. Each SPI component entry in the table is 2 DWORDS long." So
924 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
925 * check ensures that the maximum offset actually accessed is available.
926 */
Nico Huber9e14aed2017-03-28 17:08:46 +0200927 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +0000928 return ICH_RET_OOB;
929
930 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000931 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
932 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +0000933 }
934
935 /* MCH/PROC (aka. North) straps */
936 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
937 return ICH_RET_OOB;
938
939 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000940 max_count = min(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
941 for (i = 0; i < max_count; i++)
942 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000943
944 /* ICH/PCH (aka. South) straps */
945 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
946 return ICH_RET_OOB;
947
948 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000949 max_count = min(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
950 for (i = 0; i < max_count; i++)
951 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000952
953 return ICH_RET_OK;
954}
955
Nico Huberad186312016-05-02 15:15:29 +0200956#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000957
Stefan Taunerd0c5dc22011-10-20 12:57:14 +0000958/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000959\em idx in bytes or -1 if the correct size can not be determined. */
960int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +0000961{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000962 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000963 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000964 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +0000965 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000966
967 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +0000968 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000969
970 uint8_t size_enc;
971 uint8_t size_max;
972
973 switch (cs) {
974 case CHIPSET_ICH8:
975 case CHIPSET_ICH9:
976 case CHIPSET_ICH10:
977 case CHIPSET_5_SERIES_IBEX_PEAK:
978 case CHIPSET_6_SERIES_COUGAR_POINT:
979 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000980 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000981 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000982 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000983 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000984 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000985 }
986 size_max = 5;
987 break;
988 case CHIPSET_8_SERIES_LYNX_POINT:
989 case CHIPSET_8_SERIES_LYNX_POINT_LP:
990 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000991 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100992 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +0100993 case CHIPSET_100_SERIES_SUNRISE_POINT:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000994 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000995 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000996 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000997 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000998 }
999 size_max = 7;
1000 break;
1001 case CHIPSET_ICH_UNKNOWN:
1002 default:
1003 msg_pwarn("Density encoding is unknown on this chipset.\n");
1004 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001005 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001006
1007 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001008 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001009 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1010 idx, size_enc, size_max);
1011 return -1;
1012 }
1013
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001014 return (1 << (19 + size_enc));
1015}
1016
Nico Huber8d494992017-06-19 12:18:33 +02001017/* Only used by ichspi.c */
1018#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001019static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001020{
1021 uint32_t control = 0;
1022 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1023 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd54e4f42017-03-23 23:45:47 +01001024 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
1025 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1026 return mmio_le_readl(spibar + PCH100_REG_FDOD);
1027 } else {
1028 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1029 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1030 }
1031
Stefan Tauner1e146392011-09-15 23:52:55 +00001032}
1033
Nico Huberd54e4f42017-03-23 23:45:47 +01001034int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001035{
Nico Huberfa622942017-03-24 17:25:37 +01001036 size_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001037 struct ich_desc_region *r = &desc->region;
1038
1039 /* Test if bit-fields are working as expected.
1040 * FIXME: Replace this with dynamic bitfield fixup
1041 */
1042 for (i = 0; i < 4; i++)
1043 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001044 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1045 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1046 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1047 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001048 msg_pdbg("The combination of compiler and CPU architecture used"
1049 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001050 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1051 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1052 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1053 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1054 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1055 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1056 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1057 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001058 return ICH_RET_ERR;
1059 }
1060
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001061 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001062 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001063 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1064 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1065 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1066 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001067
1068 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001069 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1070 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1071 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001072
1073 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001074 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1075 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001076 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001077 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001078 return ICH_RET_ERR;
1079 }
Nico Huberfa622942017-03-24 17:25:37 +01001080 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001081 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001082
1083 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001084 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1085 if (nm < 0) {
1086 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1087 __func__, desc->content.NM + 1);
1088 return ICH_RET_ERR;
1089 }
1090 for (i = 0; i < nm; i++)
1091 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001092
1093 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1094 * reading the upper map is impossible on all chipsets, so don't bother.
1095 */
1096
1097 msg_pdbg2(" done.\n");
1098 return ICH_RET_OK;
1099}
Nico Huber8d494992017-06-19 12:18:33 +02001100#endif
Nico Huber305f4172013-06-14 11:55:26 +02001101
1102/**
1103 * @brief Read a layout from the dump of an Intel ICH descriptor.
1104 *
1105 * @param layout Pointer where to store the layout.
1106 * @param dump The descriptor dump to read from.
1107 * @param len The length of the descriptor dump.
1108 *
1109 * @return 0 on success,
1110 * 1 if the descriptor couldn't be parsed.
1111 */
1112int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1113{
Nico Huberfa622942017-03-24 17:25:37 +01001114 static const char *const regions[] = {
1115 "fd", "bios", "me", "gbe", "pd", "reg5", "reg6", "reg7", "ec", "reg9"
1116 };
Nico Huber305f4172013-06-14 11:55:26 +02001117
1118 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001119 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1120 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001121 return 1;
1122
1123 memset(layout, 0x00, sizeof(*layout));
1124
Nico Huberfa622942017-03-24 17:25:37 +01001125 ssize_t i, j;
1126 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 +02001127 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001128 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001129 if (limit <= base)
1130 continue;
1131 layout->entries[j].start = base;
1132 layout->entries[j].end = limit;
1133 layout->entries[j].included = false;
1134 snprintf(layout->entries[j].name, sizeof(layout->entries[j].name), "%s", regions[i]);
1135 ++j;
1136 }
1137 layout->base.entries = layout->entries;
1138 layout->base.num_entries = j;
1139 return 0;
1140}
1141
Nico Huberad186312016-05-02 15:15:29 +02001142#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */