Philip Prindeville (pprindeville@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/501
-gerrit
commit c3a4a4242a4c9d428638f271e95ed6d6d8cde2d4 Author: Philip Prindeville philipp@redfish-solutions.com Date: Fri Dec 23 18:09:25 2011 -0700
cb_parse_header() should not assume table in 4K of contiguous memory
If we have the CB table in E820 memory, we might not have an entire 4K (0x1000) bytes of memory to scan through. Instead, a better strategy is to pass in a pointer to the end of the region or the start + 4K (which ever is lower). This change prepares the cb_parse_header() calling convention for that change.
Change-Id: I9257726c6a7065b5596d4c32ab451edd0a3cdc10 Signed-off-by: Philip Prindeville philipp@redfish-solutions.com --- payloads/libpayload/arch/i386/coreboot.c | 22 ++++++++++++++-------- 1 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/payloads/libpayload/arch/i386/coreboot.c b/payloads/libpayload/arch/i386/coreboot.c index 709f8ae..135c59c 100644 --- a/payloads/libpayload/arch/i386/coreboot.c +++ b/payloads/libpayload/arch/i386/coreboot.c @@ -109,21 +109,21 @@ static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info) } #endif
-static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) +static int cb_parse_header(void *addr, void *end, struct sysinfo_t *info) { struct cb_header *header; - unsigned char *ptr = addr; + unsigned char *ptr; void *forward; int i;
- for (i = 0; i < len; i += 16, ptr += 16) { + for (ptr = addr; (void *)ptr < end; ptr += 16) { header = (struct cb_header *)ptr; if (!strncmp((const char *)header->signature, "LBIO", 4)) break; }
/* We walked the entire space and didn't find anything. */ - if (i >= len) + if ((void *)ptr >= end) return -1;
if (!header->table_bytes) @@ -147,7 +147,7 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) switch (rec->tag) { case CB_TAG_FORWARD: forward = phys_to_virt((void *)(unsigned long)((struct cb_forward *)rec)->forward); - return cb_parse_header(forward, len, info); + return cb_parse_header(forward, forward + 0x1000, info); continue; case CB_TAG_MEMORY: cb_parse_memory(ptr, info); @@ -176,6 +176,9 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) }
ptr += rec->size; + + if ((void *)ptr >= end) + return -1; }
return 1; @@ -186,10 +189,13 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
int get_coreboot_info(struct sysinfo_t *info) { - int ret = cb_parse_header(phys_to_virt(0x00000000), 0x1000, info); + void *base = phys_to_virt(0x00000000); + int ret = cb_parse_header(base, base + 0x1000, info);
- if (ret != 1) - ret = cb_parse_header(phys_to_virt(0x000f0000), 0x1000, info); + if (ret != 1) { + base = phys_to_virt(0x000f0000); + ret = cb_parse_header(base, base + 0x1000, info); + }
return (ret == 1) ? 0 : -1; }