Edward O'Callaghan has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/45521 )
Change subject: cbtable.c: don't assume high addresses can fully map 1MB ......................................................................
cbtable.c: don't assume high addresses can fully map 1MB
I do not know a clean way to compose find_lb_table() and find_lb_table_remap() or why this cannot always been done.
However this is a fix ported from downstream found here: https://chromium-review.googlesource.com/685608
Change-Id: Ibf2323a0a793f693928b81c64acd09bb932a6b98 Signed-off-by: Edward O'Callaghan quasisec@google.com --- M cbtable.c 1 file changed, 61 insertions(+), 7 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/21/45521/1
diff --git a/cbtable.c b/cbtable.c index 6185f12..6dd4059 100644 --- a/cbtable.c +++ b/cbtable.c @@ -205,8 +205,68 @@ msg_pdbg("Found coreboot table at 0x%08lx.\n", addr); return head;
+ }; + + return NULL; +} + +static struct lb_header *find_lb_table_remap(unsigned long start_addr, + uint8_t **table_area) +{ + size_t offset; + unsigned long addr, end; + size_t mapping_size; + void *base; + + mapping_size = getpagesize(); + offset = start_addr % getpagesize(); + start_addr -= offset; + + base = physmap_ro("high tables", start_addr, mapping_size); + if (ERROR_PTR == base) { + msg_perr("Failed getting access to coreboot high tables.\n"); + return NULL; }
+ for (addr = offset, end = getpagesize(); addr < end; addr += 16) { + struct lb_record *recs; + struct lb_header *head; + + /* No more headers to check. */ + if (end - addr < sizeof(*head)) + return NULL; + + head = (struct lb_header *)(((char *)base) + addr); + + if (!lb_header_valid(head, addr)) + continue; + + if (mapping_size - addr < head->table_bytes + sizeof(*head)) { + size_t prev_mapping_size = mapping_size; + mapping_size = head->table_bytes + sizeof(*head); + mapping_size += addr; + mapping_size += getpagesize() - + (mapping_size % getpagesize()); + physunmap(base, prev_mapping_size); + base = physmap_ro("high tables", start_addr, + mapping_size); + if (ERROR_PTR == base) { + msg_perr("Failed getting access to coreboot high tables.\n"); + return NULL; + } + } + + head = (struct lb_header *)(((char *)base) + addr); + recs = + (struct lb_record *)(((char *)base) + addr + sizeof(*head)); + if (!lb_table_valid(head, recs)) + continue; + msg_pdbg("Found coreboot table at 0x%08lx.\n", addr); + *table_area = base; + return head; + } + + physunmap(base, mapping_size); return NULL; }
@@ -283,15 +343,9 @@ (((char *)lb_table) + lb_table->header_bytes); if (forward->tag == LB_TAG_FORWARD) { start = forward->forward; - start &= ~(getpagesize() - 1); physunmap_unaligned(table_area, BYTES_TO_MAP); // FIXME: table_area is never unmapped below, nor is it unmapped above in the no-forward case - table_area = physmap_ro_unaligned("high tables", start, BYTES_TO_MAP); - if (ERROR_PTR == table_area) { - msg_perr("Failed getting access to coreboot high tables.\n"); - return -1; - } - lb_table = find_lb_table(table_area, 0x00000, 0x1000); + lb_table = find_lb_table_remap(start, &table_area); } }