blob: 3c49484064e1a0bed0803e0eec978ae997d00bb6 [file] [log] [blame]
Vadim Bendebury864ec8c2014-07-31 21:02:57 -07001/*
Vadim Bendebury864ec8c2014-07-31 21:02:57 -07002 *
3 * Copyright (C) 2008 Advanced Micro Devices, Inc.
4 * Copyright (C) 2009 coresystems GmbH
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <libpayload-config.h>
31#include <libpayload.h>
Jakub Czapiga2f236c22021-11-10 14:04:43 +000032#include <commonlib/bsd/cbmem_id.h>
Vadim Bendebury864ec8c2014-07-31 21:02:57 -070033#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
Julius Wernereab2a292019-03-05 16:55:15 -080059#if CONFIG(LP_MEMMAP_RAM_ONLY)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -070060 if (range->type != CB_MEM_RAM)
61 continue;
62#endif
63
Jianjun Wangb2537bd2022-04-08 16:57:28 +080064 info->memrange[info->n_memranges].base = range->start;
65 info->memrange[info->n_memranges].size = range->size;
Vadim Bendebury864ec8c2014-07-31 21:02:57 -070066 info->memrange[info->n_memranges].type = range->type;
67
68 info->n_memranges++;
69 }
70}
71
72static void cb_parse_serial(void *ptr, struct sysinfo_t *info)
73{
Nico Huberbe842cb2020-07-18 14:54:47 +020074 info->cb_serial = virt_to_phys(ptr);
Vadim Bendebury864ec8c2014-07-31 21:02:57 -070075}
76
Vadim Bendebury864ec8c2014-07-31 21:02:57 -070077static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
78{
79 struct lb_range *vbnv = (struct lb_range *)ptr;
80
81 info->vbnv_start = vbnv->range_start;
82 info->vbnv_size = vbnv->range_size;
83}
84
Bora Guvendikddf2bc52018-03-30 16:03:32 -070085static void cb_parse_mmc_info(unsigned char *ptr, struct sysinfo_t *info)
86{
87 struct cb_mmc_info *mmc_info = (struct cb_mmc_info *)ptr;
88
89 info->mmc_early_wake_status = mmc_info->early_cmd1_status;
90}
91
Vadim Bendebury864ec8c2014-07-31 21:02:57 -070092static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
93{
94 int i;
95 struct cb_gpios *gpios = (struct cb_gpios *)ptr;
96
97 info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ?
98 (gpios->count) : SYSINFO_MAX_GPIOS;
99
100 for (i = 0; i < info->num_gpios; i++)
101 info->gpios[i] = gpios->gpios[i];
102}
103
Vadim Bendeburyb7d74122014-09-22 19:36:28 -0700104static void cb_parse_mac_addresses(unsigned char *ptr,
105 struct sysinfo_t *info)
106{
107 struct cb_macs *macs = (struct cb_macs *)ptr;
108 int i;
109
110 info->num_macs = (macs->count < ARRAY_SIZE(info->macs)) ?
111 macs->count : ARRAY_SIZE(info->macs);
112
113 for (i = 0; i < info->num_macs; i++)
114 info->macs[i] = macs->mac_addrs[i];
115}
116
Tim Wawrzynczake1a7a262020-10-09 17:07:45 -0600117static void cb_parse_board_config(unsigned char *ptr, struct sysinfo_t *info)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700118{
Tim Wawrzynczake1a7a262020-10-09 17:07:45 -0600119 struct cb_board_config *const config = (struct cb_board_config *)ptr;
Jianjun Wangb2537bd2022-04-08 16:57:28 +0800120 info->fw_config = config->fw_config;
Tim Wawrzynczake1a7a262020-10-09 17:07:45 -0600121 info->board_id = config->board_id;
122 info->ram_code = config->ram_code;
123 info->sku_id = config->sku_id;
Julius Wernerf38a10f2017-12-05 13:49:21 -0800124}
125
Julius Wernereab2a292019-03-05 16:55:15 -0800126#if CONFIG(LP_NVRAM)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700127static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info)
128{
Nico Huberb2eafa62020-07-18 14:45:23 +0200129 /* ptr is already virtual, but we want to keep physical addresses */
130 info->cmos_option_table = virt_to_phys(ptr);
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700131}
132
133static void cb_parse_checksum(void *ptr, struct sysinfo_t *info)
134{
135 struct cb_cmos_checksum *cmos_cksum = ptr;
136 info->cmos_range_start = cmos_cksum->range_start;
137 info->cmos_range_end = cmos_cksum->range_end;
138 info->cmos_checksum_location = cmos_cksum->location;
139}
140#endif
141
Julius Wernereab2a292019-03-05 16:55:15 -0800142#if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700143static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info)
144{
Nico Huber5e0db582020-07-18 15:20:00 +0200145 info->framebuffer = *(struct cb_framebuffer *)ptr;
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700146}
147#endif
148
Nico Huber4a732522020-07-18 16:29:18 +0200149static void cb_parse_string(const void *const ptr, uintptr_t *const info)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700150{
Nico Huber4a732522020-07-18 16:29:18 +0200151 /* ptr is already virtual (str->string just an offset to that),
152 but we want to keep physical addresses */
153 const struct cb_string *const str = ptr;
154 *info = virt_to_phys(str->string);
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700155}
156
Furquan Shaikh6b322cc2014-11-08 17:19:31 -0800157static void cb_parse_ramoops(void *ptr, struct sysinfo_t *info)
158{
159 struct lb_range *ramoops = (struct lb_range *)ptr;
160
161 info->ramoops_buffer = ramoops->range_start;
162 info->ramoops_buffer_size = ramoops->range_size;
163}
164
Furquan Shaikh3cec8712015-06-10 20:38:48 -0700165static void cb_parse_mtc(void *ptr, struct sysinfo_t *info)
166{
167 struct lb_range *mtc = (struct lb_range *)ptr;
168
169 info->mtc_start = mtc->range_start;
170 info->mtc_size = mtc->range_size;
171}
172
Dan Ehrenberg6addd402015-01-08 10:29:19 -0800173static void cb_parse_spi_flash(void *ptr, struct sysinfo_t *info)
174{
175 struct cb_spi_flash *flash = (struct cb_spi_flash *)ptr;
176
177 info->spi_flash.size = flash->flash_size;
178 info->spi_flash.sector_size = flash->sector_size;
179 info->spi_flash.erase_cmd = flash->erase_cmd;
Furquan Shaikh493937e2020-11-25 17:15:09 -0800180
181 if (flash->mmap_count == 0)
182 return;
183
184 info->spi_flash.mmap_window_count = MIN(flash->mmap_count, SYSINFO_MAX_MMAP_WINDOWS);
185 memcpy(info->spi_flash.mmap_table, flash->mmap_table,
186 info->spi_flash.mmap_window_count * sizeof(struct flash_mmap_window));
Dan Ehrenberg6addd402015-01-08 10:29:19 -0800187}
188
Patrick Georgif61b35d2015-07-14 17:15:24 +0100189static void cb_parse_boot_media_params(unsigned char *ptr,
190 struct sysinfo_t *info)
191{
192 struct cb_boot_media_params *const bmp =
193 (struct cb_boot_media_params *)ptr;
194 info->fmap_offset = bmp->fmap_offset;
195 info->cbfs_offset = bmp->cbfs_offset;
196 info->cbfs_size = bmp->cbfs_size;
197 info->boot_media_size = bmp->boot_media_size;
198}
199
Julius Wernereab2a292019-03-05 16:55:15 -0800200#if CONFIG(LP_TIMER_RDTSC)
Aaron Durbin152e5a02016-02-10 11:01:49 -0600201static void cb_parse_tsc_info(void *ptr, struct sysinfo_t *info)
202{
203 const struct cb_tsc_info *tsc_info = ptr;
204
205 if (tsc_info->freq_khz == 0)
206 return;
207
208 /* Honor the TSC frequency passed to the payload. */
209 info->cpu_khz = tsc_info->freq_khz;
210}
211#endif
212
Jakub Czapiga2f236c22021-11-10 14:04:43 +0000213static void cb_parse_cbmem_entry(void *ptr, struct sysinfo_t *info)
214{
215 const struct cb_cbmem_entry *cbmem_entry = ptr;
216
217 if (cbmem_entry->size != sizeof(*cbmem_entry))
218 return;
219
220 switch (cbmem_entry->id) {
221 case CBMEM_ID_ACPI_CNVS:
222 info->acpi_cnvs = cbmem_entry->address;
223 break;
224 case CBMEM_ID_ACPI_GNVS:
225 info->acpi_gnvs = cbmem_entry->address;
226 break;
Maximilian Brune676ef5b2023-08-07 19:50:43 +0200227 case CBMEM_ID_SMBIOS:
228 info->smbios = cbmem_entry->address;
229 break;
Jakub Czapiga2f236c22021-11-10 14:04:43 +0000230 case CBMEM_ID_CBFS_RO_MCACHE:
231 info->cbfs_ro_mcache_offset = cbmem_entry->address;
Jakub Czapiga5b76ae92022-02-08 14:20:55 +0100232 info->cbfs_ro_mcache_size = cbmem_entry->entry_size;
Jakub Czapiga2f236c22021-11-10 14:04:43 +0000233 break;
234 case CBMEM_ID_CBFS_RW_MCACHE:
235 info->cbfs_rw_mcache_offset = cbmem_entry->address;
Jakub Czapiga5b76ae92022-02-08 14:20:55 +0100236 info->cbfs_rw_mcache_size = cbmem_entry->entry_size;
Jakub Czapiga2f236c22021-11-10 14:04:43 +0000237 break;
238 case CBMEM_ID_CONSOLE:
239 info->cbmem_cons = cbmem_entry->address;
240 break;
241 case CBMEM_ID_MRCDATA:
242 info->mrc_cache = cbmem_entry->address;
243 break;
244 case CBMEM_ID_VBOOT_WORKBUF:
245 info->vboot_workbuf = cbmem_entry->address;
246 break;
247 case CBMEM_ID_TIMESTAMP:
248 info->tstamp_table = cbmem_entry->address;
249 break;
250 case CBMEM_ID_VPD:
251 info->chromeos_vpd = cbmem_entry->address;
252 break;
253 case CBMEM_ID_FMAP:
254 info->fmap_cache = cbmem_entry->address;
255 break;
256 case CBMEM_ID_WIFI_CALIBRATION:
257 info->wifi_calibration = cbmem_entry->address;
258 break;
259 case CBMEM_ID_TYPE_C_INFO:
260 info->type_c_info = cbmem_entry->address;
261 break;
Ravi Kumar Bokka42fcb2a2021-11-10 05:22:47 +0530262 case CBMEM_ID_MEM_CHIP_INFO:
263 info->mem_chip_base = cbmem_entry->address;
264 break;
Jakub Czapiga2f236c22021-11-10 14:04:43 +0000265 default:
266 break;
267 }
268}
269
Jianjun Wangd16c2aa2022-03-31 15:34:34 +0800270static void cb_parse_pcie(void *ptr, struct sysinfo_t *info)
271{
272 const struct cb_pcie *pcie = ptr;
273
274 info->pcie_ctrl_base = pcie->ctrl_base;
275}
276
Arthur Heymanscddba452022-03-03 22:59:23 +0100277static void cb_parse_rsdp(void *ptr, struct sysinfo_t *info)
278{
279 const struct cb_acpi_rsdp *cb_acpi_rsdp = ptr;
Jianjun Wangb2537bd2022-04-08 16:57:28 +0800280 info->acpi_rsdp = cb_acpi_rsdp->rsdp_pointer;
Arthur Heymanscddba452022-03-03 22:59:23 +0100281}
282
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700283int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
284{
285 struct cb_header *header;
286 unsigned char *ptr = addr;
287 void *forward;
288 int i;
289
290 for (i = 0; i < len; i += 16, ptr += 16) {
291 header = (struct cb_header *)ptr;
292 if (!strncmp((const char *)header->signature, "LBIO", 4))
293 break;
294 }
295
296 /* We walked the entire space and didn't find anything. */
297 if (i >= len)
298 return -1;
299
300 /* Make sure the checksums match. */
301 if (ipchksum((u16 *) header, sizeof(*header)) != 0)
302 return -1;
303
304 if (!header->table_bytes)
305 return 0;
306
307 if (ipchksum((u16 *) (ptr + sizeof(*header)),
308 header->table_bytes) != header->table_checksum)
309 return -1;
310
Nico Huber12faea32020-07-18 16:15:42 +0200311 info->cb_header = virt_to_phys(header);
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700312
Julius Werner2e029ac2017-12-05 13:43:56 -0800313 /* Initialize IDs as undefined in case they don't show up in table. */
314 info->board_id = UNDEFINED_STRAPPING_ID;
315 info->ram_code = UNDEFINED_STRAPPING_ID;
Julius Wernerf38a10f2017-12-05 13:49:21 -0800316 info->sku_id = UNDEFINED_STRAPPING_ID;
Tim Wawrzynczake1a7a262020-10-09 17:07:45 -0600317 info->fw_config = UNDEFINED_FW_CONFIG;
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700318
319 /* Now, walk the tables. */
320 ptr += header->header_bytes;
321
322 for (i = 0; i < header->table_entries; i++) {
323 struct cb_record *rec = (struct cb_record *)ptr;
324
325 /* We only care about a few tags here (maybe more later). */
326 switch (rec->tag) {
327 case CB_TAG_FORWARD:
328 forward = phys_to_virt((void *)(unsigned long)
329 ((struct cb_forward *)rec)->forward);
330 return cb_parse_header(forward, len, info);
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700331 case CB_TAG_MEMORY:
332 cb_parse_memory(ptr, info);
333 break;
334 case CB_TAG_SERIAL:
335 cb_parse_serial(ptr, info);
336 break;
337 case CB_TAG_VERSION:
338 cb_parse_string(ptr, &info->cb_version);
339 break;
340 case CB_TAG_EXTRA_VERSION:
341 cb_parse_string(ptr, &info->extra_version);
342 break;
343 case CB_TAG_BUILD:
344 cb_parse_string(ptr, &info->build);
345 break;
346 case CB_TAG_COMPILE_TIME:
347 cb_parse_string(ptr, &info->compile_time);
348 break;
349 case CB_TAG_COMPILE_BY:
350 cb_parse_string(ptr, &info->compile_by);
351 break;
352 case CB_TAG_COMPILE_HOST:
353 cb_parse_string(ptr, &info->compile_host);
354 break;
355 case CB_TAG_COMPILE_DOMAIN:
356 cb_parse_string(ptr, &info->compile_domain);
357 break;
358 case CB_TAG_COMPILER:
359 cb_parse_string(ptr, &info->compiler);
360 break;
361 case CB_TAG_LINKER:
362 cb_parse_string(ptr, &info->linker);
363 break;
364 case CB_TAG_ASSEMBLER:
365 cb_parse_string(ptr, &info->assembler);
366 break;
Julius Wernereab2a292019-03-05 16:55:15 -0800367#if CONFIG(LP_NVRAM)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700368 case CB_TAG_CMOS_OPTION_TABLE:
369 cb_parse_optiontable(ptr, info);
370 break;
371 case CB_TAG_OPTION_CHECKSUM:
372 cb_parse_checksum(ptr, info);
373 break;
374#endif
Julius Wernereab2a292019-03-05 16:55:15 -0800375#if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700376 // FIXME we should warn on serial if coreboot set up a
377 // framebuffer buf the payload does not know about it.
378 case CB_TAG_FRAMEBUFFER:
379 cb_parse_framebuffer(ptr, info);
380 break;
381#endif
382 case CB_TAG_MAINBOARD:
Nico Huber12faea32020-07-18 16:15:42 +0200383 info->cb_mainboard = virt_to_phys(ptr);
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700384 break;
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700385 case CB_TAG_GPIO:
386 cb_parse_gpios(ptr, info);
387 break;
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700388 case CB_TAG_VBNV:
389 cb_parse_vbnv(ptr, info);
390 break;
Vadim Bendeburyb7d74122014-09-22 19:36:28 -0700391 case CB_TAG_MAC_ADDRS:
392 cb_parse_mac_addresses(ptr, info);
393 break;
Stephen Barberda262a632015-03-11 15:48:08 -0700394 case CB_TAG_SERIALNO:
395 cb_parse_string(ptr, &info->serialno);
396 break;
Tim Wawrzynczake1a7a262020-10-09 17:07:45 -0600397 case CB_TAG_BOARD_CONFIG:
398 cb_parse_board_config(ptr, info);
Julius Wernerf38a10f2017-12-05 13:49:21 -0800399 break;
Furquan Shaikh6b322cc2014-11-08 17:19:31 -0800400 case CB_TAG_RAM_OOPS:
401 cb_parse_ramoops(ptr, info);
402 break;
Dan Ehrenberg6addd402015-01-08 10:29:19 -0800403 case CB_TAG_SPI_FLASH:
404 cb_parse_spi_flash(ptr, info);
405 break;
Bora Guvendikddf2bc52018-03-30 16:03:32 -0700406 case CB_TAG_MMC_INFO:
407 cb_parse_mmc_info(ptr, info);
408 break;
Furquan Shaikh3cec8712015-06-10 20:38:48 -0700409 case CB_TAG_MTC:
410 cb_parse_mtc(ptr, info);
411 break;
Patrick Georgif61b35d2015-07-14 17:15:24 +0100412 case CB_TAG_BOOT_MEDIA_PARAMS:
413 cb_parse_boot_media_params(ptr, info);
414 break;
Jakub Czapiga2f236c22021-11-10 14:04:43 +0000415 case CB_TAG_CBMEM_ENTRY:
416 cb_parse_cbmem_entry(ptr, info);
417 break;
Julius Wernereab2a292019-03-05 16:55:15 -0800418#if CONFIG(LP_TIMER_RDTSC)
Aaron Durbin152e5a02016-02-10 11:01:49 -0600419 case CB_TAG_TSC_INFO:
420 cb_parse_tsc_info(ptr, info);
421 break;
422#endif
Arthur Heymanscddba452022-03-03 22:59:23 +0100423 case CB_TAG_ACPI_RSDP:
424 cb_parse_rsdp(ptr, info);
425 break;
Jianjun Wangd16c2aa2022-03-31 15:34:34 +0800426 case CB_TAG_PCIE:
427 cb_parse_pcie(ptr, info);
428 break;
Vadim Bendebury864ec8c2014-07-31 21:02:57 -0700429 default:
430 cb_parse_arch_specific(rec, info);
431 break;
432 }
433
434 ptr += rec->size;
435 }
436
437 return 0;
438}