1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/sched.h>
4 #include <linux/uaccess.h>
5 #include <linux/mmzone.h>
6 #include <linux/ioport.h>
7 #include <linux/seq_file.h>
8 #include <linux/console.h>
9 #include <linux/init.h>
10 #include <linux/edd.h>
11 #include <linux/dmi.h>
12 #include <linux/pfn.h>
13 #include <linux/pci.h>
14 #include <linux/export.h>
16 #include <asm/probe_roms.h>
17 #include <asm/pci-direct.h>
18 #include <asm/e820/api.h>
19 #include <asm/mmzone.h>
20 #include <asm/setup.h>
21 #include <asm/sections.h>
23 #include <asm/setup_arch.h>
25 static struct resource system_rom_resource
= {
29 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
32 static struct resource extension_rom_resource
= {
33 .name
= "Extension ROM",
36 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
39 static struct resource adapter_rom_resources
[] = { {
40 .name
= "Adapter ROM",
43 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
45 .name
= "Adapter ROM",
48 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
50 .name
= "Adapter ROM",
53 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
55 .name
= "Adapter ROM",
58 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
60 .name
= "Adapter ROM",
63 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
65 .name
= "Adapter ROM",
68 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
71 static struct resource video_rom_resource
= {
75 .flags
= IORESOURCE_BUSY
| IORESOURCE_READONLY
| IORESOURCE_MEM
78 /* does this oprom support the given pci device, or any of the devices
79 * that the driver supports?
81 static bool match_id(struct pci_dev
*pdev
, unsigned short vendor
, unsigned short device
)
83 struct pci_driver
*drv
= pdev
->driver
;
84 const struct pci_device_id
*id
;
86 if (pdev
->vendor
== vendor
&& pdev
->device
== device
)
89 for (id
= drv
? drv
->id_table
: NULL
; id
&& id
->vendor
; id
++)
90 if (id
->vendor
== vendor
&& id
->device
== device
)
93 return id
&& id
->vendor
;
96 static bool probe_list(struct pci_dev
*pdev
, unsigned short vendor
,
97 const unsigned char *rom_list
)
99 unsigned short device
;
102 if (probe_kernel_address(rom_list
, device
) != 0)
105 if (device
&& match_id(pdev
, vendor
, device
))
114 static struct resource
*find_oprom(struct pci_dev
*pdev
)
116 struct resource
*oprom
= NULL
;
119 for (i
= 0; i
< ARRAY_SIZE(adapter_rom_resources
); i
++) {
120 struct resource
*res
= &adapter_rom_resources
[i
];
121 unsigned short offset
, vendor
, device
, list
, rev
;
122 const unsigned char *rom
;
127 rom
= isa_bus_to_virt(res
->start
);
128 if (probe_kernel_address(rom
+ 0x18, offset
) != 0)
131 if (probe_kernel_address(rom
+ offset
+ 0x4, vendor
) != 0)
134 if (probe_kernel_address(rom
+ offset
+ 0x6, device
) != 0)
137 if (match_id(pdev
, vendor
, device
)) {
142 if (probe_kernel_address(rom
+ offset
+ 0x8, list
) == 0 &&
143 probe_kernel_address(rom
+ offset
+ 0xc, rev
) == 0 &&
145 probe_list(pdev
, vendor
, rom
+ offset
+ list
)) {
154 void __iomem
*pci_map_biosrom(struct pci_dev
*pdev
)
156 struct resource
*oprom
= find_oprom(pdev
);
161 return ioremap(oprom
->start
, resource_size(oprom
));
163 EXPORT_SYMBOL(pci_map_biosrom
);
165 void pci_unmap_biosrom(void __iomem
*image
)
169 EXPORT_SYMBOL(pci_unmap_biosrom
);
171 size_t pci_biosrom_size(struct pci_dev
*pdev
)
173 struct resource
*oprom
= find_oprom(pdev
);
175 return oprom
? resource_size(oprom
) : 0;
177 EXPORT_SYMBOL(pci_biosrom_size
);
179 #define ROMSIGNATURE 0xaa55
181 static int __init
romsignature(const unsigned char *rom
)
183 const unsigned short * const ptr
= (const unsigned short *)rom
;
186 return probe_kernel_address(ptr
, sig
) == 0 && sig
== ROMSIGNATURE
;
189 static int __init
romchecksum(const unsigned char *rom
, unsigned long length
)
191 unsigned char sum
, c
;
193 for (sum
= 0; length
&& probe_kernel_address(rom
++, c
) == 0; length
--)
195 return !length
&& !sum
;
198 void __init
probe_roms(void)
200 const unsigned char *rom
;
201 unsigned long start
, length
, upper
;
206 upper
= adapter_rom_resources
[0].start
;
207 for (start
= video_rom_resource
.start
; start
< upper
; start
+= 2048) {
208 rom
= isa_bus_to_virt(start
);
209 if (!romsignature(rom
))
212 video_rom_resource
.start
= start
;
214 if (probe_kernel_address(rom
+ 2, c
) != 0)
217 /* 0 < length <= 0x7f * 512, historically */
220 /* if checksum okay, trust length byte */
221 if (length
&& romchecksum(rom
, length
))
222 video_rom_resource
.end
= start
+ length
- 1;
224 request_resource(&iomem_resource
, &video_rom_resource
);
228 start
= (video_rom_resource
.end
+ 1 + 2047) & ~2047UL;
233 request_resource(&iomem_resource
, &system_rom_resource
);
234 upper
= system_rom_resource
.start
;
236 /* check for extension rom (ignore length byte!) */
237 rom
= isa_bus_to_virt(extension_rom_resource
.start
);
238 if (romsignature(rom
)) {
239 length
= resource_size(&extension_rom_resource
);
240 if (romchecksum(rom
, length
)) {
241 request_resource(&iomem_resource
, &extension_rom_resource
);
242 upper
= extension_rom_resource
.start
;
246 /* check for adapter roms on 2k boundaries */
247 for (i
= 0; i
< ARRAY_SIZE(adapter_rom_resources
) && start
< upper
; start
+= 2048) {
248 rom
= isa_bus_to_virt(start
);
249 if (!romsignature(rom
))
252 if (probe_kernel_address(rom
+ 2, c
) != 0)
255 /* 0 < length <= 0x7f * 512, historically */
258 /* but accept any length that fits if checksum okay */
259 if (!length
|| start
+ length
> upper
|| !romchecksum(rom
, length
))
262 adapter_rom_resources
[i
].start
= start
;
263 adapter_rom_resources
[i
].end
= start
+ length
- 1;
264 request_resource(&iomem_resource
, &adapter_rom_resources
[i
]);
266 start
= adapter_rom_resources
[i
++].end
& ~2047UL;