summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cbtable.c16
-rw-r--r--flash.h1
-rw-r--r--physmap.c55
3 files changed, 65 insertions, 7 deletions
diff --git a/cbtable.c b/cbtable.c
index 2611a62..c12354c 100644
--- a/cbtable.c
+++ b/cbtable.c
@@ -6,6 +6,7 @@
* (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
* Copyright (C) 2006-2009 coresystems GmbH
* (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
+ * Copyright (C) 2010 Carl-Daniel Hailfinger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -207,11 +208,15 @@ int coreboot_init(void)
#else
start = 0x0;
#endif
- table_area = physmap("low megabyte", start, BYTES_TO_MAP);
+ table_area = physmap_try_ro("low megabyte", start, BYTES_TO_MAP - start);
+ if (!table_area) {
+ msg_perr("Failed getting access to coreboot low tables.\n");
+ return -1;
+ }
lb_table = find_lb_table(table_area, 0x00000, 0x1000);
if (!lb_table)
- lb_table = find_lb_table(table_area, 0xf0000, BYTES_TO_MAP);
+ lb_table = find_lb_table(table_area, 0xf0000 - start, BYTES_TO_MAP - start);
if (lb_table) {
struct lb_forward *forward = (struct lb_forward *)
(((char *)lb_table) + lb_table->header_bytes);
@@ -219,7 +224,12 @@ int coreboot_init(void)
start = forward->forward;
start &= ~(getpagesize() - 1);
physunmap(table_area, BYTES_TO_MAP);
- table_area = physmap("high tables", start, BYTES_TO_MAP);
+ table_area = physmap_try_ro("high tables", start, BYTES_TO_MAP);
+ if (!table_area) {
+ msg_perr("Failed getting access to coreboot "
+ "high tables.\n");
+ return -1;
+ }
lb_table = find_lb_table(table_area, 0x00000, 0x1000);
}
}
diff --git a/flash.h b/flash.h
index 3d31d44..d8f02bb 100644
--- a/flash.h
+++ b/flash.h
@@ -343,6 +343,7 @@ int chipset_flash_enable(void);
/* physmap.c */
void *physmap(const char *descr, unsigned long phys_addr, size_t len);
+void *physmap_try_ro(const char *descr, unsigned long phys_addr, size_t len);
void physunmap(void *virt_addr, size_t len);
int setup_cpu_msr(int cpu);
void cleanup_cpu_msr(void);
diff --git a/physmap.c b/physmap.c
index 3a003fe..fba7a53 100644
--- a/physmap.c
+++ b/physmap.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2009 Peter Stuge <peter@stuge.se>
* Copyright (C) 2009 coresystems GmbH
+ * Copyright (C) 2010 Carl-Daniel Hailfinger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,6 +37,10 @@ void *sys_physmap(unsigned long phys_addr, size_t len)
return map_physical(phys_addr, len);
}
+/* The OS X driver does not differentiate between mapping types. */
+#define sys_physmap_rw_uncached sys_physmap
+#define sys_physmap_ro_cached sys_physmap
+
void physunmap(void *virt_addr, size_t len)
{
unmap_physical(virt_addr, len);
@@ -51,8 +56,10 @@ void physunmap(void *virt_addr, size_t len)
#endif
static int fd_mem = -1;
+static int fd_mem_cached = -1;
-void *sys_physmap(unsigned long phys_addr, size_t len)
+/* For MMIO access. Must be uncached, doesn't make sense to restrict to ro. */
+void *sys_physmap_rw_uncached(unsigned long phys_addr, size_t len)
{
void *virt_addr;
@@ -69,6 +76,26 @@ void *sys_physmap(unsigned long phys_addr, size_t len)
return MAP_FAILED == virt_addr ? NULL : virt_addr;
}
+/* For reading DMI/coreboot/whatever tables. We should never write, and we
+ * do not care about caching.
+ */
+void *sys_physmap_ro_cached(unsigned long phys_addr, size_t len)
+{
+ void *virt_addr;
+
+ if (-1 == fd_mem_cached) {
+ /* Open the memory device CACHED. */
+ if (-1 == (fd_mem_cached = open(MEM_DEV, O_RDWR))) {
+ perror("Critical error: open(" MEM_DEV ")");
+ exit(2);
+ }
+ }
+
+ virt_addr = mmap(0, len, PROT_READ, MAP_SHARED,
+ fd_mem_cached, (off_t)phys_addr);
+ return MAP_FAILED == virt_addr ? NULL : virt_addr;
+}
+
void physunmap(void *virt_addr, size_t len)
{
if (len == 0) {
@@ -80,7 +107,12 @@ void physunmap(void *virt_addr, size_t len)
}
#endif
-void *physmap(const char *descr, unsigned long phys_addr, size_t len)
+#define PHYSMAP_NOFAIL 0
+#define PHYSMAP_MAYFAIL 1
+#define PHYSMAP_RW 0
+#define PHYSMAP_RO 1
+
+void *physmap_common(const char *descr, unsigned long phys_addr, size_t len, int mayfail, int readonly)
{
void *virt_addr;
@@ -100,7 +132,11 @@ void *physmap(const char *descr, unsigned long phys_addr, size_t len)
descr, (unsigned long)len, phys_addr);
}
- virt_addr = sys_physmap(phys_addr, len);
+ if (readonly) {
+ virt_addr = sys_physmap_ro_cached(phys_addr, len);
+ } else {
+ virt_addr = sys_physmap_rw_uncached(phys_addr, len);
+ }
if (NULL == virt_addr) {
if (NULL == descr)
@@ -114,12 +150,23 @@ void *physmap(const char *descr, unsigned long phys_addr, size_t len)
fprintf(stderr, "You can override CONFIG_X86_PAT at boot with the nopat kernel parameter but\n");
fprintf(stderr, "disabling the other option unfortunately requires a kernel recompile. Sorry!\n");
}
- exit(3);
+ if (!mayfail)
+ exit(3);
}
return virt_addr;
}
+void *physmap(const char *descr, unsigned long phys_addr, size_t len)
+{
+ return physmap_common(descr, phys_addr, len, PHYSMAP_NOFAIL, PHYSMAP_RW);
+}
+
+void *physmap_try_ro(const char *descr, unsigned long phys_addr, size_t len)
+{
+ return physmap_common(descr, phys_addr, len, PHYSMAP_MAYFAIL, PHYSMAP_RO);
+}
+
#ifdef __linux__
/*
* Reading and writing to MSRs, however requires instructions rdmsr/wrmsr,
OpenPOWER on IntegriCloud