blob: 3e248e19c328a57a55fd66e4ef84c82893923756 [file] [log] [blame]
Vadim Bendebury864ec8c2014-07-31 21:02:57 -07001/*
2 * This file is part of the libpayload project.
3 *
4 * Copyright (C) 2008 Advanced Micro Devices, Inc.
5 * Copyright (C) 2009 coresystems GmbH
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <libpayload-config.h>
32#include <libpayload.h>
33#include <coreboot_tables.h>
34#include <stdint.h>
35
36/*
37 * The code in this file applies to all coreboot architectures. Some coreboot
38 * table tags are architecture specific, they are handled by their respective
39 * cb_parse_arch_specific() functions.
40 */
41
42/* === Parsing code === */
43/* This is the generic parsing code. */
44
45static void cb_parse_memory(void *ptr, struct sysinfo_t *info)
46{
47 struct cb_memory *mem = ptr;
48 int count = MEM_RANGE_COUNT(mem);
49 int i;
50
51 if (count > SYSINFO_MAX_MEM_RANGES)
52 count = SYSINFO_MAX_MEM_RANGES;
53
54 info->n_memranges = 0;
55
56 for (i = 0; i < count; i++) {
57 struct cb_memory_range *range = MEM_RANGE_PTR(mem, i);
58
Stefan Reinauer1b4d3942015-06-29 15:47:34 -070059#if IS_ENABLED(CONFIG_LP_MEMMAP_RAM_ONLY)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -070060 if (range->type != CB_MEM_RAM)
61 continue;
62#endif
63
64 info->memrange[info->n_memranges].base =
65 cb_unpack64(range->start);
66
67 info->memrange[info->n_memranges].size =
68 cb_unpack64(range->size);
69
70 info->memrange[info->n_memranges].type = range->type;
71
72 info->n_memranges++;
73 }
74}
75
76static void cb_parse_serial(void *ptr, struct sysinfo_t *info)
77{
78 info->serial = ((struct cb_serial *)ptr);
79}
80
Stefan Reinauer1b4d3942015-06-29 15:47:34 -070081#if IS_ENABLED(CONFIG_LP_CHROMEOS)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -070082static void cb_parse_vboot_handoff(unsigned char *ptr, struct sysinfo_t *info)
83{
84 struct lb_range *vbho = (struct lb_range *)ptr;
85
86 info->vboot_handoff = (void *)(uintptr_t)vbho->range_start;
87 info->vboot_handoff_size = vbho->range_size;
88}
89
90static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
91{
92 struct lb_range *vbnv = (struct lb_range *)ptr;
93
94 info->vbnv_start = vbnv->range_start;
95 info->vbnv_size = vbnv->range_size;
96}
97
98static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
99{
100 int i;
101 struct cb_gpios *gpios = (struct cb_gpios *)ptr;
102
103 info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ?
104 (gpios->count) : SYSINFO_MAX_GPIOS;
105
106 for (i = 0; i < info->num_gpios; i++)
107 info->gpios[i] = gpios->gpios[i];
108}
109
110static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info)
111{
112 struct lb_range *vdat = (struct lb_range *) ptr;
113
114 info->vdat_addr = phys_to_virt(vdat->range_start);
115 info->vdat_size = vdat->range_size;
116}
Vadim Bendeburyb7d74122014-09-22 19:36:28 -0700117
118static void cb_parse_mac_addresses(unsigned char *ptr,
119 struct sysinfo_t *info)
120{
121 struct cb_macs *macs = (struct cb_macs *)ptr;
122 int i;
123
124 info->num_macs = (macs->count < ARRAY_SIZE(info->macs)) ?
125 macs->count : ARRAY_SIZE(info->macs);
126
127 for (i = 0; i < info->num_macs; i++)
128 info->macs[i] = macs->mac_addrs[i];
129}
130
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700131#endif
132
133static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info)
134{
135 struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
136 info->tstamp_table = phys_to_virt(cbmem->cbmem_tab);
137}
138
139static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info)
140{
141 struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
142 info->cbmem_cons = phys_to_virt(cbmem->cbmem_tab);
143}
144
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700145static void cb_parse_acpi_gnvs(unsigned char *ptr, struct sysinfo_t *info)
146{
147 struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
148 info->acpi_gnvs = phys_to_virt(cbmem->cbmem_tab);
149}
150
151static void cb_parse_board_id(unsigned char *ptr, struct sysinfo_t *info)
152{
153 struct cb_board_id *const cbbid = (struct cb_board_id *)ptr;
154 info->board_id = cbbid->board_id;
155}
156
David Hendricks272afe82014-11-20 13:59:45 -0800157static void cb_parse_ram_code(unsigned char *ptr, struct sysinfo_t *info)
158{
159 struct cb_ram_code *const ram_code = (struct cb_ram_code *)ptr;
160 info->ram_code = ram_code->ram_code;
161}
162
Stefan Reinauer1b4d3942015-06-29 15:47:34 -0700163#if IS_ENABLED(CONFIG_LP_NVRAM)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700164static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info)
165{
166 /* ptr points to a coreboot table entry and is already virtual */
167 info->option_table = ptr;
168}
169
170static void cb_parse_checksum(void *ptr, struct sysinfo_t *info)
171{
172 struct cb_cmos_checksum *cmos_cksum = ptr;
173 info->cmos_range_start = cmos_cksum->range_start;
174 info->cmos_range_end = cmos_cksum->range_end;
175 info->cmos_checksum_location = cmos_cksum->location;
176}
177#endif
178
Stefan Reinauer1b4d3942015-06-29 15:47:34 -0700179#if IS_ENABLED(CONFIG_LP_COREBOOT_VIDEO_CONSOLE)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700180static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info)
181{
182 /* ptr points to a coreboot table entry and is already virtual */
183 info->framebuffer = ptr;
184}
185#endif
186
187static void cb_parse_string(unsigned char *ptr, char **info)
188{
189 *info = (char *)((struct cb_string *)ptr)->string;
190}
191
Vadim Bendebury522f9c62014-10-24 15:14:55 -0700192static void cb_parse_wifi_calibration(void *ptr, struct sysinfo_t *info)
193{
194 struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
195 info->wifi_calibration = phys_to_virt(cbmem->cbmem_tab);
196}
197
Furquan Shaikh6b322cc2014-11-08 17:19:31 -0800198static void cb_parse_ramoops(void *ptr, struct sysinfo_t *info)
199{
200 struct lb_range *ramoops = (struct lb_range *)ptr;
201
202 info->ramoops_buffer = ramoops->range_start;
203 info->ramoops_buffer_size = ramoops->range_size;
204}
205
Furquan Shaikh3cec8712015-06-10 20:38:48 -0700206static void cb_parse_mtc(void *ptr, struct sysinfo_t *info)
207{
208 struct lb_range *mtc = (struct lb_range *)ptr;
209
210 info->mtc_start = mtc->range_start;
211 info->mtc_size = mtc->range_size;
212}
213
Dan Ehrenberg6addd402015-01-08 10:29:19 -0800214static void cb_parse_spi_flash(void *ptr, struct sysinfo_t *info)
215{
216 struct cb_spi_flash *flash = (struct cb_spi_flash *)ptr;
217
218 info->spi_flash.size = flash->flash_size;
219 info->spi_flash.sector_size = flash->sector_size;
220 info->spi_flash.erase_cmd = flash->erase_cmd;
221}
222
Patrick Georgif61b35d2015-07-14 17:15:24 +0100223static void cb_parse_boot_media_params(unsigned char *ptr,
224 struct sysinfo_t *info)
225{
226 struct cb_boot_media_params *const bmp =
227 (struct cb_boot_media_params *)ptr;
228 info->fmap_offset = bmp->fmap_offset;
229 info->cbfs_offset = bmp->cbfs_offset;
230 info->cbfs_size = bmp->cbfs_size;
231 info->boot_media_size = bmp->boot_media_size;
232}
233
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700234int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
235{
236 struct cb_header *header;
237 unsigned char *ptr = addr;
238 void *forward;
239 int i;
240
241 for (i = 0; i < len; i += 16, ptr += 16) {
242 header = (struct cb_header *)ptr;
243 if (!strncmp((const char *)header->signature, "LBIO", 4))
244 break;
245 }
246
247 /* We walked the entire space and didn't find anything. */
248 if (i >= len)
249 return -1;
250
251 /* Make sure the checksums match. */
252 if (ipchksum((u16 *) header, sizeof(*header)) != 0)
253 return -1;
254
255 if (!header->table_bytes)
256 return 0;
257
258 if (ipchksum((u16 *) (ptr + sizeof(*header)),
259 header->table_bytes) != header->table_checksum)
260 return -1;
261
262 info->header = header;
263
264 /*
David Hendricks272afe82014-11-20 13:59:45 -0800265 * Board straps represented by numerical values are small numbers.
266 * Preset them to an invalid value in case the firmware does not
267 * supply the info.
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700268 */
269 info->board_id = ~0;
David Hendricks272afe82014-11-20 13:59:45 -0800270 info->ram_code = ~0;
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700271
272 /* Now, walk the tables. */
273 ptr += header->header_bytes;
274
275 for (i = 0; i < header->table_entries; i++) {
276 struct cb_record *rec = (struct cb_record *)ptr;
277
278 /* We only care about a few tags here (maybe more later). */
279 switch (rec->tag) {
280 case CB_TAG_FORWARD:
281 forward = phys_to_virt((void *)(unsigned long)
282 ((struct cb_forward *)rec)->forward);
283 return cb_parse_header(forward, len, info);
284 continue;
285 case CB_TAG_MEMORY:
286 cb_parse_memory(ptr, info);
287 break;
288 case CB_TAG_SERIAL:
289 cb_parse_serial(ptr, info);
290 break;
291 case CB_TAG_VERSION:
292 cb_parse_string(ptr, &info->cb_version);
293 break;
294 case CB_TAG_EXTRA_VERSION:
295 cb_parse_string(ptr, &info->extra_version);
296 break;
297 case CB_TAG_BUILD:
298 cb_parse_string(ptr, &info->build);
299 break;
300 case CB_TAG_COMPILE_TIME:
301 cb_parse_string(ptr, &info->compile_time);
302 break;
303 case CB_TAG_COMPILE_BY:
304 cb_parse_string(ptr, &info->compile_by);
305 break;
306 case CB_TAG_COMPILE_HOST:
307 cb_parse_string(ptr, &info->compile_host);
308 break;
309 case CB_TAG_COMPILE_DOMAIN:
310 cb_parse_string(ptr, &info->compile_domain);
311 break;
312 case CB_TAG_COMPILER:
313 cb_parse_string(ptr, &info->compiler);
314 break;
315 case CB_TAG_LINKER:
316 cb_parse_string(ptr, &info->linker);
317 break;
318 case CB_TAG_ASSEMBLER:
319 cb_parse_string(ptr, &info->assembler);
320 break;
Stefan Reinauer1b4d3942015-06-29 15:47:34 -0700321#if IS_ENABLED(CONFIG_LP_NVRAM)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700322 case CB_TAG_CMOS_OPTION_TABLE:
323 cb_parse_optiontable(ptr, info);
324 break;
325 case CB_TAG_OPTION_CHECKSUM:
326 cb_parse_checksum(ptr, info);
327 break;
328#endif
Stefan Reinauer1b4d3942015-06-29 15:47:34 -0700329#if IS_ENABLED(CONFIG_LP_COREBOOT_VIDEO_CONSOLE)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700330 // FIXME we should warn on serial if coreboot set up a
331 // framebuffer buf the payload does not know about it.
332 case CB_TAG_FRAMEBUFFER:
333 cb_parse_framebuffer(ptr, info);
334 break;
335#endif
336 case CB_TAG_MAINBOARD:
337 info->mainboard = (struct cb_mainboard *)ptr;
338 break;
Stefan Reinauer1b4d3942015-06-29 15:47:34 -0700339#if IS_ENABLED(CONFIG_LP_CHROMEOS)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700340 case CB_TAG_GPIO:
341 cb_parse_gpios(ptr, info);
342 break;
343 case CB_TAG_VDAT:
344 cb_parse_vdat(ptr, info);
345 break;
346 case CB_TAG_VBNV:
347 cb_parse_vbnv(ptr, info);
348 break;
349 case CB_TAG_VBOOT_HANDOFF:
350 cb_parse_vboot_handoff(ptr, info);
351 break;
Vadim Bendeburyb7d74122014-09-22 19:36:28 -0700352 case CB_TAG_MAC_ADDRS:
353 cb_parse_mac_addresses(ptr, info);
354 break;
Stephen Barberda262a632015-03-11 15:48:08 -0700355 case CB_TAG_SERIALNO:
356 cb_parse_string(ptr, &info->serialno);
357 break;
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700358#endif
359 case CB_TAG_TIMESTAMPS:
360 cb_parse_tstamp(ptr, info);
361 break;
362 case CB_TAG_CBMEM_CONSOLE:
363 cb_parse_cbmem_cons(ptr, info);
364 break;
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700365 case CB_TAG_ACPI_GNVS:
366 cb_parse_acpi_gnvs(ptr, info);
367 break;
368 case CB_TAG_BOARD_ID:
369 cb_parse_board_id(ptr, info);
370 break;
David Hendricks272afe82014-11-20 13:59:45 -0800371 case CB_TAG_RAM_CODE:
372 cb_parse_ram_code(ptr, info);
373 break;
Vadim Bendebury522f9c62014-10-24 15:14:55 -0700374 case CB_TAG_WIFI_CALIBRATION:
375 cb_parse_wifi_calibration(ptr, info);
376 break;
Furquan Shaikh6b322cc2014-11-08 17:19:31 -0800377 case CB_TAG_RAM_OOPS:
378 cb_parse_ramoops(ptr, info);
379 break;
Dan Ehrenberg6addd402015-01-08 10:29:19 -0800380 case CB_TAG_SPI_FLASH:
381 cb_parse_spi_flash(ptr, info);
382 break;
Furquan Shaikh3cec8712015-06-10 20:38:48 -0700383 case CB_TAG_MTC:
384 cb_parse_mtc(ptr, info);
385 break;
Patrick Georgif61b35d2015-07-14 17:15:24 +0100386 case CB_TAG_BOOT_MEDIA_PARAMS:
387 cb_parse_boot_media_params(ptr, info);
388 break;
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700389 default:
390 cb_parse_arch_specific(rec, info);
391 break;
392 }
393
394 ptr += rec->size;
395 }
396
397 return 0;
398}