1#include <linux/sched.h> 2#include <linux/mm.h> 3#include <linux/uaccess.h> 4#include <linux/mmzone.h> 5#include <linux/ioport.h> 6#include <linux/seq_file.h> 7#include <linux/console.h> 8#include <linux/init.h> 9#include <linux/edd.h> 10#include <linux/dmi.h> 11#include <linux/pfn.h> 12#include <linux/pci.h> 13#include <asm/pci-direct.h> 14 15 16#include <asm/e820.h> 17#include <asm/mmzone.h> 18#include <asm/setup.h> 19#include <asm/sections.h> 20#include <asm/io.h> 21#include <asm/setup_arch.h> 22 23static struct resource system_rom_resource = { 24 .name = "System ROM", 25 .start = 0xf0000, 26 .end = 0xfffff, 27 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM 28}; 29 30static struct resource extension_rom_resource = { 31 .name = "Extension ROM", 32 .start = 0xe0000, 33 .end = 0xeffff, 34 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM 35}; 36 37static struct resource adapter_rom_resources[] = { { 38 .name = "Adapter ROM", 39 .start = 0xc8000, 40 .end = 0, 41 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM 42}, { 43 .name = "Adapter ROM", 44 .start = 0, 45 .end = 0, 46 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM 47}, { 48 .name = "Adapter ROM", 49 .start = 0, 50 .end = 0, 51 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM 52}, { 53 .name = "Adapter ROM", 54 .start = 0, 55 .end = 0, 56 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM 57}, { 58 .name = "Adapter ROM", 59 .start = 0, 60 .end = 0, 61 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM 62}, { 63 .name = "Adapter ROM", 64 .start = 0, 65 .end = 0, 66 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM 67} }; 68 69static struct resource video_rom_resource = { 70 .name = "Video ROM", 71 .start = 0xc0000, 72 .end = 0xc7fff, 73 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM 74}; 75 76#define ROMSIGNATURE 0xaa55 77 78static int __init romsignature(const unsigned char *rom) 79{ 80 const unsigned short * const ptr = (const unsigned short *)rom; 81 unsigned short sig; 82 83 return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE; 84} 85 86static int __init romchecksum(const unsigned char *rom, unsigned long length) 87{ 88 unsigned char sum, c; 89 90 for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--) 91 sum += c; 92 return !length && !sum; 93} 94 95void __init probe_roms(void) 96{ 97 const unsigned char *rom; 98 unsigned long start, length, upper; 99 unsigned char c; 100 int i; 101 102 /* video rom */ 103 upper = adapter_rom_resources[0].start; 104 for (start = video_rom_resource.start; start < upper; start += 2048) { 105 rom = isa_bus_to_virt(start); 106 if (!romsignature(rom)) 107 continue; 108 109 video_rom_resource.start = start; 110 111 if (probe_kernel_address(rom + 2, c) != 0) 112 continue; 113 114 /* 0 < length <= 0x7f * 512, historically */ 115 length = c * 512; 116 117 /* if checksum okay, trust length byte */ 118 if (length && romchecksum(rom, length)) 119 video_rom_resource.end = start + length - 1; 120 121 request_resource(&iomem_resource, &video_rom_resource); 122 break; 123 } 124 125 start = (video_rom_resource.end + 1 + 2047) & ~2047UL; 126 if (start < upper) 127 start = upper; 128 129 /* system rom */ 130 request_resource(&iomem_resource, &system_rom_resource); 131 upper = system_rom_resource.start; 132 133 /* check for extension rom (ignore length byte!) */ 134 rom = isa_bus_to_virt(extension_rom_resource.start); 135 if (romsignature(rom)) { 136 length = extension_rom_resource.end - extension_rom_resource.start + 1; 137 if (romchecksum(rom, length)) { 138 request_resource(&iomem_resource, &extension_rom_resource); 139 upper = extension_rom_resource.start; 140 } 141 } 142 143 /* check for adapter roms on 2k boundaries */ 144 for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) { 145 rom = isa_bus_to_virt(start); 146 if (!romsignature(rom)) 147 continue; 148 149 if (probe_kernel_address(rom + 2, c) != 0) 150 continue; 151 152 /* 0 < length <= 0x7f * 512, historically */ 153 length = c * 512; 154 155 /* but accept any length that fits if checksum okay */ 156 if (!length || start + length > upper || !romchecksum(rom, length)) 157 continue; 158 159 adapter_rom_resources[i].start = start; 160 adapter_rom_resources[i].end = start + length - 1; 161 request_resource(&iomem_resource, &adapter_rom_resources[i]); 162 163 start = adapter_rom_resources[i++].end & ~2047UL; 164 } 165} 166