summaryrefslogtreecommitdiffstats
path: root/cbtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'cbtable.c')
-rw-r--r--cbtable.c77
1 files changed, 62 insertions, 15 deletions
diff --git a/cbtable.c b/cbtable.c
index 6185f125a..dd6a0b956 100644
--- a/cbtable.c
+++ b/cbtable.c
@@ -26,6 +26,7 @@
#include "flash.h"
#include "programmer.h"
#include "coreboot_tables.h"
+#include "hwaccess_physmap.h"
static char *cb_vendor = NULL, *cb_model = NULL;
@@ -158,7 +159,7 @@ static int lb_header_valid(struct lb_header *head, unsigned long addr)
msg_pdbg("Found candidate at: %08lx-%08lx\n",
addr, addr + sizeof(*head) + head->table_bytes);
if (head->header_bytes != sizeof(*head)) {
- msg_perr("Header bytes of %d are incorrect.\n",
+ msg_perr("Header bytes of %"PRId32" are incorrect.\n",
head->header_bytes);
return 0;
}
@@ -174,12 +175,12 @@ static int lb_table_valid(struct lb_header *head, struct lb_record *recs)
{
if (compute_checksum(recs, head->table_bytes)
!= head->table_checksum) {
- msg_perr("Bad table checksum: %04x.\n",
+ msg_perr("Bad table checksum: %04"PRIx32".\n",
head->table_checksum);
return 0;
}
if (count_lb_records(head) != head->table_entries) {
- msg_perr("Bad record count: %d.\n",
+ msg_perr("Bad record count: %"PRId32".\n",
head->table_entries);
return 0;
}
@@ -210,6 +211,62 @@ static struct lb_header *find_lb_table(void *base, unsigned long start,
return NULL;
}
+static struct lb_header *find_lb_table_remap(unsigned long start_addr,
+ uint8_t **table_area)
+{
+ size_t offset;
+ unsigned long 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 (end = getpagesize(); offset < end; offset += 16) {
+ struct lb_record *recs;
+ struct lb_header *head;
+
+ /* No more headers to check. */
+ if (end - offset < sizeof(*head))
+ return NULL;
+
+ head = (struct lb_header *)(((char *)base) + offset);
+
+ if (!lb_header_valid(head, offset))
+ continue;
+
+ if (mapping_size - offset < head->table_bytes + sizeof(*head)) {
+ size_t prev_mapping_size = mapping_size;
+ mapping_size = head->table_bytes + sizeof(*head);
+ mapping_size += offset;
+ 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");
+ else
+ head = (struct lb_header *)(((char *)base) + offset);
+ }
+
+ recs = (struct lb_record *)(((char *)base) + offset + sizeof(*head));
+ if (!lb_table_valid(head, recs))
+ continue;
+ msg_pdbg("Found coreboot table at 0x%08zx.\n", offset);
+ *table_area = base;
+ return head;
+ }
+
+ physunmap(base, mapping_size);
+ return NULL;
+}
+
static void find_mainboard(struct lb_record *ptr, unsigned long addr)
{
struct lb_mainboard *rec;
@@ -238,13 +295,10 @@ static struct lb_record *next_record(struct lb_record *rec)
static void search_lb_records(struct lb_record *rec, struct lb_record *last, unsigned long addr)
{
struct lb_record *next;
- int count;
- count = 0;
for (next = next_record(rec); (rec < last) && (next <= last);
rec = next, addr += rec->size) {
next = next_record(rec);
- count++;
if (rec->tag == LB_TAG_MAINBOARD) {
find_mainboard(rec, addr);
break;
@@ -283,15 +337,8 @@ int cb_parse_table(const char **vendor, const char **model)
(((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);
}
}
@@ -305,7 +352,7 @@ int cb_parse_table(const char **vendor, const char **model)
(unsigned long)lb_table - (unsigned long)table_area + start);
rec = (struct lb_record *)(((char *)lb_table) + lb_table->header_bytes);
last = (struct lb_record *)(((char *)rec) + lb_table->table_bytes);
- msg_pdbg("coreboot header(%d) checksum: %04x table(%d) checksum: %04x entries: %d\n",
+ msg_pdbg("coreboot header(%"PRId32") checksum: %04"PRIx32" table(%"PRId32") checksum: %04"PRIx32" entries: %"PRId32"\n",
lb_table->header_bytes, lb_table->header_checksum,
lb_table->table_bytes, lb_table->table_checksum,
lb_table->table_entries);