Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/sched.h>
0003 #include <linux/mm.h>
0004 #include <linux/uaccess.h>
0005 #include <linux/mmzone.h>
0006 #include <linux/ioport.h>
0007 #include <linux/seq_file.h>
0008 #include <linux/console.h>
0009 #include <linux/init.h>
0010 #include <linux/edd.h>
0011 #include <linux/dmi.h>
0012 #include <linux/pfn.h>
0013 #include <linux/pci.h>
0014 #include <linux/export.h>
0015 
0016 #include <asm/probe_roms.h>
0017 #include <asm/pci-direct.h>
0018 #include <asm/e820/api.h>
0019 #include <asm/mmzone.h>
0020 #include <asm/setup.h>
0021 #include <asm/sections.h>
0022 #include <asm/io.h>
0023 #include <asm/setup_arch.h>
0024 #include <asm/sev.h>
0025 
0026 static struct resource system_rom_resource = {
0027     .name   = "System ROM",
0028     .start  = 0xf0000,
0029     .end    = 0xfffff,
0030     .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
0031 };
0032 
0033 static struct resource extension_rom_resource = {
0034     .name   = "Extension ROM",
0035     .start  = 0xe0000,
0036     .end    = 0xeffff,
0037     .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
0038 };
0039 
0040 static struct resource adapter_rom_resources[] = { {
0041     .name   = "Adapter ROM",
0042     .start  = 0xc8000,
0043     .end    = 0,
0044     .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
0045 }, {
0046     .name   = "Adapter ROM",
0047     .start  = 0,
0048     .end    = 0,
0049     .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
0050 }, {
0051     .name   = "Adapter ROM",
0052     .start  = 0,
0053     .end    = 0,
0054     .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
0055 }, {
0056     .name   = "Adapter ROM",
0057     .start  = 0,
0058     .end    = 0,
0059     .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
0060 }, {
0061     .name   = "Adapter ROM",
0062     .start  = 0,
0063     .end    = 0,
0064     .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
0065 }, {
0066     .name   = "Adapter ROM",
0067     .start  = 0,
0068     .end    = 0,
0069     .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
0070 } };
0071 
0072 static struct resource video_rom_resource = {
0073     .name   = "Video ROM",
0074     .start  = 0xc0000,
0075     .end    = 0xc7fff,
0076     .flags  = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
0077 };
0078 
0079 /* does this oprom support the given pci device, or any of the devices
0080  * that the driver supports?
0081  */
0082 static bool match_id(struct pci_dev *pdev, unsigned short vendor, unsigned short device)
0083 {
0084     struct pci_driver *drv = to_pci_driver(pdev->dev.driver);
0085     const struct pci_device_id *id;
0086 
0087     if (pdev->vendor == vendor && pdev->device == device)
0088         return true;
0089 
0090     for (id = drv ? drv->id_table : NULL; id && id->vendor; id++)
0091         if (id->vendor == vendor && id->device == device)
0092             break;
0093 
0094     return id && id->vendor;
0095 }
0096 
0097 static bool probe_list(struct pci_dev *pdev, unsigned short vendor,
0098                const void *rom_list)
0099 {
0100     unsigned short device;
0101 
0102     do {
0103         if (get_kernel_nofault(device, rom_list) != 0)
0104             device = 0;
0105 
0106         if (device && match_id(pdev, vendor, device))
0107             break;
0108 
0109         rom_list += 2;
0110     } while (device);
0111 
0112     return !!device;
0113 }
0114 
0115 static struct resource *find_oprom(struct pci_dev *pdev)
0116 {
0117     struct resource *oprom = NULL;
0118     int i;
0119 
0120     for (i = 0; i < ARRAY_SIZE(adapter_rom_resources); i++) {
0121         struct resource *res = &adapter_rom_resources[i];
0122         unsigned short offset, vendor, device, list, rev;
0123         const void *rom;
0124 
0125         if (res->end == 0)
0126             break;
0127 
0128         rom = isa_bus_to_virt(res->start);
0129         if (get_kernel_nofault(offset, rom + 0x18) != 0)
0130             continue;
0131 
0132         if (get_kernel_nofault(vendor, rom + offset + 0x4) != 0)
0133             continue;
0134 
0135         if (get_kernel_nofault(device, rom + offset + 0x6) != 0)
0136             continue;
0137 
0138         if (match_id(pdev, vendor, device)) {
0139             oprom = res;
0140             break;
0141         }
0142 
0143         if (get_kernel_nofault(list, rom + offset + 0x8) == 0 &&
0144             get_kernel_nofault(rev, rom + offset + 0xc) == 0 &&
0145             rev >= 3 && list &&
0146             probe_list(pdev, vendor, rom + offset + list)) {
0147             oprom = res;
0148             break;
0149         }
0150     }
0151 
0152     return oprom;
0153 }
0154 
0155 void __iomem *pci_map_biosrom(struct pci_dev *pdev)
0156 {
0157     struct resource *oprom = find_oprom(pdev);
0158 
0159     if (!oprom)
0160         return NULL;
0161 
0162     return ioremap(oprom->start, resource_size(oprom));
0163 }
0164 EXPORT_SYMBOL(pci_map_biosrom);
0165 
0166 void pci_unmap_biosrom(void __iomem *image)
0167 {
0168     iounmap(image);
0169 }
0170 EXPORT_SYMBOL(pci_unmap_biosrom);
0171 
0172 size_t pci_biosrom_size(struct pci_dev *pdev)
0173 {
0174     struct resource *oprom = find_oprom(pdev);
0175 
0176     return oprom ? resource_size(oprom) : 0;
0177 }
0178 EXPORT_SYMBOL(pci_biosrom_size);
0179 
0180 #define ROMSIGNATURE 0xaa55
0181 
0182 static int __init romsignature(const unsigned char *rom)
0183 {
0184     const unsigned short * const ptr = (const unsigned short *)rom;
0185     unsigned short sig;
0186 
0187     return get_kernel_nofault(sig, ptr) == 0 && sig == ROMSIGNATURE;
0188 }
0189 
0190 static int __init romchecksum(const unsigned char *rom, unsigned long length)
0191 {
0192     unsigned char sum, c;
0193 
0194     for (sum = 0; length && get_kernel_nofault(c, rom++) == 0; length--)
0195         sum += c;
0196     return !length && !sum;
0197 }
0198 
0199 void __init probe_roms(void)
0200 {
0201     unsigned long start, length, upper;
0202     const unsigned char *rom;
0203     unsigned char c;
0204     int i;
0205 
0206     /*
0207      * The ROM memory range is not part of the e820 table and is therefore not
0208      * pre-validated by BIOS. The kernel page table maps the ROM region as encrypted
0209      * memory, and SNP requires encrypted memory to be validated before access.
0210      * Do that here.
0211      */
0212     snp_prep_memory(video_rom_resource.start,
0213             ((system_rom_resource.end + 1) - video_rom_resource.start),
0214             SNP_PAGE_STATE_PRIVATE);
0215 
0216     /* video rom */
0217     upper = adapter_rom_resources[0].start;
0218     for (start = video_rom_resource.start; start < upper; start += 2048) {
0219         rom = isa_bus_to_virt(start);
0220         if (!romsignature(rom))
0221             continue;
0222 
0223         video_rom_resource.start = start;
0224 
0225         if (get_kernel_nofault(c, rom + 2) != 0)
0226             continue;
0227 
0228         /* 0 < length <= 0x7f * 512, historically */
0229         length = c * 512;
0230 
0231         /* if checksum okay, trust length byte */
0232         if (length && romchecksum(rom, length))
0233             video_rom_resource.end = start + length - 1;
0234 
0235         request_resource(&iomem_resource, &video_rom_resource);
0236         break;
0237     }
0238 
0239     start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
0240     if (start < upper)
0241         start = upper;
0242 
0243     /* system rom */
0244     request_resource(&iomem_resource, &system_rom_resource);
0245     upper = system_rom_resource.start;
0246 
0247     /* check for extension rom (ignore length byte!) */
0248     rom = isa_bus_to_virt(extension_rom_resource.start);
0249     if (romsignature(rom)) {
0250         length = resource_size(&extension_rom_resource);
0251         if (romchecksum(rom, length)) {
0252             request_resource(&iomem_resource, &extension_rom_resource);
0253             upper = extension_rom_resource.start;
0254         }
0255     }
0256 
0257     /* check for adapter roms on 2k boundaries */
0258     for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {
0259         rom = isa_bus_to_virt(start);
0260         if (!romsignature(rom))
0261             continue;
0262 
0263         if (get_kernel_nofault(c, rom + 2) != 0)
0264             continue;
0265 
0266         /* 0 < length <= 0x7f * 512, historically */
0267         length = c * 512;
0268 
0269         /* but accept any length that fits if checksum okay */
0270         if (!length || start + length > upper || !romchecksum(rom, length))
0271             continue;
0272 
0273         adapter_rom_resources[i].start = start;
0274         adapter_rom_resources[i].end = start + length - 1;
0275         request_resource(&iomem_resource, &adapter_rom_resources[i]);
0276 
0277         start = adapter_rom_resources[i++].end & ~2047UL;
0278     }
0279 }
0280