From 969c255511a4bd12e6becc11b2a822f24c1fbb76 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 31 Jul 2009 17:11:41 -0700 Subject: [PATCH] platform: relax rom scanning alignment for ahci platforms The PCI-3.0 Firmware specification allows for option-roms to have 512-byte alignment rather than 2048-byte. As there does not appear to be a reliable method to detect a PCI-3.0 compliant BIOS from userspace we allow the imsm platform detection code to presume that a system modern enough to have an Intel AHCI controller does not have dangerous/legacy ISA regions in the option-ROM memory space. An environment variable to disable this behaviour, IMSM_SAFE_OROM_SCAN, is added in case this presumption is ever proven wrong. Reported-by: Hans de Goede Signed-off-by: Dan Williams --- platform-intel.c | 7 ++++++- probe_roms.c | 26 +++++++++++++++++++++----- probe_roms.h | 2 +- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/platform-intel.c b/platform-intel.c index 5160227..eaf4c48 100644 --- a/platform-intel.c +++ b/platform-intel.c @@ -157,6 +157,7 @@ static int scan(const void *start, const void *end) const struct imsm_orom *find_imsm_orom(void) { static int populated = 0; + unsigned long align; /* it's static data so we only need to read it once */ if (populated) @@ -184,7 +185,11 @@ const struct imsm_orom *find_imsm_orom(void) return NULL; /* scan option-rom memory looking for an imsm signature */ - if (probe_roms_init() != 0) + if (check_env("IMSM_SAFE_OROM_SCAN")) + align = 2048; + else + align = 512; + if (probe_roms_init(align) != 0) return NULL; probe_roms(); populated = scan_adapter_roms(scan); diff --git a/probe_roms.c b/probe_roms.c index 06ec3f5..a9a8638 100644 --- a/probe_roms.c +++ b/probe_roms.c @@ -32,6 +32,8 @@ static void *rom_mem = MAP_FAILED; static int rom_fd = -1; const static int rom_len = 0xf0000 - 0xc0000; /* option-rom memory region */ static int _sigbus; +static unsigned long rom_align; + #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) static void sigbus(int sig) @@ -76,11 +78,20 @@ void probe_roms_exit(void) } } -int probe_roms_init(void) +int probe_roms_init(unsigned long align) { int fd; int rc = 0; + /* valid values are 2048 and 512. 512 is for PCI-3.0 compliant + * systems, or systems that do not have dangerous/legacy ISA + * devices. 2048 should always be safe + */ + if (align == 512 || align == 2048) + rom_align = align; + else + return -1; + if (signal(SIGBUS, sigbus) == SIG_ERR) rc = -1; if (rc == 0) { @@ -208,6 +219,11 @@ int scan_adapter_roms(scan_fn fn) return found; } +static unsigned long align(unsigned long addr, unsigned long alignment) +{ + return (addr + alignment - 1) & ~(alignment - 1); +} + void probe_roms(void) { const void *rom; @@ -220,7 +236,7 @@ void probe_roms(void) /* video rom */ upper = adapter_rom_resources[0].start; - for (start = video_rom_resource.start; start < upper; start += 2048) { + for (start = video_rom_resource.start; start < upper; start += rom_align) { rom = isa_bus_to_virt(start); if (!romsignature(rom)) continue; @@ -239,7 +255,7 @@ void probe_roms(void) break; } - start = (video_rom_resource.end + 1 + 2047) & ~2047UL; + start = align(video_rom_resource.end + 1, rom_align); if (start < upper) start = upper; @@ -255,7 +271,7 @@ void probe_roms(void) } /* check for adapter roms on 2k boundaries */ - for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) { + for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += rom_align) { rom = isa_bus_to_virt(start); if (!romsignature(rom)) continue; @@ -273,7 +289,7 @@ void probe_roms(void) adapter_rom_resources[i].start = start; adapter_rom_resources[i].end = start + length - 1; - start = adapter_rom_resources[i++].end & ~2047UL; + start = adapter_rom_resources[i++].end & ~(rom_align - 1); } } diff --git a/probe_roms.h b/probe_roms.h index 557e933..a1e291a 100644 --- a/probe_roms.h +++ b/probe_roms.h @@ -18,7 +18,7 @@ */ void probe_roms_exit(void); -int probe_roms_init(void); +int probe_roms_init(unsigned long align); typedef int (*scan_fn)(const void *start, const void *end); int scan_adapter_roms(scan_fn fn); void probe_roms(void);