3 * Copyright (C) 2008 Advanced Micro Devices, Inc.
4 * Copyright (C) 2009 coresystems GmbH
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
30 #include <libpayload-config.h>
31 #include <libpayload.h>
32 #include <commonlib/bsd/cbmem_id.h>
33 #include <coreboot_tables.h>
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.
42 /* === Parsing code === */
43 /* This is the generic parsing code. */
45 static void cb_parse_memory(void *ptr
, struct sysinfo_t
*info
)
47 struct cb_memory
*mem
= ptr
;
48 int count
= MEM_RANGE_COUNT(mem
);
51 if (count
> SYSINFO_MAX_MEM_RANGES
)
52 count
= SYSINFO_MAX_MEM_RANGES
;
54 info
->n_memranges
= 0;
56 for (i
= 0; i
< count
; i
++) {
57 struct cb_memory_range
*range
= MEM_RANGE_PTR(mem
, i
);
59 #if CONFIG(LP_MEMMAP_RAM_ONLY)
60 if (range
->type
!= CB_MEM_RAM
)
64 info
->memrange
[info
->n_memranges
].base
= range
->start
;
65 info
->memrange
[info
->n_memranges
].size
= range
->size
;
66 info
->memrange
[info
->n_memranges
].type
= range
->type
;
72 static void cb_parse_serial(void *ptr
, struct sysinfo_t
*info
)
74 info
->cb_serial
= virt_to_phys(ptr
);
77 static void cb_parse_vbnv(unsigned char *ptr
, struct sysinfo_t
*info
)
79 struct lb_range
*vbnv
= (struct lb_range
*)ptr
;
81 info
->vbnv_start
= vbnv
->range_start
;
82 info
->vbnv_size
= vbnv
->range_size
;
85 static void cb_parse_mmc_info(unsigned char *ptr
, struct sysinfo_t
*info
)
87 struct cb_mmc_info
*mmc_info
= (struct cb_mmc_info
*)ptr
;
89 info
->mmc_early_wake_status
= mmc_info
->early_cmd1_status
;
92 static void cb_parse_gpios(unsigned char *ptr
, struct sysinfo_t
*info
)
95 struct cb_gpios
*gpios
= (struct cb_gpios
*)ptr
;
97 info
->num_gpios
= (gpios
->count
< SYSINFO_MAX_GPIOS
) ?
98 (gpios
->count
) : SYSINFO_MAX_GPIOS
;
100 for (i
= 0; i
< info
->num_gpios
; i
++)
101 info
->gpios
[i
] = gpios
->gpios
[i
];
104 static void cb_parse_mac_addresses(unsigned char *ptr
,
105 struct sysinfo_t
*info
)
107 struct cb_macs
*macs
= (struct cb_macs
*)ptr
;
110 info
->num_macs
= (macs
->count
< ARRAY_SIZE(info
->macs
)) ?
111 macs
->count
: ARRAY_SIZE(info
->macs
);
113 for (i
= 0; i
< info
->num_macs
; i
++)
114 info
->macs
[i
] = macs
->mac_addrs
[i
];
117 static void cb_parse_board_config(unsigned char *ptr
, struct sysinfo_t
*info
)
119 struct cb_board_config
*const config
= (struct cb_board_config
*)ptr
;
120 info
->fw_config
= config
->fw_config
;
121 info
->board_id
= config
->board_id
;
122 info
->ram_code
= config
->ram_code
;
123 info
->sku_id
= config
->sku_id
;
127 static void cb_parse_optiontable(void *ptr
, struct sysinfo_t
*info
)
129 /* ptr is already virtual, but we want to keep physical addresses */
130 info
->cmos_option_table
= virt_to_phys(ptr
);
133 static void cb_parse_checksum(void *ptr
, struct sysinfo_t
*info
)
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
;
142 #if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
143 static void cb_parse_framebuffer(void *ptr
, struct sysinfo_t
*info
)
145 info
->framebuffer
= *(struct cb_framebuffer
*)ptr
;
149 static void cb_parse_string(const void *const ptr
, uintptr_t *const info
)
151 /* 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
);
157 static void cb_parse_ramoops(void *ptr
, struct sysinfo_t
*info
)
159 struct lb_range
*ramoops
= (struct lb_range
*)ptr
;
161 info
->ramoops_buffer
= ramoops
->range_start
;
162 info
->ramoops_buffer_size
= ramoops
->range_size
;
165 static void cb_parse_mtc(void *ptr
, struct sysinfo_t
*info
)
167 struct lb_range
*mtc
= (struct lb_range
*)ptr
;
169 info
->mtc_start
= mtc
->range_start
;
170 info
->mtc_size
= mtc
->range_size
;
173 static void cb_parse_spi_flash(void *ptr
, struct sysinfo_t
*info
)
175 struct cb_spi_flash
*flash
= (struct cb_spi_flash
*)ptr
;
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
;
181 if (flash
->mmap_count
== 0)
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
));
189 static void cb_parse_boot_media_params(unsigned char *ptr
,
190 struct sysinfo_t
*info
)
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
;
200 #if CONFIG(LP_TIMER_RDTSC)
201 static void cb_parse_tsc_info(void *ptr
, struct sysinfo_t
*info
)
203 const struct cb_tsc_info
*tsc_info
= ptr
;
205 if (tsc_info
->freq_khz
== 0)
208 /* Honor the TSC frequency passed to the payload. */
209 info
->cpu_khz
= tsc_info
->freq_khz
;
213 static void cb_parse_cbmem_entry(void *ptr
, struct sysinfo_t
*info
)
215 const struct cb_cbmem_entry
*cbmem_entry
= ptr
;
217 if (cbmem_entry
->size
!= sizeof(*cbmem_entry
))
220 switch (cbmem_entry
->id
) {
221 case CBMEM_ID_ACPI_CNVS
:
222 info
->acpi_cnvs
= cbmem_entry
->address
;
224 case CBMEM_ID_ACPI_GNVS
:
225 info
->acpi_gnvs
= cbmem_entry
->address
;
227 case CBMEM_ID_SMBIOS
:
228 info
->smbios
= cbmem_entry
->address
;
230 case CBMEM_ID_CBFS_RO_MCACHE
:
231 info
->cbfs_ro_mcache_offset
= cbmem_entry
->address
;
232 info
->cbfs_ro_mcache_size
= cbmem_entry
->entry_size
;
234 case CBMEM_ID_CBFS_RW_MCACHE
:
235 info
->cbfs_rw_mcache_offset
= cbmem_entry
->address
;
236 info
->cbfs_rw_mcache_size
= cbmem_entry
->entry_size
;
238 case CBMEM_ID_CONSOLE
:
239 info
->cbmem_cons
= cbmem_entry
->address
;
241 case CBMEM_ID_MRCDATA
:
242 info
->mrc_cache
= cbmem_entry
->address
;
244 case CBMEM_ID_VBOOT_WORKBUF
:
245 info
->vboot_workbuf
= cbmem_entry
->address
;
247 case CBMEM_ID_TIMESTAMP
:
248 info
->tstamp_table
= cbmem_entry
->address
;
251 info
->chromeos_vpd
= cbmem_entry
->address
;
254 info
->fmap_cache
= cbmem_entry
->address
;
256 case CBMEM_ID_WIFI_CALIBRATION
:
257 info
->wifi_calibration
= cbmem_entry
->address
;
259 case CBMEM_ID_TYPE_C_INFO
:
260 info
->type_c_info
= cbmem_entry
->address
;
262 case CBMEM_ID_MEM_CHIP_INFO
:
263 info
->mem_chip_base
= cbmem_entry
->address
;
265 case CBMEM_ID_CSE_BP_INFO
:
266 info
->cse_bp_info
= cbmem_entry
->address
;
268 case CBMEM_ID_CSE_INFO
:
269 info
->cse_info
= cbmem_entry
->address
;
276 static void cb_parse_pcie(void *ptr
, struct sysinfo_t
*info
)
278 const struct cb_pcie
*pcie
= ptr
;
280 info
->pcie_ctrl_base
= pcie
->ctrl_base
;
283 static void cb_parse_rsdp(void *ptr
, struct sysinfo_t
*info
)
285 const struct cb_acpi_rsdp
*cb_acpi_rsdp
= ptr
;
286 info
->acpi_rsdp
= cb_acpi_rsdp
->rsdp_pointer
;
289 int cb_parse_header(void *addr
, int len
, struct sysinfo_t
*info
)
291 struct cb_header
*header
;
292 unsigned char *ptr
= addr
;
296 for (i
= 0; i
< len
; i
+= 16, ptr
+= 16) {
297 header
= (struct cb_header
*)ptr
;
298 if (!strncmp((const char *)header
->signature
, "LBIO", 4))
302 /* We walked the entire space and didn't find anything. */
306 /* Make sure the checksums match. */
307 if (ipchksum((u16
*) header
, sizeof(*header
)) != 0)
310 if (!header
->table_bytes
)
313 if (ipchksum((u16
*) (ptr
+ sizeof(*header
)),
314 header
->table_bytes
) != header
->table_checksum
)
317 info
->cb_header
= virt_to_phys(header
);
319 /* Initialize IDs as undefined in case they don't show up in table. */
320 info
->board_id
= UNDEFINED_STRAPPING_ID
;
321 info
->ram_code
= UNDEFINED_STRAPPING_ID
;
322 info
->sku_id
= UNDEFINED_STRAPPING_ID
;
323 info
->fw_config
= UNDEFINED_FW_CONFIG
;
325 /* Now, walk the tables. */
326 ptr
+= header
->header_bytes
;
328 for (i
= 0; i
< header
->table_entries
; i
++) {
329 struct cb_record
*rec
= (struct cb_record
*)ptr
;
331 /* We only care about a few tags here (maybe more later). */
334 forward
= phys_to_virt((void *)(unsigned long)
335 ((struct cb_forward
*)rec
)->forward
);
336 return cb_parse_header(forward
, len
, info
);
338 cb_parse_memory(ptr
, info
);
341 cb_parse_serial(ptr
, info
);
344 cb_parse_string(ptr
, &info
->cb_version
);
346 case CB_TAG_EXTRA_VERSION
:
347 cb_parse_string(ptr
, &info
->extra_version
);
350 cb_parse_string(ptr
, &info
->build
);
352 case CB_TAG_COMPILE_TIME
:
353 cb_parse_string(ptr
, &info
->compile_time
);
355 case CB_TAG_COMPILE_BY
:
356 cb_parse_string(ptr
, &info
->compile_by
);
358 case CB_TAG_COMPILE_HOST
:
359 cb_parse_string(ptr
, &info
->compile_host
);
361 case CB_TAG_COMPILE_DOMAIN
:
362 cb_parse_string(ptr
, &info
->compile_domain
);
364 case CB_TAG_COMPILER
:
365 cb_parse_string(ptr
, &info
->compiler
);
368 cb_parse_string(ptr
, &info
->linker
);
370 case CB_TAG_ASSEMBLER
:
371 cb_parse_string(ptr
, &info
->assembler
);
374 case CB_TAG_CMOS_OPTION_TABLE
:
375 cb_parse_optiontable(ptr
, info
);
377 case CB_TAG_OPTION_CHECKSUM
:
378 cb_parse_checksum(ptr
, info
);
381 #if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
382 // FIXME we should warn on serial if coreboot set up a
383 // framebuffer buf the payload does not know about it.
384 case CB_TAG_FRAMEBUFFER
:
385 cb_parse_framebuffer(ptr
, info
);
388 case CB_TAG_MAINBOARD
:
389 info
->cb_mainboard
= virt_to_phys(ptr
);
392 cb_parse_gpios(ptr
, info
);
395 cb_parse_vbnv(ptr
, info
);
397 case CB_TAG_MAC_ADDRS
:
398 cb_parse_mac_addresses(ptr
, info
);
400 case CB_TAG_SERIALNO
:
401 cb_parse_string(ptr
, &info
->serialno
);
403 case CB_TAG_BOARD_CONFIG
:
404 cb_parse_board_config(ptr
, info
);
406 case CB_TAG_RAM_OOPS
:
407 cb_parse_ramoops(ptr
, info
);
409 case CB_TAG_SPI_FLASH
:
410 cb_parse_spi_flash(ptr
, info
);
412 case CB_TAG_MMC_INFO
:
413 cb_parse_mmc_info(ptr
, info
);
416 cb_parse_mtc(ptr
, info
);
418 case CB_TAG_BOOT_MEDIA_PARAMS
:
419 cb_parse_boot_media_params(ptr
, info
);
421 case CB_TAG_CBMEM_ENTRY
:
422 cb_parse_cbmem_entry(ptr
, info
);
424 #if CONFIG(LP_TIMER_RDTSC)
425 case CB_TAG_TSC_INFO
:
426 cb_parse_tsc_info(ptr
, info
);
429 case CB_TAG_ACPI_RSDP
:
430 cb_parse_rsdp(ptr
, info
);
433 cb_parse_pcie(ptr
, info
);
436 cb_parse_arch_specific(rec
, info
);