X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=probe_roms.c;h=b0b088332bb6ab5f4acb8541a9f0b8b0e5676111;hb=b7d81a38c7be8019ceb812071021f0564bc61795;hp=0f0ffbccbdc8c1bb14ce158042c61d7ce658743f;hpb=922f66a935df8e6b3b66073a89c47c68c2e8cbe3;p=thirdparty%2Fmdadm.git diff --git a/probe_roms.c b/probe_roms.c index 0f0ffbcc..b0b08833 100644 --- a/probe_roms.c +++ b/probe_roms.c @@ -20,6 +20,7 @@ */ #include "probe_roms.h" +#include "mdadm.h" #include #include #include @@ -30,12 +31,10 @@ static void *rom_mem = MAP_FAILED; static int rom_fd = -1; -const static int rom_len = 0xf0000 - 0xc0000; /* option-rom memory region */ +static const 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) { _sigbus = 1; @@ -108,7 +107,7 @@ int probe_roms_init(unsigned long align) if (rc == 0) rom_fd = fd; else { - if (fd >= 0) + if (fd >= 0) close(fd); probe_roms_exit(); } @@ -130,50 +129,60 @@ static void *isa_bus_to_virt(unsigned long addr) struct resource { unsigned long start; unsigned long end; + unsigned long data; const char *name; }; static struct resource system_rom_resource = { .name = "System ROM", .start = 0xf0000, + .data = 0, .end = 0xfffff, }; static struct resource extension_rom_resource = { .name = "Extension ROM", .start = 0xe0000, + .data = 0, .end = 0xeffff, }; static struct resource adapter_rom_resources[] = { { - .name = "Adapter ROM", + .name = "Adapter ROM", .start = 0xc8000, + .data = 0, .end = 0, }, { - .name = "Adapter ROM", + .name = "Adapter ROM", .start = 0, + .data = 0, .end = 0, }, { - .name = "Adapter ROM", + .name = "Adapter ROM", .start = 0, + .data = 0, .end = 0, }, { - .name = "Adapter ROM", + .name = "Adapter ROM", .start = 0, + .data = 0, .end = 0, }, { - .name = "Adapter ROM", + .name = "Adapter ROM", .start = 0, + .data = 0, .end = 0, }, { - .name = "Adapter ROM", + .name = "Adapter ROM", .start = 0, + .data = 0, .end = 0, } }; static struct resource video_rom_resource = { - .name = "Video ROM", + .name = "Video ROM", .start = 0xc0000, + .data = 0, .end = 0xc7fff, }; @@ -199,7 +208,7 @@ static int romchecksum(const unsigned char *rom, unsigned long length) int scan_adapter_roms(scan_fn fn) { /* let scan_fn examing each of the adapter roms found by probe_roms */ - int i; + unsigned int i; int found; if (rom_fd < 0) @@ -211,7 +220,8 @@ int scan_adapter_roms(scan_fn fn) if (res->start) { found = fn(isa_bus_to_virt(res->start), - isa_bus_to_virt(res->end)); + isa_bus_to_virt(res->end), + isa_bus_to_virt(res->data)); if (found) break; } else @@ -231,7 +241,8 @@ void probe_roms(void) const void *rom; unsigned long start, length, upper; unsigned char c; - int i; + unsigned int i; + __u16 val=0; if (rom_fd < 0) return; @@ -284,14 +295,23 @@ void probe_roms(void) /* 0 < length <= 0x7f * 512, historically */ length = c * 512; + /* Retrieve 16-bit pointer to PCI Data Structure (offset 18h-19h) + * The data can be within 64KB forward of the first location + * of this code image. The pointer is in little-endian order + */ + + if (probe_address16(rom + 0x18, &val) != 0) + continue; + val = __le16_to_cpu(val); + /* but accept any length that fits if checksum okay */ if (!length || start + length > upper || !romchecksum(rom, length)) continue; adapter_rom_resources[i].start = start; + adapter_rom_resources[i].data = start + (unsigned long) val; adapter_rom_resources[i].end = start + length - 1; start = adapter_rom_resources[i++].end & ~(rom_align - 1); } } -