probe_roms.c (mdadm-4.1) | : | probe_roms.c (mdadm-4.2) | ||
---|---|---|---|---|
skipping to change at line 38 | skipping to change at line 38 | |||
#include <sys/stat.h> | #include <sys/stat.h> | |||
#include <sys/types.h> | #include <sys/types.h> | |||
#include <asm/types.h> | #include <asm/types.h> | |||
static void *rom_mem = MAP_FAILED; | static void *rom_mem = MAP_FAILED; | |||
static int rom_fd = -1; | static int rom_fd = -1; | |||
static const int rom_len = 0xf0000 - 0xc0000; /* option-rom memory region */ | static const int rom_len = 0xf0000 - 0xc0000; /* option-rom memory region */ | |||
static int _sigbus; | static int _sigbus; | |||
static unsigned long rom_align; | static unsigned long rom_align; | |||
static void roms_deinit(void); | ||||
static int roms_init(void); | ||||
static void sigbus(int sig) | static void sigbus(int sig) | |||
{ | { | |||
_sigbus = 1; | _sigbus = 1; | |||
} | } | |||
static int probe_address8(const __u8 *ptr, __u8 *val) | static int probe_address8(const __u8 *ptr, __u8 *val) | |||
{ | { | |||
int rc = 0; | int rc = 0; | |||
*val = *ptr; | *val = *ptr; | |||
skipping to change at line 78 | skipping to change at line 81 | |||
{ | { | |||
signal(SIGBUS, SIG_DFL); | signal(SIGBUS, SIG_DFL); | |||
if (rom_fd >= 0) { | if (rom_fd >= 0) { | |||
close(rom_fd); | close(rom_fd); | |||
rom_fd = -1; | rom_fd = -1; | |||
} | } | |||
if (rom_mem != MAP_FAILED) { | if (rom_mem != MAP_FAILED) { | |||
munmap(rom_mem, rom_len); | munmap(rom_mem, rom_len); | |||
rom_mem = MAP_FAILED; | rom_mem = MAP_FAILED; | |||
} | } | |||
roms_deinit(); | ||||
} | } | |||
int probe_roms_init(unsigned long align) | int probe_roms_init(unsigned long align) | |||
{ | { | |||
int fd = -1; | int fd = -1; | |||
int rc = 0; | int rc = 0; | |||
/* valid values are 2048 and 512. 512 is for PCI-3.0 compliant | /* valid values are 2048 and 512. 512 is for PCI-3.0 compliant | |||
* systems, or systems that do not have dangerous/legacy ISA | * systems, or systems that do not have dangerous/legacy ISA | |||
* devices. 2048 should always be safe | * devices. 2048 should always be safe | |||
*/ | */ | |||
if (align == 512 || align == 2048) | if (align == 512 || align == 2048) | |||
rom_align = align; | rom_align = align; | |||
else | else | |||
return -1; | return -1; | |||
if (roms_init()) | ||||
return -1; | ||||
if (signal(SIGBUS, sigbus) == SIG_ERR) | if (signal(SIGBUS, sigbus) == SIG_ERR) | |||
rc = -1; | rc = -1; | |||
if (rc == 0) { | if (rc == 0) { | |||
fd = open("/dev/mem", O_RDONLY); | fd = open("/dev/mem", O_RDONLY); | |||
if (fd < 0) | if (fd < 0) | |||
rc = -1; | rc = -1; | |||
} | } | |||
if (rc == 0) { | if (rc == 0) { | |||
rom_mem = mmap(NULL, rom_len, PROT_READ, MAP_PRIVATE, fd, 0xc0000 ); | rom_mem = mmap(NULL, rom_len, PROT_READ, MAP_PRIVATE, fd, 0xc0000 ); | |||
if (rom_mem == MAP_FAILED) | if (rom_mem == MAP_FAILED) | |||
skipping to change at line 134 | skipping to change at line 141 | |||
static void *isa_bus_to_virt(unsigned long addr) | static void *isa_bus_to_virt(unsigned long addr) | |||
{ | { | |||
return rom_mem + (addr - 0xc0000); | return rom_mem + (addr - 0xc0000); | |||
} | } | |||
struct resource { | struct resource { | |||
unsigned long start; | unsigned long start; | |||
unsigned long end; | unsigned long end; | |||
unsigned long data; | unsigned long data; | |||
const char *name; | const char *name; | |||
struct resource *next; | ||||
}; | }; | |||
static struct resource system_rom_resource = { | static struct resource system_rom_resource = { | |||
.name = "System ROM", | .name = "System ROM", | |||
.start = 0xf0000, | .start = 0xf0000, | |||
.data = 0, | .data = 0, | |||
.end = 0xfffff, | .end = 0xfffff, | |||
}; | }; | |||
static struct resource extension_rom_resource = { | static struct resource extension_rom_resource = { | |||
.name = "Extension ROM", | .name = "Extension ROM", | |||
.start = 0xe0000, | .start = 0xe0000, | |||
.data = 0, | .data = 0, | |||
.end = 0xeffff, | .end = 0xeffff, | |||
}; | }; | |||
static struct resource adapter_rom_resources[] = { { | static struct resource *adapter_rom_resources; | |||
.name = "Adapter ROM", | ||||
.start = 0xc8000, | ||||
.data = 0, | ||||
.end = 0, | ||||
}, { | ||||
.name = "Adapter ROM", | ||||
.start = 0, | ||||
.data = 0, | ||||
.end = 0, | ||||
}, { | ||||
.name = "Adapter ROM", | ||||
.start = 0, | ||||
.data = 0, | ||||
.end = 0, | ||||
}, { | ||||
.name = "Adapter ROM", | ||||
.start = 0, | ||||
.data = 0, | ||||
.end = 0, | ||||
}, { | ||||
.name = "Adapter ROM", | ||||
.start = 0, | ||||
.data = 0, | ||||
.end = 0, | ||||
}, { | ||||
.name = "Adapter ROM", | ||||
.start = 0, | ||||
.data = 0, | ||||
.end = 0, | ||||
} }; | ||||
static struct resource video_rom_resource = { | static struct resource video_rom_resource = { | |||
.name = "Video ROM", | .name = "Video ROM", | |||
.start = 0xc0000, | .start = 0xc0000, | |||
.data = 0, | .data = 0, | |||
.end = 0xc7fff, | .end = 0xc7fff, | |||
}; | }; | |||
static int roms_init(void) | ||||
{ | ||||
adapter_rom_resources = malloc(sizeof(struct resource)); | ||||
if (adapter_rom_resources == NULL) | ||||
return 1; | ||||
adapter_rom_resources->name = "Adapter ROM"; | ||||
adapter_rom_resources->start = 0xc8000; | ||||
adapter_rom_resources->data = 0; | ||||
adapter_rom_resources->end = 0; | ||||
adapter_rom_resources->next = NULL; | ||||
return 0; | ||||
} | ||||
static void roms_deinit(void) | ||||
{ | ||||
struct resource *res; | ||||
res = adapter_rom_resources; | ||||
while (res) { | ||||
struct resource *tmp = res; | ||||
res = res->next; | ||||
free(tmp); | ||||
} | ||||
} | ||||
#define ROMSIGNATURE 0xaa55 | #define ROMSIGNATURE 0xaa55 | |||
static int romsignature(const unsigned char *rom) | static int romsignature(const unsigned char *rom) | |||
{ | { | |||
const unsigned short * const ptr = (const unsigned short *)rom; | const unsigned short * const ptr = (const unsigned short *)rom; | |||
unsigned short sig = 0; | unsigned short sig = 0; | |||
return probe_address16(ptr, &sig) == 0 && sig == ROMSIGNATURE; | return probe_address16(ptr, &sig) == 0 && sig == ROMSIGNATURE; | |||
} | } | |||
skipping to change at line 211 | skipping to change at line 215 | |||
unsigned char sum, c; | unsigned char sum, c; | |||
for (sum = 0; length && probe_address8(rom++, &c) == 0; length--) | for (sum = 0; length && probe_address8(rom++, &c) == 0; length--) | |||
sum += c; | sum += c; | |||
return !length && !sum; | return !length && !sum; | |||
} | } | |||
int scan_adapter_roms(scan_fn fn) | int scan_adapter_roms(scan_fn fn) | |||
{ | { | |||
/* let scan_fn examing each of the adapter roms found by probe_roms */ | /* let scan_fn examing each of the adapter roms found by probe_roms */ | |||
unsigned int i; | struct resource *res = adapter_rom_resources; | |||
int found; | int found; | |||
if (rom_fd < 0) | if (rom_fd < 0) | |||
return 0; | return 0; | |||
found = 0; | found = 0; | |||
for (i = 0; i < ARRAY_SIZE(adapter_rom_resources); i++) { | while (res) { | |||
struct resource *res = &adapter_rom_resources[i]; | ||||
if (res->start) { | if (res->start) { | |||
found = fn(isa_bus_to_virt(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)); | isa_bus_to_virt(res->data)); | |||
if (found) | if (found) | |||
break; | break; | |||
} else | } else | |||
break; | break; | |||
res = res->next; | ||||
} | } | |||
return found; | return found; | |||
} | } | |||
static unsigned long align(unsigned long addr, unsigned long alignment) | static unsigned long align(unsigned long addr, unsigned long alignment) | |||
{ | { | |||
return (addr + alignment - 1) & ~(alignment - 1); | return (addr + alignment - 1) & ~(alignment - 1); | |||
} | } | |||
void probe_roms(void) | void probe_roms(void) | |||
{ | { | |||
const void *rom; | const void *rom; | |||
unsigned long start, length, upper; | unsigned long start, length, upper; | |||
unsigned char c; | unsigned char c; | |||
unsigned int i; | struct resource *res = adapter_rom_resources; | |||
__u16 val=0; | __u16 val=0; | |||
if (rom_fd < 0) | if (rom_fd < 0) | |||
return; | return; | |||
/* video rom */ | /* video rom */ | |||
upper = adapter_rom_resources[0].start; | upper = res->start; | |||
for (start = video_rom_resource.start; start < upper; start += rom_align) { | for (start = video_rom_resource.start; start < upper; start += rom_align) { | |||
rom = isa_bus_to_virt(start); | rom = isa_bus_to_virt(start); | |||
if (!romsignature(rom)) | if (!romsignature(rom)) | |||
continue; | continue; | |||
video_rom_resource.start = start; | video_rom_resource.start = start; | |||
if (probe_address8(rom + 2, &c) != 0) | if (probe_address8(rom + 2, &c) != 0) | |||
continue; | continue; | |||
skipping to change at line 286 | skipping to change at line 289 | |||
upper = system_rom_resource.start; | upper = system_rom_resource.start; | |||
/* check for extension rom (ignore length byte!) */ | /* check for extension rom (ignore length byte!) */ | |||
rom = isa_bus_to_virt(extension_rom_resource.start); | rom = isa_bus_to_virt(extension_rom_resource.start); | |||
if (romsignature(rom)) { | if (romsignature(rom)) { | |||
length = extension_rom_resource.end - extension_rom_resource.star t + 1; | length = extension_rom_resource.end - extension_rom_resource.star t + 1; | |||
if (romchecksum(rom, length)) | if (romchecksum(rom, length)) | |||
upper = extension_rom_resource.start; | upper = extension_rom_resource.start; | |||
} | } | |||
struct resource *prev_res = res; | ||||
/* check for adapter roms on 2k boundaries */ | /* check for adapter roms on 2k boundaries */ | |||
for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += rom_align) { | for (; start < upper; start += rom_align) { | |||
rom = isa_bus_to_virt(start); | rom = isa_bus_to_virt(start); | |||
if (!romsignature(rom)) | if (!romsignature(rom)) | |||
continue; | continue; | |||
if (probe_address8(rom + 2, &c) != 0) | if (probe_address8(rom + 2, &c) != 0) | |||
continue; | continue; | |||
/* 0 < length <= 0x7f * 512, historically */ | /* 0 < length <= 0x7f * 512, historically */ | |||
length = c * 512; | length = c * 512; | |||
skipping to change at line 311 | skipping to change at line 315 | |||
*/ | */ | |||
if (probe_address16(rom + 0x18, &val) != 0) | if (probe_address16(rom + 0x18, &val) != 0) | |||
continue; | continue; | |||
val = __le16_to_cpu(val); | val = __le16_to_cpu(val); | |||
/* but accept any length that fits if checksum okay */ | /* but accept any length that fits if checksum okay */ | |||
if (!length || start + length > upper || !romchecksum(rom, length )) | if (!length || start + length > upper || !romchecksum(rom, length )) | |||
continue; | continue; | |||
adapter_rom_resources[i].start = start; | if (res == NULL) { | |||
adapter_rom_resources[i].data = start + (unsigned long) val; | res = calloc(1, sizeof(struct resource)); | |||
adapter_rom_resources[i].end = start + length - 1; | if (res == NULL) | |||
return; | ||||
start = adapter_rom_resources[i++].end & ~(rom_align - 1); | prev_res->next = res; | |||
} | ||||
res->start = start; | ||||
res->data = start + (unsigned long)val; | ||||
res->end = start + length - 1; | ||||
start = res->end & ~(rom_align - 1); | ||||
prev_res = res; | ||||
res = res->next; | ||||
} | } | |||
} | } | |||
End of changes. 14 change blocks. | ||||
43 lines changed or deleted | 56 lines changed or added |