cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rom.c (5464B)


      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 */
     24int pci_enable_rom(struct pci_dev *pdev)
     25{
     26	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
     27	struct pci_bus_region region;
     28	u32 rom_addr;
     29
     30	if (!res->flags)
     31		return -1;
     32
     33	/* Nothing to enable if we're using a shadow copy in RAM */
     34	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	pcibios_resource_to_bus(pdev->bus, &region, res);
     43	pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
     44	rom_addr &= ~PCI_ROM_ADDRESS_MASK;
     45	rom_addr |= region.start | PCI_ROM_ADDRESS_ENABLE;
     46	pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
     47	return 0;
     48}
     49EXPORT_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 */
     58void pci_disable_rom(struct pci_dev *pdev)
     59{
     60	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
     61	u32 rom_addr;
     62
     63	if (res->flags & IORESOURCE_ROM_SHADOW)
     64		return;
     65
     66	pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
     67	rom_addr &= ~PCI_ROM_ADDRESS_ENABLE;
     68	pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
     69}
     70EXPORT_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 */
     83static 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	image = rom;
     91	do {
     92		void __iomem *pds;
     93		/* Standard PCI ROMs start out with these bytes 55 AA */
     94		if (readw(image) != 0xAA55) {
     95			pci_info(pdev, "Invalid PCI ROM header signature: expecting 0xaa55, got %#06x\n",
     96				 readw(image));
     97			break;
     98		}
     99		/* get the PCI data structure and check its "PCIR" signature */
    100		pds = image + readw(image + 24);
    101		if (readl(pds) != 0x52494350) {
    102			pci_info(pdev, "Invalid PCI ROM data signature: expecting 0x52494350, got %#010x\n",
    103				 readl(pds));
    104			break;
    105		}
    106		last_image = readb(pds + 21) & 0x80;
    107		length = readw(pds + 16);
    108		image += length * 512;
    109		/* Avoid iterating through memory outside the resource window */
    110		if (image >= rom + size)
    111			break;
    112		if (!last_image) {
    113			if (readw(image) != 0xAA55) {
    114				pci_info(pdev, "No more image in the PCI ROM\n");
    115				break;
    116			}
    117		}
    118	} 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	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 */
    136void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
    137{
    138	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	if (res->parent == NULL && pci_assign_resource(pdev, PCI_ROM_RESOURCE))
    144		return NULL;
    145
    146	start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
    147	*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
    148	if (*size == 0)
    149		return NULL;
    150
    151	/* Enable ROM space decodes */
    152	if (pci_enable_rom(pdev))
    153		return NULL;
    154
    155	rom = ioremap(start, *size);
    156	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	*size = pci_get_rom_size(pdev, rom, *size);
    165	if (!*size)
    166		goto invalid_rom;
    167
    168	return rom;
    169
    170invalid_rom:
    171	iounmap(rom);
    172err_ioremap:
    173	/* restore enable if ioremap fails */
    174	if (!(res->flags & IORESOURCE_ROM_ENABLE))
    175		pci_disable_rom(pdev);
    176	return NULL;
    177}
    178EXPORT_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 */
    187void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
    188{
    189	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
    190
    191	iounmap(rom);
    192
    193	/* Disable again before continuing */
    194	if (!(res->flags & IORESOURCE_ROM_ENABLE))
    195		pci_disable_rom(pdev);
    196}
    197EXPORT_SYMBOL(pci_unmap_rom);