diff options
author | John Keller <jpk@sgi.com> | 2007-07-09 11:42:24 -0700 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2007-07-09 13:37:18 -0700 |
commit | d7ad2254fa7cc11aec3faeba076c1243f6adeb47 (patch) | |
tree | 900c05b11a3a44f19618701172ffb5f51ecdeb99 /drivers/pci/rom.c | |
parent | 83ce6ef8408bbc7d9322ab50ba592f83012dea94 (diff) | |
download | lwn-d7ad2254fa7cc11aec3faeba076c1243f6adeb47.tar.gz lwn-d7ad2254fa7cc11aec3faeba076c1243f6adeb47.zip |
[IA64] SN: Correct ROM resource length for BIOS copy
On SN systems, when setting the IORESOURCE_ROM_BIOS_COPY resource flag,
the resource length should be set to the actual size of the ROM image
so that a call to pci_map_rom() returns the correct size.
Signed-off-by: John Keller <jpk@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'drivers/pci/rom.c')
-rw-r--r-- | drivers/pci/rom.c | 73 |
1 files changed, 44 insertions, 29 deletions
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index d087e0817715..dbbcc04abd1a 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -54,6 +54,49 @@ static void pci_disable_rom(struct pci_dev *pdev) } /** + * pci_get_rom_size - obtain the actual size of the ROM image + * @rom: kernel virtual pointer to image of ROM + * @size: size of PCI window + * return: size of actual ROM image + * + * Determine the actual length of the ROM image. + * The PCI window size could be much larger than the + * actual image size. + */ +size_t pci_get_rom_size(void __iomem *rom, size_t size) +{ + void __iomem *image; + int last_image; + + image = rom; + do { + void __iomem *pds; + /* Standard PCI ROMs start out with these bytes 55 AA */ + if (readb(image) != 0x55) + break; + if (readb(image + 1) != 0xAA) + break; + /* get the PCI data structure and check its signature */ + pds = image + readw(image + 24); + if (readb(pds) != 'P') + break; + if (readb(pds + 1) != 'C') + break; + if (readb(pds + 2) != 'I') + break; + if (readb(pds + 3) != 'R') + break; + last_image = readb(pds + 21) & 0x80; + /* this length is reliable */ + image += readw(pds + 16) * 512; + } while (!last_image); + + /* never return a size larger than the PCI resource window */ + /* there are known ROMs that get the size wrong */ + return min((size_t)(image - rom), size); +} + +/** * pci_map_rom - map a PCI ROM to kernel space * @pdev: pointer to pci device struct * @size: pointer to receive size of pci window over ROM @@ -68,8 +111,6 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; loff_t start; void __iomem *rom; - void __iomem *image; - int last_image; /* * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy @@ -117,33 +158,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) * size is much larger than the actual size of the ROM. * True size is important if the ROM is going to be copied. */ - image = rom; - do { - void __iomem *pds; - /* Standard PCI ROMs start out with these bytes 55 AA */ - if (readb(image) != 0x55) - break; - if (readb(image + 1) != 0xAA) - break; - /* get the PCI data structure and check its signature */ - pds = image + readw(image + 24); - if (readb(pds) != 'P') - break; - if (readb(pds + 1) != 'C') - break; - if (readb(pds + 2) != 'I') - break; - if (readb(pds + 3) != 'R') - break; - last_image = readb(pds + 21) & 0x80; - /* this length is reliable */ - image += readw(pds + 16) * 512; - } while (!last_image); - - /* never return a size larger than the PCI resource window */ - /* there are known ROMs that get the size wrong */ - *size = min((size_t)(image - rom), *size); - + *size = pci_get_rom_size(rom, *size); return rom; } |