Browse Source

coreboot: Add memory range parsing

This patch adds code to parse memory range information passed by
coreboot, and a simple helper to test whether a specific address belongs
to a range. This may be useful for coreboot-using platforms that need to
know information about the system's memory layout (e.g. to check whether
an address passed in via SMC targets valid DRAM).

Signed-off-by: Julius Werner <jwerner@chromium.org>
Change-Id: I3bea326c426db27d1a8b7d6e17418e4850e884b4
pull/1938/head
Julius Werner 5 years ago
committed by Sandrine Bailleux
parent
commit
579d1e90d4
  1. 23
      include/lib/coreboot.h
  2. 32
      lib/coreboot/coreboot_table.c

23
include/lib/coreboot.h

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -19,6 +19,27 @@ typedef struct {
} coreboot_serial_t; } coreboot_serial_t;
extern coreboot_serial_t coreboot_serial; extern coreboot_serial_t coreboot_serial;
#define COREBOOT_MAX_MEMRANGES 32 /* libpayload also uses this limit */
typedef struct __packed {
uint64_t start;
uint64_t size;
uint32_t type;
} coreboot_memrange_t;
extern coreboot_memrange_t coreboot_memranges[COREBOOT_MAX_MEMRANGES];
typedef enum {
CB_MEM_NONE = 0, /* coreboot will never report this */
CB_MEM_RAM = 1,
CB_MEM_RESERVED = 2,
CB_MEM_ACPI = 3,
CB_MEM_NVS = 4,
CB_MEM_UNUSABLE = 5,
CB_MEM_VENDOR_RSVD = 6,
CB_MEM_TABLE = 16,
} coreboot_memory_t;
coreboot_memory_t coreboot_get_memory_type(uintptr_t address);
void coreboot_table_setup(void *base); void coreboot_table_setup(void *base);
#endif /* COREBOOT_H */ #endif /* COREBOOT_H */

32
lib/coreboot/coreboot_table.c

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -29,6 +29,7 @@ typedef struct {
} cb_header_t; } cb_header_t;
typedef enum { typedef enum {
CB_TAG_MEMORY = 0x1,
CB_TAG_SERIAL = 0xf, CB_TAG_SERIAL = 0xf,
CB_TAG_CBMEM_CONSOLE = 0x17, CB_TAG_CBMEM_CONSOLE = 0x17,
} cb_tag_t; } cb_tag_t;
@ -37,11 +38,13 @@ typedef struct {
uint32_t tag; uint32_t tag;
uint32_t size; uint32_t size;
union { union {
coreboot_memrange_t memranges[COREBOOT_MAX_MEMRANGES];
coreboot_serial_t serial; coreboot_serial_t serial;
uint64_t uint64; uint64_t uint64;
}; };
} cb_entry_t; } cb_entry_t;
coreboot_memrange_t coreboot_memranges[COREBOOT_MAX_MEMRANGES];
coreboot_serial_t coreboot_serial; coreboot_serial_t coreboot_serial;
/* /*
@ -86,6 +89,23 @@ static void setup_cbmem_console(uintptr_t baseaddr)
CONSOLE_FLAG_CRASH); CONSOLE_FLAG_CRASH);
} }
coreboot_memory_t coreboot_get_memory_type(uintptr_t address)
{
int i;
for (i = 0; i < COREBOOT_MAX_MEMRANGES; i++) {
coreboot_memrange_t *range = &coreboot_memranges[i];
if (range->type == CB_MEM_NONE)
break; /* end of table reached */
if (address >= range->start &&
address - range->start < range->size)
return range->type;
}
return CB_MEM_NONE;
}
void coreboot_table_setup(void *base) void coreboot_table_setup(void *base)
{ {
cb_header_t *header = base; cb_header_t *header = base;
@ -99,6 +119,7 @@ void coreboot_table_setup(void *base)
ptr = base + header->header_bytes; ptr = base + header->header_bytes;
for (i = 0; i < header->table_entries; i++) { for (i = 0; i < header->table_entries; i++) {
size_t size;
cb_entry_t *entry = ptr; cb_entry_t *entry = ptr;
if (ptr - base >= header->header_bytes + header->table_bytes) { if (ptr - base >= header->header_bytes + header->table_bytes) {
@ -107,6 +128,15 @@ void coreboot_table_setup(void *base)
} }
switch (read_le32(&entry->tag)) { switch (read_le32(&entry->tag)) {
case CB_TAG_MEMORY:
size = read_le32(&entry->size) -
offsetof(cb_entry_t, memranges);
if (size > sizeof(coreboot_memranges)) {
ERROR("Need to truncate coreboot memranges!\n");
size = sizeof(coreboot_memranges);
}
memcpy(&coreboot_memranges, &entry->memranges, size);
break;
case CB_TAG_SERIAL: case CB_TAG_SERIAL:
memcpy(&coreboot_serial, &entry->serial, memcpy(&coreboot_serial, &entry->serial,
sizeof(coreboot_serial)); sizeof(coreboot_serial));

Loading…
Cancel
Save