LCOV - code coverage report
Current view: top level - drivers/pci - rom.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 56 0.0 %
Date: 2023-03-27 20:00:47 Functions: 0 5 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * PCI ROM access routines
       4             :  *
       5             :  * (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com>
       6             :  * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com>
       7             :  */
       8             : #include <linux/kernel.h>
       9             : #include <linux/export.h>
      10             : #include <linux/pci.h>
      11             : #include <linux/slab.h>
      12             : 
      13             : #include "pci.h"
      14             : 
      15             : /**
      16             :  * pci_enable_rom - enable ROM decoding for a PCI device
      17             :  * @pdev: PCI device to enable
      18             :  *
      19             :  * Enable ROM decoding on @dev.  This involves simply turning on the last
      20             :  * bit of the PCI ROM BAR.  Note that some cards may share address decoders
      21             :  * between the ROM and other resources, so enabling it may disable access
      22             :  * to MMIO registers or other card memory.
      23             :  */
      24           0 : int pci_enable_rom(struct pci_dev *pdev)
      25             : {
      26           0 :         struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
      27             :         struct pci_bus_region region;
      28             :         u32 rom_addr;
      29             : 
      30           0 :         if (!res->flags)
      31             :                 return -1;
      32             : 
      33             :         /* Nothing to enable if we're using a shadow copy in RAM */
      34           0 :         if (res->flags & IORESOURCE_ROM_SHADOW)
      35             :                 return 0;
      36             : 
      37             :         /*
      38             :          * Ideally pci_update_resource() would update the ROM BAR address,
      39             :          * and we would only set the enable bit here.  But apparently some
      40             :          * devices have buggy ROM BARs that read as zero when disabled.
      41             :          */
      42           0 :         pcibios_resource_to_bus(pdev->bus, &region, res);
      43           0 :         pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
      44           0 :         rom_addr &= ~PCI_ROM_ADDRESS_MASK;
      45           0 :         rom_addr |= region.start | PCI_ROM_ADDRESS_ENABLE;
      46           0 :         pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
      47           0 :         return 0;
      48             : }
      49             : EXPORT_SYMBOL_GPL(pci_enable_rom);
      50             : 
      51             : /**
      52             :  * pci_disable_rom - disable ROM decoding for a PCI device
      53             :  * @pdev: PCI device to disable
      54             :  *
      55             :  * Disable ROM decoding on a PCI device by turning off the last bit in the
      56             :  * ROM BAR.
      57             :  */
      58           0 : void pci_disable_rom(struct pci_dev *pdev)
      59             : {
      60           0 :         struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
      61             :         u32 rom_addr;
      62             : 
      63           0 :         if (res->flags & IORESOURCE_ROM_SHADOW)
      64           0 :                 return;
      65             : 
      66           0 :         pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
      67           0 :         rom_addr &= ~PCI_ROM_ADDRESS_ENABLE;
      68           0 :         pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
      69             : }
      70             : EXPORT_SYMBOL_GPL(pci_disable_rom);
      71             : 
      72             : /**
      73             :  * pci_get_rom_size - obtain the actual size of the ROM image
      74             :  * @pdev: target PCI device
      75             :  * @rom: kernel virtual pointer to image of ROM
      76             :  * @size: size of PCI window
      77             :  *  return: size of actual ROM image
      78             :  *
      79             :  * Determine the actual length of the ROM image.
      80             :  * The PCI window size could be much larger than the
      81             :  * actual image size.
      82             :  */
      83           0 : static size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom,
      84             :                                size_t size)
      85             : {
      86             :         void __iomem *image;
      87             :         int last_image;
      88             :         unsigned int length;
      89             : 
      90           0 :         image = rom;
      91             :         do {
      92             :                 void __iomem *pds;
      93             :                 /* Standard PCI ROMs start out with these bytes 55 AA */
      94           0 :                 if (readw(image) != 0xAA55) {
      95           0 :                         pci_info(pdev, "Invalid PCI ROM header signature: expecting 0xaa55, got %#06x\n",
      96             :                                  readw(image));
      97           0 :                         break;
      98             :                 }
      99             :                 /* get the PCI data structure and check its "PCIR" signature */
     100           0 :                 pds = image + readw(image + 24);
     101           0 :                 if (readl(pds) != 0x52494350) {
     102           0 :                         pci_info(pdev, "Invalid PCI ROM data signature: expecting 0x52494350, got %#010x\n",
     103             :                                  readl(pds));
     104           0 :                         break;
     105             :                 }
     106           0 :                 last_image = readb(pds + 21) & 0x80;
     107           0 :                 length = readw(pds + 16);
     108           0 :                 image += length * 512;
     109             :                 /* Avoid iterating through memory outside the resource window */
     110           0 :                 if (image >= rom + size)
     111             :                         break;
     112           0 :                 if (!last_image) {
     113           0 :                         if (readw(image) != 0xAA55) {
     114           0 :                                 pci_info(pdev, "No more image in the PCI ROM\n");
     115           0 :                                 break;
     116             :                         }
     117             :                 }
     118           0 :         } while (length && !last_image);
     119             : 
     120             :         /* never return a size larger than the PCI resource window */
     121             :         /* there are known ROMs that get the size wrong */
     122           0 :         return min((size_t)(image - rom), size);
     123             : }
     124             : 
     125             : /**
     126             :  * pci_map_rom - map a PCI ROM to kernel space
     127             :  * @pdev: pointer to pci device struct
     128             :  * @size: pointer to receive size of pci window over ROM
     129             :  *
     130             :  * Return: kernel virtual pointer to image of ROM
     131             :  *
     132             :  * Map a PCI ROM into kernel space. If ROM is boot video ROM,
     133             :  * the shadow BIOS copy will be returned instead of the
     134             :  * actual ROM.
     135             :  */
     136           0 : void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
     137             : {
     138           0 :         struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
     139             :         loff_t start;
     140             :         void __iomem *rom;
     141             : 
     142             :         /* assign the ROM an address if it doesn't have one */
     143           0 :         if (res->parent == NULL && pci_assign_resource(pdev, PCI_ROM_RESOURCE))
     144             :                 return NULL;
     145             : 
     146           0 :         start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
     147           0 :         *size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
     148           0 :         if (*size == 0)
     149             :                 return NULL;
     150             : 
     151             :         /* Enable ROM space decodes */
     152           0 :         if (pci_enable_rom(pdev))
     153             :                 return NULL;
     154             : 
     155           0 :         rom = ioremap(start, *size);
     156           0 :         if (!rom)
     157             :                 goto err_ioremap;
     158             : 
     159             :         /*
     160             :          * Try to find the true size of the ROM since sometimes the PCI window
     161             :          * size is much larger than the actual size of the ROM.
     162             :          * True size is important if the ROM is going to be copied.
     163             :          */
     164           0 :         *size = pci_get_rom_size(pdev, rom, *size);
     165           0 :         if (!*size)
     166             :                 goto invalid_rom;
     167             : 
     168             :         return rom;
     169             : 
     170             : invalid_rom:
     171           0 :         iounmap(rom);
     172             : err_ioremap:
     173             :         /* restore enable if ioremap fails */
     174           0 :         if (!(res->flags & IORESOURCE_ROM_ENABLE))
     175           0 :                 pci_disable_rom(pdev);
     176             :         return NULL;
     177             : }
     178             : EXPORT_SYMBOL(pci_map_rom);
     179             : 
     180             : /**
     181             :  * pci_unmap_rom - unmap the ROM from kernel space
     182             :  * @pdev: pointer to pci device struct
     183             :  * @rom: virtual address of the previous mapping
     184             :  *
     185             :  * Remove a mapping of a previously mapped ROM
     186             :  */
     187           0 : void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
     188             : {
     189           0 :         struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
     190             : 
     191           0 :         iounmap(rom);
     192             : 
     193             :         /* Disable again before continuing */
     194           0 :         if (!(res->flags & IORESOURCE_ROM_ENABLE))
     195           0 :                 pci_disable_rom(pdev);
     196           0 : }
     197             : EXPORT_SYMBOL(pci_unmap_rom);

Generated by: LCOV version 1.14