blob: 791615286717cd0a305c9e1704e92e9fce49de51 [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) {
49 case CHIPSET_100_SERIES_SUNRISE_POINT:
50 return 10;
51 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
52 case CHIPSET_9_SERIES_WILDCAT_POINT:
53 case CHIPSET_8_SERIES_LYNX_POINT_LP:
54 case CHIPSET_8_SERIES_LYNX_POINT:
55 case CHIPSET_8_SERIES_WELLSBURG:
56 if (cont->NR <= 6)
57 return cont->NR + 1;
58 else
59 return -1;
60 default:
61 if (cont->NR <= 4)
62 return cont->NR + 1;
63 else
64 return -1;
65 }
66}
67
68ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont)
69{
70 if (cont->NM < MAX_NUM_MASTERS)
71 return cont->NM + 1;
72 else
73 return -1;
74}
75
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000076void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
Stefan Tauner1e146392011-09-15 23:52:55 +000077{
78 print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF);
79 print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF);
80 print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF);
81 print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +000082 print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF);
83 if (print_vcl)
84 print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF);
85 print(verbosity, "\n");
Stefan Tauner1e146392011-09-15 23:52:55 +000086}
87
88#define getFCBA(cont) (((cont)->FLMAP0 << 4) & 0x00000ff0)
89#define getFRBA(cont) (((cont)->FLMAP0 >> 12) & 0x00000ff0)
90#define getFMBA(cont) (((cont)->FLMAP1 << 4) & 0x00000ff0)
91#define getFISBA(cont) (((cont)->FLMAP1 >> 12) & 0x00000ff0)
92#define getFMSBA(cont) (((cont)->FLMAP2 << 4) & 0x00000ff0)
93
Nico Huber67d71792017-06-17 03:10:15 +020094void prettyprint_ich_chipset(enum ich_chipset cs)
95{
96 static const char *const chipset_names[] = {
97 "Unknown ICH", "ICH8", "ICH9", "ICH10",
98 "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point",
99 "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg",
100 "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point",
101 };
102 if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names))
103 cs = 0;
104 else
105 cs = cs - CHIPSET_ICH8 + 1;
106 msg_pdbg2("Assuming chipset '%s'.\n", chipset_names[cs]);
107}
108
Stefan Tauner1e146392011-09-15 23:52:55 +0000109void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc)
110{
Nico Huberfa622942017-03-24 17:25:37 +0100111 prettyprint_ich_descriptor_content(cs, &desc->content);
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000112 prettyprint_ich_descriptor_component(cs, desc);
Nico Huberfa622942017-03-24 17:25:37 +0100113 prettyprint_ich_descriptor_region(cs, desc);
114 prettyprint_ich_descriptor_master(cs, desc);
Nico Huberad186312016-05-02 15:15:29 +0200115#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000116 if (cs >= CHIPSET_ICH8) {
117 prettyprint_ich_descriptor_upper_map(&desc->upper);
118 prettyprint_ich_descriptor_straps(cs, desc);
119 }
Nico Huberad186312016-05-02 15:15:29 +0200120#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */
Stefan Tauner1e146392011-09-15 23:52:55 +0000121}
122
Nico Huberfa622942017-03-24 17:25:37 +0100123void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont)
Stefan Tauner1e146392011-09-15 23:52:55 +0000124{
125 msg_pdbg2("=== Content Section ===\n");
126 msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG);
127 msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0);
128 msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1);
129 msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2);
130 msg_pdbg2("\n");
131
132 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100133 msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont));
134 msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont));
135 msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1);
136 msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont));
137 msg_pdbg2("ISL (ICH/PCH Strap Length): %5d\n", cont->ISL);
138 msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH Strap Base Address): 0x%03x\n", getFISBA(cont));
139 msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont));
140 msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont));
141 msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL);
142 msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont));
Stefan Tauner1e146392011-09-15 23:52:55 +0000143 msg_pdbg2("\n");
144}
145
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000146static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
147{
148 if (idx > 1) {
149 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
150 return NULL;
151 }
152
153 if (desc->content.NC == 0 && idx > 0)
154 return "unused";
155
156 static const char * const size_str[] = {
157 "512 kB", /* 0000 */
158 "1 MB", /* 0001 */
159 "2 MB", /* 0010 */
160 "4 MB", /* 0011 */
161 "8 MB", /* 0100 */
162 "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */
163 "32 MB", /* 0110 */
164 "64 MB", /* 0111 */
165 };
166
167 switch (cs) {
168 case CHIPSET_ICH8:
169 case CHIPSET_ICH9:
170 case CHIPSET_ICH10:
171 case CHIPSET_5_SERIES_IBEX_PEAK:
172 case CHIPSET_6_SERIES_COUGAR_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000173 case CHIPSET_7_SERIES_PANTHER_POINT:
174 case CHIPSET_BAYTRAIL: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000175 uint8_t size_enc;
176 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000177 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000178 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000179 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000180 }
181 if (size_enc > 5)
182 return "reserved";
183 return size_str[size_enc];
184 }
185 case CHIPSET_8_SERIES_LYNX_POINT:
186 case CHIPSET_8_SERIES_LYNX_POINT_LP:
Duncan Laurie823096e2014-08-20 15:39:38 +0000187 case CHIPSET_8_SERIES_WELLSBURG:
Nico Huber51205912017-03-17 17:59:54 +0100188 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huberfa622942017-03-24 17:25:37 +0100189 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
190 case CHIPSET_100_SERIES_SUNRISE_POINT: {
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000191 uint8_t size_enc;
192 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000193 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000194 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000195 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000196 }
197 if (size_enc > 7)
198 return "reserved";
199 return size_str[size_enc];
200 }
201 case CHIPSET_ICH_UNKNOWN:
202 default:
203 return "unknown";
204 }
205}
206
207static const char *pprint_freq(enum ich_chipset cs, uint8_t value)
Stefan Tauner1e146392011-09-15 23:52:55 +0000208{
Nico Huberfa622942017-03-24 17:25:37 +0100209 static const char *const freq_str[2][8] = { {
Stefan Tauner1e146392011-09-15 23:52:55 +0000210 "20 MHz", /* 000 */
211 "33 MHz", /* 001 */
212 "reserved", /* 010 */
213 "reserved", /* 011 */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000214 "50 MHz", /* 100 */ /* New since Ibex Peak */
Stefan Tauner1e146392011-09-15 23:52:55 +0000215 "reserved", /* 101 */
216 "reserved", /* 110 */
217 "reserved" /* 111 */
Nico Huberfa622942017-03-24 17:25:37 +0100218 }, {
219 "reserved", /* 000 */
220 "reserved", /* 001 */
221 "48 MHz", /* 010 */
222 "reserved", /* 011 */
223 "30 MHz", /* 100 */
224 "reserved", /* 101 */
225 "17 MHz", /* 110 */
226 "reserved" /* 111 */
227 } };
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000228
229 switch (cs) {
230 case CHIPSET_ICH8:
231 case CHIPSET_ICH9:
232 case CHIPSET_ICH10:
233 if (value > 1)
234 return "reserved";
235 case CHIPSET_5_SERIES_IBEX_PEAK:
236 case CHIPSET_6_SERIES_COUGAR_POINT:
237 case CHIPSET_7_SERIES_PANTHER_POINT:
238 case CHIPSET_8_SERIES_LYNX_POINT:
Duncan Laurie4095ed72014-08-20 15:39:32 +0000239 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000240 case CHIPSET_8_SERIES_LYNX_POINT_LP:
241 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000242 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100243 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberfa622942017-03-24 17:25:37 +0100244 return freq_str[0][value];
245 case CHIPSET_100_SERIES_SUNRISE_POINT:
246 return freq_str[1][value];
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000247 case CHIPSET_ICH_UNKNOWN:
248 default:
249 return "unknown";
250 }
251}
252
253void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc)
254{
Stefan Tauner1e146392011-09-15 23:52:55 +0000255
256 msg_pdbg2("=== Component Section ===\n");
257 msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP);
258 msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL );
Nico Huberfa622942017-03-24 17:25:37 +0100259 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT)
260 msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000261 msg_pdbg2("\n");
262
263 msg_pdbg2("--- Details ---\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000264 msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0));
Stefan Tauner1e146392011-09-15 23:52:55 +0000265 if (desc->content.NC)
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000266 msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1));
Stefan Tauner1e146392011-09-15 23:52:55 +0000267 else
268 msg_pdbg2("Component 2 is not used.\n");
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000269 msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.modes.freq_read));
270 msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_read_id));
271 msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.modes.freq_write));
272 msg_pdbg2("Fast Read is %ssupported.\n", desc->component.modes.fastread ? "" : "not ");
273 if (desc->component.modes.fastread)
Stefan Tauner1e146392011-09-15 23:52:55 +0000274 msg_pdbg2("Fast Read Clock Frequency: %s\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000275 pprint_freq(cs, desc->component.modes.freq_fastread));
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000276 if (cs > CHIPSET_6_SERIES_COUGAR_POINT)
277 msg_pdbg2("Dual Output Fast Read Support: %sabled\n",
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000278 desc->component.modes.dual_output ? "dis" : "en");
Nico Huberfa622942017-03-24 17:25:37 +0100279 if (desc->component.FLILL == 0 &&
280 (cs != CHIPSET_100_SERIES_SUNRISE_POINT || desc->component.FLILL1 == 0)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000281 msg_pdbg2("No forbidden opcodes.\n");
Nico Huberfa622942017-03-24 17:25:37 +0100282 } else {
Stefan Tauner1e146392011-09-15 23:52:55 +0000283 msg_pdbg2("Invalid instruction 0: 0x%02x\n",
284 desc->component.invalid_instr0);
285 msg_pdbg2("Invalid instruction 1: 0x%02x\n",
286 desc->component.invalid_instr1);
287 msg_pdbg2("Invalid instruction 2: 0x%02x\n",
288 desc->component.invalid_instr2);
289 msg_pdbg2("Invalid instruction 3: 0x%02x\n",
290 desc->component.invalid_instr3);
Nico Huberfa622942017-03-24 17:25:37 +0100291 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
292 msg_pdbg2("Invalid instruction 4: 0x%02x\n",
293 desc->component.invalid_instr4);
294 msg_pdbg2("Invalid instruction 5: 0x%02x\n",
295 desc->component.invalid_instr5);
296 msg_pdbg2("Invalid instruction 6: 0x%02x\n",
297 desc->component.invalid_instr6);
298 msg_pdbg2("Invalid instruction 7: 0x%02x\n",
299 desc->component.invalid_instr7);
300 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000301 }
302 msg_pdbg2("\n");
303}
304
305static void pprint_freg(const struct ich_desc_region *reg, uint32_t i)
306{
Nico Huberfa622942017-03-24 17:25:37 +0100307 static const char *const region_names[] = {
308 "Descr.", "BIOS", "ME", "GbE", "Platf.", "unknown", "unknown", "unknown",
309 "EC", "unknown",
Stefan Tauner1e146392011-09-15 23:52:55 +0000310 };
Nico Huberfa622942017-03-24 17:25:37 +0100311 if (i >= ARRAY_SIZE(region_names)) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000312 msg_pdbg2("%s: region index too high.\n", __func__);
313 return;
314 }
315 uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]);
316 uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]);
Nico Huberfa622942017-03-24 17:25:37 +0100317 msg_pdbg2("Region %d (%-7s) ", i, region_names[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000318 if (base > limit)
319 msg_pdbg2("is unused.\n");
320 else
Nico Huber0bb3f712017-03-29 16:44:33 +0200321 msg_pdbg2("0x%08x - 0x%08x\n", base, limit);
Stefan Tauner1e146392011-09-15 23:52:55 +0000322}
323
Nico Huberfa622942017-03-24 17:25:37 +0100324void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000325{
Nico Huberfa622942017-03-24 17:25:37 +0100326 size_t i;
327 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000328 msg_pdbg2("=== Region Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100329 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +0000330 msg_pdbg2("%s: number of regions too high (%d).\n", __func__,
Nico Huberfa622942017-03-24 17:25:37 +0100331 desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +0000332 return;
333 }
Nico Huberfa622942017-03-24 17:25:37 +0100334 for (i = 0; i < nr; i++)
335 msg_pdbg2("FLREG%zu 0x%08x\n", i, desc->region.FLREGs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000336 msg_pdbg2("\n");
337
338 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100339 for (i = 0; i < nr; i++)
Stefan Tauner1e146392011-09-15 23:52:55 +0000340 pprint_freg(&desc->region, i);
341 msg_pdbg2("\n");
342}
343
Nico Huberfa622942017-03-24 17:25:37 +0100344void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc)
Stefan Tauner1e146392011-09-15 23:52:55 +0000345{
Nico Huberfa622942017-03-24 17:25:37 +0100346 size_t i;
347 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
Stefan Tauner1e146392011-09-15 23:52:55 +0000348 msg_pdbg2("=== Master Section ===\n");
Nico Huberfa622942017-03-24 17:25:37 +0100349 if (nm < 0) {
350 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
351 desc->content.NM + 1);
352 return;
353 }
354 for (i = 0; i < nm; i++)
355 msg_pdbg2("FLMSTR%zu 0x%08x\n", i + 1, desc->master.FLMSTRs[i]);
Stefan Tauner1e146392011-09-15 23:52:55 +0000356 msg_pdbg2("\n");
357
358 msg_pdbg2("--- Details ---\n");
Nico Huberfa622942017-03-24 17:25:37 +0100359 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
360 const char *const master_names[] = {
361 "BIOS", "ME", "GbE", "unknown", "EC",
362 };
363 if (nm >= ARRAY_SIZE(master_names)) {
364 msg_pdbg2("%s: number of masters too high (%d).\n", __func__,
365 desc->content.NM + 1);
366 return;
367 }
368
369 msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9\n");
370 for (i = 0; i < nm; i++) {
371 size_t j;
372 msg_pdbg2("%-4s", master_names[i]);
373 for (j = 0; j < 10; j++)
374 msg_pdbg2(" %c%c ",
375 desc->master.mstr[i].read & (1 << j) ? 'r' : ' ',
376 desc->master.mstr[i].write & (1 << j) ? 'w' : ' ');
377 msg_pdbg2("\n");
378 }
379 } else {
380 const struct ich_desc_master *const mstr = &desc->master;
381 msg_pdbg2(" Descr. BIOS ME GbE Platf.\n");
382 msg_pdbg2("BIOS %c%c %c%c %c%c %c%c %c%c\n",
383 (mstr->BIOS_descr_r) ?'r':' ', (mstr->BIOS_descr_w) ?'w':' ',
384 (mstr->BIOS_BIOS_r) ?'r':' ', (mstr->BIOS_BIOS_w) ?'w':' ',
385 (mstr->BIOS_ME_r) ?'r':' ', (mstr->BIOS_ME_w) ?'w':' ',
386 (mstr->BIOS_GbE_r) ?'r':' ', (mstr->BIOS_GbE_w) ?'w':' ',
387 (mstr->BIOS_plat_r) ?'r':' ', (mstr->BIOS_plat_w) ?'w':' ');
388 msg_pdbg2("ME %c%c %c%c %c%c %c%c %c%c\n",
389 (mstr->ME_descr_r) ?'r':' ', (mstr->ME_descr_w) ?'w':' ',
390 (mstr->ME_BIOS_r) ?'r':' ', (mstr->ME_BIOS_w) ?'w':' ',
391 (mstr->ME_ME_r) ?'r':' ', (mstr->ME_ME_w) ?'w':' ',
392 (mstr->ME_GbE_r) ?'r':' ', (mstr->ME_GbE_w) ?'w':' ',
393 (mstr->ME_plat_r) ?'r':' ', (mstr->ME_plat_w) ?'w':' ');
394 msg_pdbg2("GbE %c%c %c%c %c%c %c%c %c%c\n",
395 (mstr->GbE_descr_r) ?'r':' ', (mstr->GbE_descr_w) ?'w':' ',
396 (mstr->GbE_BIOS_r) ?'r':' ', (mstr->GbE_BIOS_w) ?'w':' ',
397 (mstr->GbE_ME_r) ?'r':' ', (mstr->GbE_ME_w) ?'w':' ',
398 (mstr->GbE_GbE_r) ?'r':' ', (mstr->GbE_GbE_w) ?'w':' ',
399 (mstr->GbE_plat_r) ?'r':' ', (mstr->GbE_plat_w) ?'w':' ');
400 }
Stefan Tauner1e146392011-09-15 23:52:55 +0000401 msg_pdbg2("\n");
402}
403
Stefan Taunerb3850962011-12-24 00:00:32 +0000404void prettyprint_ich_descriptor_straps_ich8(const struct ich_descriptors *desc)
405{
406 static const char * const str_GPIO12[4] = {
407 "GPIO12",
408 "LAN PHY Power Control Function (Native Output)",
409 "GLAN_DOCK# (Native Input)",
410 "invalid configuration",
411 };
412
413 msg_pdbg2("--- MCH details ---\n");
414 msg_pdbg2("ME B is %sabled.\n", desc->north.ich8.MDB ? "dis" : "en");
415 msg_pdbg2("\n");
416
417 msg_pdbg2("--- ICH details ---\n");
418 msg_pdbg2("ME SMBus Address 1: 0x%02x\n", desc->south.ich8.ASD);
419 msg_pdbg2("ME SMBus Address 2: 0x%02x\n", desc->south.ich8.ASD2);
420 msg_pdbg2("ME SMBus Controller is connected to the %s.\n",
421 desc->south.ich8.MESM2SEL ? "SMLink pins" : "SMBus pins");
422 msg_pdbg2("SPI CS1 is used for %s.\n",
423 desc->south.ich8.SPICS1_LANPHYPC_SEL ?
424 "LAN PHY Power Control Function" :
425 "SPI Chip Select");
426 msg_pdbg2("GPIO12 is used as %s.\n",
427 str_GPIO12[desc->south.ich8.GPIO12_SEL]);
428 msg_pdbg2("PCIe Port 6 is used for %s.\n",
429 desc->south.ich8.GLAN_PCIE_SEL ? "integrated LAN" : "PCI Express");
430 msg_pdbg2("%sn BMC Mode: "
431 "Intel AMT SMBus Controller 1 is connected to %s.\n",
432 desc->south.ich8.BMCMODE ? "I" : "Not i",
433 desc->south.ich8.BMCMODE ? "SMLink" : "SMBus");
434 msg_pdbg2("TCO is in %s Mode.\n",
435 desc->south.ich8.TCOMODE ? "Advanced TCO" : "Legacy/Compatible");
436 msg_pdbg2("ME A is %sabled.\n",
437 desc->south.ich8.ME_DISABLE ? "dis" : "en");
438 msg_pdbg2("\n");
439}
440
441static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t off)
442{
443 msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
444
445 off *= 4;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000446 switch (conf){
Stefan Taunerb3850962011-12-24 00:00:32 +0000447 case 0:
448 msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off);
449 break;
450 case 1:
451 msg_pdbg2("1x2, 2x1 Port %d (x2), Port %d (disabled), "
452 "Ports %d, %d (x1)", 1+off, 2+off, 3+off, 4+off);
453 break;
454 case 2:
455 msg_pdbg2("2x2 Port %d (x2), Port %d (x2), Ports "
456 "%d, %d (disabled)", 1+off, 3+off, 2+off, 4+off);
457 break;
458 case 3:
459 msg_pdbg2("1x4 Port %d (x4), Ports %d-%d (disabled)",
460 1+off, 2+off, 4+off);
461 break;
462 }
463 msg_pdbg2("\n");
464}
465
466void prettyprint_ich_descriptor_pchstraps45678_56(const struct ich_desc_south_strap *s)
467{
468 /* PCHSTRP4 */
469 msg_pdbg2("Intel PHY is %s.\n",
470 (s->ibex.PHYCON == 2) ? "connected" :
471 (s->ibex.PHYCON == 0) ? "disconnected" : "reserved");
472 msg_pdbg2("GbE MAC SMBus address is %sabled.\n",
473 s->ibex.GBEMAC_SMBUS_ADDR_EN ? "en" : "dis");
474 msg_pdbg2("GbE MAC SMBus address: 0x%02x\n",
475 s->ibex.GBEMAC_SMBUS_ADDR);
476 msg_pdbg2("GbE PHY SMBus address: 0x%02x\n",
477 s->ibex.GBEPHY_SMBUS_ADDR);
478
479 /* PCHSTRP5 */
480 /* PCHSTRP6 */
481 /* PCHSTRP7 */
482 msg_pdbg2("Intel ME SMBus Subsystem Vendor ID: 0x%04x\n",
483 s->ibex.MESMA2UDID_VENDOR);
484 msg_pdbg2("Intel ME SMBus Subsystem Device ID: 0x%04x\n",
485 s->ibex.MESMA2UDID_VENDOR);
486
487 /* PCHSTRP8 */
488}
489
490void prettyprint_ich_descriptor_pchstraps111213_56(const struct ich_desc_south_strap *s)
491{
492 /* PCHSTRP11 */
493 msg_pdbg2("SMLink1 GP Address is %sabled.\n",
494 s->ibex.SML1GPAEN ? "en" : "dis");
495 msg_pdbg2("SMLink1 controller General Purpose Target address: 0x%02x\n",
496 s->ibex.SML1GPA);
497 msg_pdbg2("SMLink1 I2C Target address is %sabled.\n",
498 s->ibex.SML1I2CAEN ? "en" : "dis");
499 msg_pdbg2("SMLink1 I2C Target address: 0x%02x\n",
500 s->ibex.SML1I2CA);
501
502 /* PCHSTRP12 */
503 /* PCHSTRP13 */
504}
505
506void prettyprint_ich_descriptor_straps_ibex(const struct ich_desc_south_strap *s)
507{
Stefan Tauner67d163d2013-01-15 17:37:48 +0000508 static const uint8_t dec_t209min[4] = {
Stefan Taunerb3850962011-12-24 00:00:32 +0000509 100,
510 50,
511 5,
512 1
513 };
514
515 msg_pdbg2("--- PCH ---\n");
516
517 /* PCHSTRP0 */
518 msg_pdbg2("Chipset configuration Softstrap 2: %d\n", s->ibex.cs_ss2);
519 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
520 s->ibex.SMB_EN ? "en" : "dis");
521 msg_pdbg2("SMLink0 segment is %sabled.\n",
522 s->ibex.SML0_EN ? "en" : "dis");
523 msg_pdbg2("SMLink1 segment is %sabled.\n",
524 s->ibex.SML1_EN ? "en" : "dis");
525 msg_pdbg2("SMLink1 Frequency: %s\n",
526 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
527 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
528 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
529 msg_pdbg2("SMLink0 Frequency: %s\n",
530 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
531 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
532 "LAN_PHY_PWR_CTRL" : "general purpose output");
533 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->ibex.cs_ss1);
534 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
535 s->ibex.DMI_REQID_DIS ? "en" : "dis");
536 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
537 1 << (6 + s->ibex.BBBS));
538
539 /* PCHSTRP1 */
540 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
541
542 /* PCHSTRP2 */
543 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
544 s->ibex.MESMASDEN ? "en" : "dis");
545 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
546 s->ibex.MESMASDA);
547 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
548 s->ibex.MESMI2CEN ? "en" : "dis");
549 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
550 s->ibex.MESMI2CA);
551
552 /* PCHSTRP3 */
553 prettyprint_ich_descriptor_pchstraps45678_56(s);
554 /* PCHSTRP9 */
555 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
556 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
557 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
558 s->ibex.PCIELR1 ? "" : "not ");
559 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
560 s->ibex.PCIELR2 ? "" : "not ");
561 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
562 s->ibex.DMILR ? "" : "not ");
563 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
564 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
565 s->ibex.PHY_PCIE_EN ? "en" : "dis");
566
567 /* PCHSTRP10 */
568 msg_pdbg2("Management Engine will boot from %sflash.\n",
569 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
570 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->ibex.cs_ss5);
571 msg_pdbg2("Virtualization Engine Enable 1 is %sabled.\n",
572 s->ibex.VE_EN ? "en" : "dis");
573 msg_pdbg2("ME Memory-attached Debug Display Device is %sabled.\n",
574 s->ibex.MMDDE ? "en" : "dis");
575 msg_pdbg2("ME Memory-attached Debug Display Device address: 0x%02x\n",
576 s->ibex.MMADDR);
577 msg_pdbg2("Chipset configuration Softstrap 7: %d\n", s->ibex.cs_ss7);
578 msg_pdbg2("Integrated Clocking Configuration is %d.\n",
579 (s->ibex.ICC_SEL == 7) ? 0 : s->ibex.ICC_SEL);
580 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a "
581 "reset.\n", s->ibex.MER_CL1 ? "" : "not ");
582
583 prettyprint_ich_descriptor_pchstraps111213_56(s);
584
585 /* PCHSTRP14 */
586 msg_pdbg2("Virtualization Engine Enable 2 is %sabled.\n",
587 s->ibex.VE_EN2 ? "en" : "dis");
588 msg_pdbg2("Virtualization Engine will boot from %sflash.\n",
589 s->ibex.VE_BOOT_FLASH ? "" : "ROM, then ");
590 msg_pdbg2("Braidwood SSD functionality is %sabled.\n",
591 s->ibex.BW_SSD ? "en" : "dis");
592 msg_pdbg2("Braidwood NVMHCI functionality is %sabled.\n",
593 s->ibex.NVMHCI_EN ? "en" : "dis");
594
595 /* PCHSTRP15 */
596 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->ibex.cs_ss6);
597 msg_pdbg2("Integrated wired LAN Solution is %sabled.\n",
598 s->ibex.IWL_EN ? "en" : "dis");
599 msg_pdbg2("t209 min Timing: %d ms\n",
600 dec_t209min[s->ibex.t209min]);
601 msg_pdbg2("\n");
602}
603
604void prettyprint_ich_descriptor_straps_cougar(const struct ich_desc_south_strap *s)
605{
606 msg_pdbg2("--- PCH ---\n");
607
608 /* PCHSTRP0 */
609 msg_pdbg2("Chipset configuration Softstrap 1: %d\n", s->cougar.cs_ss1);
610 msg_pdbg2("Intel ME SMBus Select is %sabled.\n",
611 s->ibex.SMB_EN ? "en" : "dis");
612 msg_pdbg2("SMLink0 segment is %sabled.\n",
613 s->ibex.SML0_EN ? "en" : "dis");
614 msg_pdbg2("SMLink1 segment is %sabled.\n",
615 s->ibex.SML1_EN ? "en" : "dis");
616 msg_pdbg2("SMLink1 Frequency: %s\n",
617 (s->ibex.SML1FRQ == 1) ? "100 kHz" : "reserved");
618 msg_pdbg2("Intel ME SMBus Frequency: %s\n",
619 (s->ibex.SMB0FRQ == 1) ? "100 kHz" : "reserved");
620 msg_pdbg2("SMLink0 Frequency: %s\n",
621 (s->ibex.SML0FRQ == 1) ? "100 kHz" : "reserved");
622 msg_pdbg2("GPIO12 is used as %s.\n", s->ibex.LANPHYPC_GP12_SEL ?
623 "LAN_PHY_PWR_CTRL" : "general purpose output");
624 msg_pdbg2("LinkSec is %sabled.\n",
625 s->cougar.LINKSEC_DIS ? "en" : "dis");
626 msg_pdbg2("DMI RequesterID Checks are %sabled.\n",
627 s->ibex.DMI_REQID_DIS ? "en" : "dis");
628 msg_pdbg2("BIOS Boot-Block size (BBBS): %d kB.\n",
629 1 << (6 + s->ibex.BBBS));
630
631 /* PCHSTRP1 */
632 msg_pdbg2("Chipset configuration Softstrap 3: 0x%x\n", s->ibex.cs_ss3);
633 msg_pdbg2("Chipset configuration Softstrap 2: 0x%x\n", s->ibex.cs_ss2);
634
635 /* PCHSTRP2 */
636 msg_pdbg2("ME SMBus ASD address is %sabled.\n",
637 s->ibex.MESMASDEN ? "en" : "dis");
638 msg_pdbg2("ME SMBus Controller ASD Target address: 0x%02x\n",
639 s->ibex.MESMASDA);
640 msg_pdbg2("ME SMBus MCTP Address is %sabled.\n",
641 s->cougar.MESMMCTPAEN ? "en" : "dis");
642 msg_pdbg2("ME SMBus MCTP target address: 0x%02x\n",
643 s->cougar.MESMMCTPA);
644 msg_pdbg2("ME SMBus I2C address is %sabled.\n",
645 s->ibex.MESMI2CEN ? "en" : "dis");
646 msg_pdbg2("ME SMBus I2C target address: 0x%02x\n",
647 s->ibex.MESMI2CA);
648
649 /* PCHSTRP3 */
650 prettyprint_ich_descriptor_pchstraps45678_56(s);
651 /* PCHSTRP9 */
652 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 0);
653 prettyprint_ich_descriptor_straps_56_pciecs(s->ibex.PCIEPCS1, 1);
654 msg_pdbg2("PCIe Lane Reversal 1: PCIe Lanes 0-3 are %sreserved.\n",
655 s->ibex.PCIELR1 ? "" : "not ");
656 msg_pdbg2("PCIe Lane Reversal 2: PCIe Lanes 4-7 are %sreserved.\n",
657 s->ibex.PCIELR2 ? "" : "not ");
658 msg_pdbg2("DMI Lane Reversal: DMI Lanes 0-3 are %sreserved.\n",
659 s->ibex.DMILR ? "" : "not ");
660 msg_pdbg2("ME Debug status writes over SMBUS are %sabled.\n",
661 s->cougar.MDSMBE_EN ? "en" : "dis");
662 msg_pdbg2("ME Debug SMBus Emergency Mode address: 0x%02x (raw)\n",
663 s->cougar.MDSMBE_ADD);
664 msg_pdbg2("Default PHY PCIe Port is %d.\n", s->ibex.PHY_PCIEPORTSEL+1);
665 msg_pdbg2("Integrated MAC/PHY communication over PCIe is %sabled.\n",
666 s->ibex.PHY_PCIE_EN ? "en" : "dis");
667 msg_pdbg2("PCIe ports Subtractive Decode Agent is %sabled.\n",
668 s->cougar.SUB_DECODE_EN ? "en" : "dis");
669 msg_pdbg2("GPIO74 is used as %s.\n", s->cougar.PCHHOT_SML1ALERT_SEL ?
670 "PCHHOT#" : "SML1ALERT#");
671
672 /* PCHSTRP10 */
673 msg_pdbg2("Management Engine will boot from %sflash.\n",
674 s->ibex.ME_BOOT_FLASH ? "" : "ROM, then ");
675
676 msg_pdbg2("ME Debug SMBus Emergency Mode is %sabled.\n",
677 s->cougar.MDSMBE_EN ? "en" : "dis");
678 msg_pdbg2("ME Debug SMBus Emergency Mode Address: 0x%02x\n",
679 s->cougar.MDSMBE_ADD);
680
681 msg_pdbg2("Integrated Clocking Configuration used: %d\n",
682 s->cougar.ICC_SEL);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000683 msg_pdbg2("PCH Signal CL_RST1# does %sassert when Intel ME performs a reset.\n",
684 s->ibex.MER_CL1 ? "" : "not ");
Stefan Taunerb3850962011-12-24 00:00:32 +0000685 msg_pdbg2("ICC Profile is selected by %s.\n",
686 s->cougar.ICC_PRO_SEL ? "Softstraps" : "BIOS");
687 msg_pdbg2("Deep SX is %ssupported on the platform.\n",
688 s->cougar.Deep_SX_EN ? "not " : "");
689 msg_pdbg2("ME Debug LAN Emergency Mode is %sabled.\n",
690 s->cougar.ME_DBG_LAN ? "en" : "dis");
691
692 prettyprint_ich_descriptor_pchstraps111213_56(s);
693
694 /* PCHSTRP14 */
695 /* PCHSTRP15 */
696 msg_pdbg2("Chipset configuration Softstrap 6: %d\n", s->cougar.cs_ss6);
697 msg_pdbg2("Integrated wired LAN is %sabled.\n",
698 s->cougar.IWL_EN ? "en" : "dis");
699 msg_pdbg2("Chipset configuration Softstrap 5: %d\n", s->cougar.cs_ss5);
700 msg_pdbg2("SMLink1 provides temperature from %s.\n",
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000701 s->cougar.SMLINK1_THERM_SEL ? "PCH only" : "the CPU, PCH and DIMMs");
Stefan Taunerb3850962011-12-24 00:00:32 +0000702 msg_pdbg2("GPIO29 is used as %s.\n", s->cougar.SLP_LAN_GP29_SEL ?
703 "general purpose output" : "SLP_LAN#");
704
705 /* PCHSTRP16 */
706 /* PCHSTRP17 */
707 msg_pdbg2("Integrated Clock: %s Clock Mode\n",
708 s->cougar.ICML ? "Buffered Through" : "Full Integrated");
709 msg_pdbg2("\n");
710}
711
712void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_descriptors *desc)
713{
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000714 unsigned int i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000715 msg_pdbg2("=== Softstraps ===\n");
716
Nico Huberd7c75522017-03-29 16:31:49 +0200717 max_count = min(ARRAY_SIZE(desc->north.STRPs), desc->content.MSL);
718 if (max_count < desc->content.MSL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000719 msg_pdbg2("MSL (%u) is greater than the current maximum of %u entries.\n",
Nico Huberd7c75522017-03-29 16:31:49 +0200720 desc->content.MSL, max_count);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000721 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200722 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000723
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000724 msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count);
725 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000726 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]);
727 msg_pdbg2("\n");
728
Nico Huberd7c75522017-03-29 16:31:49 +0200729 max_count = min(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL);
730 if (max_count < desc->content.ISL) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000731 msg_pdbg2("ISL (%u) is greater than the current maximum of %u entries.\n",
732 desc->content.ISL, max_count);
733 msg_pdbg2("Only the first %u entries will be printed.\n", max_count);
Nico Huberd7c75522017-03-29 16:31:49 +0200734 }
Stefan Taunerb3850962011-12-24 00:00:32 +0000735
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000736 msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count);
737 for (i = 0; i < max_count; i++)
Stefan Taunerb3850962011-12-24 00:00:32 +0000738 msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]);
739 msg_pdbg2("\n");
740
741 switch (cs) {
742 case CHIPSET_ICH8:
743 if (sizeof(desc->north.ich8) / 4 != desc->content.MSL)
744 msg_pdbg2("Detailed North/MCH/PROC information is "
745 "probably not reliable, printing anyway.\n");
746 if (sizeof(desc->south.ich8) / 4 != desc->content.ISL)
747 msg_pdbg2("Detailed South/ICH/PCH information is "
748 "probably not reliable, printing anyway.\n");
749 prettyprint_ich_descriptor_straps_ich8(desc);
750 break;
751 case CHIPSET_5_SERIES_IBEX_PEAK:
752 /* PCH straps only. PROCSTRPs are unknown. */
753 if (sizeof(desc->south.ibex) / 4 != desc->content.ISL)
754 msg_pdbg2("Detailed South/ICH/PCH information is "
755 "probably not reliable, printing anyway.\n");
756 prettyprint_ich_descriptor_straps_ibex(&desc->south);
757 break;
758 case CHIPSET_6_SERIES_COUGAR_POINT:
759 /* PCH straps only. PROCSTRP0 is "reserved". */
760 if (sizeof(desc->south.cougar) / 4 != desc->content.ISL)
761 msg_pdbg2("Detailed South/ICH/PCH information is "
762 "probably not reliable, printing anyway.\n");
763 prettyprint_ich_descriptor_straps_cougar(&desc->south);
764 break;
765 case CHIPSET_ICH_UNKNOWN:
766 break;
767 default:
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000768 msg_pdbg2("The meaning of the descriptor straps are unknown yet.\n\n");
Stefan Taunerb3850962011-12-24 00:00:32 +0000769 break;
770 }
771}
772
773void prettyprint_rdid(uint32_t reg_val)
774{
775 uint8_t mid = reg_val & 0xFF;
776 uint16_t did = ((reg_val >> 16) & 0xFF) | (reg_val & 0xFF00);
777 msg_pdbg2("Manufacturer ID 0x%02x, Device ID 0x%04x\n", mid, did);
778}
779
780void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap)
781{
782 int i;
783 msg_pdbg2("=== Upper Map Section ===\n");
784 msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1);
785 msg_pdbg2("\n");
786
787 msg_pdbg2("--- Details ---\n");
788 msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL);
789 msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap));
790 msg_pdbg2("\n");
791
792 msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2);
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000793 for (i = 0; i < umap->VTL/2; i++) {
Stefan Taunerb3850962011-12-24 00:00:32 +0000794 uint32_t jid = umap->vscc_table[i].JID;
795 uint32_t vscc = umap->vscc_table[i].VSCC;
796 msg_pdbg2(" JID%d = 0x%08x\n", i, jid);
797 msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc);
798 msg_pdbg2(" "); /* indention */
799 prettyprint_rdid(jid);
800 msg_pdbg2(" "); /* indention */
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000801 prettyprint_ich_reg_vscc(vscc, 0, false);
Stefan Taunerb3850962011-12-24 00:00:32 +0000802 }
803 msg_pdbg2("\n");
804}
805
Nico Huber1dc3d422017-06-17 00:09:31 +0200806/*
807 * Guesses a minimum chipset version based on the maximum number of
808 * soft straps per generation.
809 */
810static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_content *const content)
811{
812 if (content->ICCRIBA == 0x00) {
813 if (content->MSL == 0 && content->ISL <= 2)
814 return CHIPSET_ICH8;
815 else if (content->ISL <= 2)
816 return CHIPSET_ICH9;
817 else if (content->ISL <= 10)
818 return CHIPSET_ICH10;
819 else if (content->ISL <= 16)
820 return CHIPSET_5_SERIES_IBEX_PEAK;
821 msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n");
822 return CHIPSET_5_SERIES_IBEX_PEAK;
823 } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) {
824 if (content->MSL == 0 && content->ISL <= 17)
825 return CHIPSET_BAYTRAIL;
826 else if (content->MSL <= 1 && content->ISL <= 18)
827 return CHIPSET_6_SERIES_COUGAR_POINT;
828 else if (content->MSL <= 1 && content->ISL <= 21)
829 return CHIPSET_8_SERIES_LYNX_POINT;
830 msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n");
831 return CHIPSET_9_SERIES_WILDCAT_POINT;
832 } else {
833 return CHIPSET_100_SERIES_SUNRISE_POINT;
834 }
835}
836
837/*
838 * As an additional measure, we check the read frequency like `ifdtool`.
839 * The frequency value 6 (17MHz) was reserved before Skylake and is the
840 * only valid value since. Skylake is currently the most important dis-
841 * tinction because of the dropped number of regions field (NR).
842 */
Nico Huberfa622942017-03-24 17:25:37 +0100843static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const content,
844 const struct ich_desc_component *const component)
Nico Huber1dc3d422017-06-17 00:09:31 +0200845{
846 const enum ich_chipset guess = guess_ich_chipset_from_content(content);
847
848 if (component->modes.freq_read == 6) {
849 if (guess != CHIPSET_100_SERIES_SUNRISE_POINT)
850 msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n"
851 "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n"
852 "Please report this message, the output of `ich_descriptors_tool` for\n"
853 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
854 return CHIPSET_100_SERIES_SUNRISE_POINT;
855 } else {
856 if (guess == CHIPSET_100_SERIES_SUNRISE_POINT) {
857 msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n"
858 "However, the read frequency isn't set to 17MHz (the only valid value).\n"
859 "Please report this message, the output of `ich_descriptors_tool` for\n"
860 "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n");
861 return CHIPSET_9_SERIES_WILDCAT_POINT;
862 }
863 }
864
865 return guess;
866}
867
Stefan Taunerb3850962011-12-24 00:00:32 +0000868/* len is the length of dump in bytes */
Nico Huberfa622942017-03-24 17:25:37 +0100869int read_ich_descriptors_from_dump(const uint32_t *const dump, const size_t len,
870 enum ich_chipset *const cs, struct ich_descriptors *const desc)
Stefan Taunerb3850962011-12-24 00:00:32 +0000871{
Nico Huberfa622942017-03-24 17:25:37 +0100872 size_t i, max_count;
Stefan Taunerb3850962011-12-24 00:00:32 +0000873 uint8_t pch_bug_offset = 0;
874
875 if (dump == NULL || desc == NULL)
876 return ICH_RET_PARAM;
877
878 if (dump[0] != DESCRIPTOR_MODE_SIGNATURE) {
879 if (dump[4] == DESCRIPTOR_MODE_SIGNATURE)
880 pch_bug_offset = 4;
881 else
882 return ICH_RET_ERR;
883 }
884
885 /* map */
Nico Huber9e14aed2017-03-28 17:08:46 +0200886 if (len < (4 + pch_bug_offset) * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000887 return ICH_RET_OOB;
888 desc->content.FLVALSIG = dump[0 + pch_bug_offset];
889 desc->content.FLMAP0 = dump[1 + pch_bug_offset];
890 desc->content.FLMAP1 = dump[2 + pch_bug_offset];
891 desc->content.FLMAP2 = dump[3 + pch_bug_offset];
892
893 /* component */
Nico Huber9e14aed2017-03-28 17:08:46 +0200894 if (len < getFCBA(&desc->content) + 3 * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000895 return ICH_RET_OOB;
896 desc->component.FLCOMP = dump[(getFCBA(&desc->content) >> 2) + 0];
897 desc->component.FLILL = dump[(getFCBA(&desc->content) >> 2) + 1];
898 desc->component.FLPB = dump[(getFCBA(&desc->content) >> 2) + 2];
899
Nico Huber67d71792017-06-17 03:10:15 +0200900 if (*cs == CHIPSET_ICH_UNKNOWN) {
Nico Huberfa622942017-03-24 17:25:37 +0100901 *cs = guess_ich_chipset(&desc->content, &desc->component);
Nico Huber67d71792017-06-17 03:10:15 +0200902 prettyprint_ich_chipset(*cs);
903 }
Nico Huberfa622942017-03-24 17:25:37 +0100904
Stefan Taunerb3850962011-12-24 00:00:32 +0000905 /* region */
Nico Huberfa622942017-03-24 17:25:37 +0100906 const ssize_t nr = ich_number_of_regions(*cs, &desc->content);
907 if (nr < 0 || len < getFRBA(&desc->content) + nr * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000908 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +0100909 for (i = 0; i < nr; i++)
910 desc->region.FLREGs[i] = dump[(getFRBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000911
912 /* master */
Nico Huberfa622942017-03-24 17:25:37 +0100913 const ssize_t nm = ich_number_of_masters(*cs, &desc->content);
914 if (nm < 0 || len < getFMBA(&desc->content) + nm * 4)
Stefan Taunerb3850962011-12-24 00:00:32 +0000915 return ICH_RET_OOB;
Nico Huberfa622942017-03-24 17:25:37 +0100916 for (i = 0; i < nm; i++)
917 desc->master.FLMSTRs[i] = dump[(getFMBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000918
919 /* upper map */
920 desc->upper.FLUMAP1 = dump[(UPPER_MAP_OFFSET >> 2) + 0];
921
922 /* VTL is 8 bits long. Quote from the Ibex Peak SPI programming guide:
923 * "Identifies the 1s based number of DWORDS contained in the VSCC
924 * Table. Each SPI component entry in the table is 2 DWORDS long." So
925 * the maximum of 255 gives us 127.5 SPI components(!?) 8 bytes each. A
926 * check ensures that the maximum offset actually accessed is available.
927 */
Nico Huber9e14aed2017-03-28 17:08:46 +0200928 if (len < getVTBA(&desc->upper) + (desc->upper.VTL / 2 * 8))
Stefan Taunerb3850962011-12-24 00:00:32 +0000929 return ICH_RET_OOB;
930
931 for (i = 0; i < desc->upper.VTL/2; i++) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000932 desc->upper.vscc_table[i].JID = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 0];
933 desc->upper.vscc_table[i].VSCC = dump[(getVTBA(&desc->upper) >> 2) + i * 2 + 1];
Stefan Taunerb3850962011-12-24 00:00:32 +0000934 }
935
936 /* MCH/PROC (aka. North) straps */
937 if (len < getFMSBA(&desc->content) + desc->content.MSL * 4)
938 return ICH_RET_OOB;
939
940 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000941 max_count = min(sizeof(desc->north.STRPs) / 4, desc->content.MSL);
942 for (i = 0; i < max_count; i++)
943 desc->north.STRPs[i] = dump[(getFMSBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000944
945 /* ICH/PCH (aka. South) straps */
946 if (len < getFISBA(&desc->content) + desc->content.ISL * 4)
947 return ICH_RET_OOB;
948
949 /* limit the range to be written */
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000950 max_count = min(sizeof(desc->south.STRPs) / 4, desc->content.ISL);
951 for (i = 0; i < max_count; i++)
952 desc->south.STRPs[i] = dump[(getFISBA(&desc->content) >> 2) + i];
Stefan Taunerb3850962011-12-24 00:00:32 +0000953
954 return ICH_RET_OK;
955}
956
Nico Huberad186312016-05-02 15:15:29 +0200957#ifndef ICH_DESCRIPTORS_FROM_DUMP_ONLY
Stefan Taunerb3850962011-12-24 00:00:32 +0000958
Stefan Taunerd0c5dc22011-10-20 12:57:14 +0000959/** Returns the integer representation of the component density with index
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000960\em idx in bytes or -1 if the correct size can not be determined. */
961int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +0000962{
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000963 if (idx > 1) {
Stefan Taunera1a14ec2012-08-13 08:45:13 +0000964 msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n");
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000965 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +0000966 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000967
968 if (desc->content.NC == 0 && idx > 0)
Stefan Taunerd0c5dc22011-10-20 12:57:14 +0000969 return 0;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000970
971 uint8_t size_enc;
972 uint8_t size_max;
973
974 switch (cs) {
975 case CHIPSET_ICH8:
976 case CHIPSET_ICH9:
977 case CHIPSET_ICH10:
978 case CHIPSET_5_SERIES_IBEX_PEAK:
979 case CHIPSET_6_SERIES_COUGAR_POINT:
980 case CHIPSET_7_SERIES_PANTHER_POINT:
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000981 case CHIPSET_BAYTRAIL:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000982 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000983 size_enc = desc->component.dens_old.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000984 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000985 size_enc = desc->component.dens_old.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000986 }
987 size_max = 5;
988 break;
989 case CHIPSET_8_SERIES_LYNX_POINT:
990 case CHIPSET_8_SERIES_LYNX_POINT_LP:
991 case CHIPSET_8_SERIES_WELLSBURG:
Duncan Laurie823096e2014-08-20 15:39:38 +0000992 case CHIPSET_9_SERIES_WILDCAT_POINT:
Nico Huber51205912017-03-17 17:59:54 +0100993 case CHIPSET_9_SERIES_WILDCAT_POINT_LP:
Nico Huberd54e4f42017-03-23 23:45:47 +0100994 case CHIPSET_100_SERIES_SUNRISE_POINT:
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000995 if (idx == 0) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000996 size_enc = desc->component.dens_new.comp1_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000997 } else {
Tai-Hong Wu60dead42015-01-05 23:00:14 +0000998 size_enc = desc->component.dens_new.comp2_density;
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +0000999 }
1000 size_max = 7;
1001 break;
1002 case CHIPSET_ICH_UNKNOWN:
1003 default:
1004 msg_pwarn("Density encoding is unknown on this chipset.\n");
1005 return -1;
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001006 }
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001007
1008 if (size_enc > size_max) {
Tai-Hong Wu60dead42015-01-05 23:00:14 +00001009 msg_perr("Density of ICH SPI component with index %d is invalid.\n"
Stefan Tauner2ba9f6e2014-08-20 15:39:19 +00001010 "Encoded density is 0x%x while maximum allowed is 0x%x.\n",
1011 idx, size_enc, size_max);
1012 return -1;
1013 }
1014
Stefan Taunerd0c5dc22011-10-20 12:57:14 +00001015 return (1 << (19 + size_enc));
1016}
1017
Nico Huber8d494992017-06-19 12:18:33 +02001018/* Only used by ichspi.c */
1019#if CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))
Nico Huberd54e4f42017-03-23 23:45:47 +01001020static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16_t offset, void *spibar)
Stefan Tauner1e146392011-09-15 23:52:55 +00001021{
1022 uint32_t control = 0;
1023 control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS;
1024 control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI;
Nico Huberd54e4f42017-03-23 23:45:47 +01001025 if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) {
1026 mmio_le_writel(control, spibar + PCH100_REG_FDOC);
1027 return mmio_le_readl(spibar + PCH100_REG_FDOD);
1028 } else {
1029 mmio_le_writel(control, spibar + ICH9_REG_FDOC);
1030 return mmio_le_readl(spibar + ICH9_REG_FDOD);
1031 }
1032
Stefan Tauner1e146392011-09-15 23:52:55 +00001033}
1034
Nico Huberd54e4f42017-03-23 23:45:47 +01001035int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc)
Stefan Tauner1e146392011-09-15 23:52:55 +00001036{
Nico Huberfa622942017-03-24 17:25:37 +01001037 size_t i;
Stefan Tauner1e146392011-09-15 23:52:55 +00001038 struct ich_desc_region *r = &desc->region;
1039
1040 /* Test if bit-fields are working as expected.
1041 * FIXME: Replace this with dynamic bitfield fixup
1042 */
1043 for (i = 0; i < 4; i++)
1044 desc->region.FLREGs[i] = 0x5A << (i * 8);
Nico Huberfa622942017-03-24 17:25:37 +01001045 if (r->old_reg[0].base != 0x005A || r->old_reg[0].limit != 0x0000 ||
1046 r->old_reg[1].base != 0x1A00 || r->old_reg[1].limit != 0x0000 ||
1047 r->old_reg[2].base != 0x0000 || r->old_reg[2].limit != 0x005A ||
1048 r->old_reg[3].base != 0x0000 || r->old_reg[3].limit != 0x1A00) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001049 msg_pdbg("The combination of compiler and CPU architecture used"
1050 "does not lay out bit-fields as expected, sorry.\n");
Nico Huberfa622942017-03-24 17:25:37 +01001051 msg_pspew("r->old_reg[0].base = 0x%04X (0x005A)\n", r->old_reg[0].base);
1052 msg_pspew("r->old_reg[0].limit = 0x%04X (0x0000)\n", r->old_reg[0].limit);
1053 msg_pspew("r->old_reg[1].base = 0x%04X (0x1A00)\n", r->old_reg[1].base);
1054 msg_pspew("r->old_reg[1].limit = 0x%04X (0x0000)\n", r->old_reg[1].limit);
1055 msg_pspew("r->old_reg[2].base = 0x%04X (0x0000)\n", r->old_reg[2].base);
1056 msg_pspew("r->old_reg[2].limit = 0x%04X (0x005A)\n", r->old_reg[2].limit);
1057 msg_pspew("r->old_reg[3].base = 0x%04X (0x0000)\n", r->old_reg[3].base);
1058 msg_pspew("r->old_reg[3].limit = 0x%04X (0x1A00)\n", r->old_reg[3].limit);
Stefan Tauner1e146392011-09-15 23:52:55 +00001059 return ICH_RET_ERR;
1060 }
1061
Stefan Taunera1a14ec2012-08-13 08:45:13 +00001062 msg_pdbg2("Reading flash descriptors mapped by the chipset via FDOC/FDOD...");
Stefan Tauner1e146392011-09-15 23:52:55 +00001063 /* content section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001064 desc->content.FLVALSIG = read_descriptor_reg(cs, 0, 0, spibar);
1065 desc->content.FLMAP0 = read_descriptor_reg(cs, 0, 1, spibar);
1066 desc->content.FLMAP1 = read_descriptor_reg(cs, 0, 2, spibar);
1067 desc->content.FLMAP2 = read_descriptor_reg(cs, 0, 3, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001068
1069 /* component section */
Nico Huberd54e4f42017-03-23 23:45:47 +01001070 desc->component.FLCOMP = read_descriptor_reg(cs, 1, 0, spibar);
1071 desc->component.FLILL = read_descriptor_reg(cs, 1, 1, spibar);
1072 desc->component.FLPB = read_descriptor_reg(cs, 1, 2, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001073
1074 /* region section */
Nico Huberfa622942017-03-24 17:25:37 +01001075 const ssize_t nr = ich_number_of_regions(cs, &desc->content);
1076 if (nr < 0) {
Stefan Tauner1e146392011-09-15 23:52:55 +00001077 msg_pdbg2("%s: number of regions too high (%d) - failed\n",
Nico Huberfa622942017-03-24 17:25:37 +01001078 __func__, desc->content.NR + 1);
Stefan Tauner1e146392011-09-15 23:52:55 +00001079 return ICH_RET_ERR;
1080 }
Nico Huberfa622942017-03-24 17:25:37 +01001081 for (i = 0; i < nr; i++)
Nico Huberd54e4f42017-03-23 23:45:47 +01001082 desc->region.FLREGs[i] = read_descriptor_reg(cs, 2, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001083
1084 /* master section */
Nico Huberfa622942017-03-24 17:25:37 +01001085 const ssize_t nm = ich_number_of_masters(cs, &desc->content);
1086 if (nm < 0) {
1087 msg_pdbg2("%s: number of masters too high (%d) - failed\n",
1088 __func__, desc->content.NM + 1);
1089 return ICH_RET_ERR;
1090 }
1091 for (i = 0; i < nm; i++)
1092 desc->master.FLMSTRs[i] = read_descriptor_reg(cs, 3, i, spibar);
Stefan Tauner1e146392011-09-15 23:52:55 +00001093
1094 /* Accessing the strap section via FDOC/D is only possible on ICH8 and
1095 * reading the upper map is impossible on all chipsets, so don't bother.
1096 */
1097
1098 msg_pdbg2(" done.\n");
1099 return ICH_RET_OK;
1100}
Nico Huber8d494992017-06-19 12:18:33 +02001101#endif
Nico Huber305f4172013-06-14 11:55:26 +02001102
1103/**
1104 * @brief Read a layout from the dump of an Intel ICH descriptor.
1105 *
1106 * @param layout Pointer where to store the layout.
1107 * @param dump The descriptor dump to read from.
1108 * @param len The length of the descriptor dump.
1109 *
1110 * @return 0 on success,
1111 * 1 if the descriptor couldn't be parsed.
1112 */
1113int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
1114{
Nico Huberfa622942017-03-24 17:25:37 +01001115 static const char *const regions[] = {
1116 "fd", "bios", "me", "gbe", "pd", "reg5", "reg6", "reg7", "ec", "reg9"
1117 };
Nico Huber305f4172013-06-14 11:55:26 +02001118
1119 struct ich_descriptors desc;
Nico Huberfa622942017-03-24 17:25:37 +01001120 enum ich_chipset cs = CHIPSET_ICH_UNKNOWN;
1121 if (read_ich_descriptors_from_dump(dump, len, &cs, &desc))
Nico Huber305f4172013-06-14 11:55:26 +02001122 return 1;
1123
1124 memset(layout, 0x00, sizeof(*layout));
1125
Nico Huberfa622942017-03-24 17:25:37 +01001126 ssize_t i, j;
1127 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 +02001128 const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
Nico Huber0bb3f712017-03-29 16:44:33 +02001129 const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]);
Nico Huber305f4172013-06-14 11:55:26 +02001130 if (limit <= base)
1131 continue;
1132 layout->entries[j].start = base;
1133 layout->entries[j].end = limit;
1134 layout->entries[j].included = false;
1135 snprintf(layout->entries[j].name, sizeof(layout->entries[j].name), "%s", regions[i]);
1136 ++j;
1137 }
1138 layout->base.entries = layout->entries;
1139 layout->base.num_entries = j;
1140 return 0;
1141}
1142
Nico Huberad186312016-05-02 15:15:29 +02001143#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */