From 9421727c708e6b30831a24c190938ea2951a771b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ky=C3=B6sti=20M=C3=A4lkki?= Date: Mon, 11 Mar 2019 18:26:01 +0200 Subject: arch/x86: Fix PCI IO config accessor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case PCI_IO_CFG_EXT=n parameter 'reg' was not properly truncated to 8 bits and it would overflow to dev.fn part of the register. A similar thing could happen with 'dev' but that value originates from PCI_DEV() macro unlike 'reg'. Change-Id: Id2888e07fc0f2b182b4633a747c1786e5c560678 Signed-off-by: Kyösti Mälkki Reviewed-on: https://review.coreboot.org/c/coreboot/+/31847 Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- src/arch/x86/include/arch/pci_io_cfg.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'src/arch') diff --git a/src/arch/x86/include/arch/pci_io_cfg.h b/src/arch/x86/include/arch/pci_io_cfg.h index 6c88b3cf5e..1e6934abcc 100644 --- a/src/arch/x86/include/arch/pci_io_cfg.h +++ b/src/arch/x86/include/arch/pci_io_cfg.h @@ -21,19 +21,22 @@ static __always_inline uint32_t pci_io_encode_addr(pci_devfn_t dev, uint16_t reg) { - if (CONFIG(PCI_IO_CFG_EXT)) { - // seg == 0 - return dev >> 4 | (reg & 0xff) | ((reg & 0xf00) << 16); - } else { - return dev >> 4 | reg; - } + uint32_t addr = 1 << 31; + + addr |= dev >> 4; + addr |= reg & 0xfc; + + if (CONFIG(PCI_IO_CFG_EXT)) + addr |= (reg & 0xf00) << 16; + + return addr; } static __always_inline uint8_t pci_io_read_config8(pci_devfn_t dev, uint16_t reg) { uint32_t addr = pci_io_encode_addr(dev, reg); - outl(0x80000000 | (addr & ~3), 0xCF8); + outl(addr, 0xCF8); return inb(0xCFC + (reg & 3)); } @@ -41,7 +44,7 @@ static __always_inline uint16_t pci_io_read_config16(pci_devfn_t dev, uint16_t reg) { uint32_t addr = pci_io_encode_addr(dev, reg); - outl(0x80000000 | (addr & ~3), 0xCF8); + outl(addr, 0xCF8); return inw(0xCFC + (reg & 2)); } @@ -49,7 +52,7 @@ static __always_inline uint32_t pci_io_read_config32(pci_devfn_t dev, uint16_t reg) { uint32_t addr = pci_io_encode_addr(dev, reg); - outl(0x80000000 | (addr & ~3), 0xCF8); + outl(addr, 0xCF8); return inl(0xCFC); } @@ -57,7 +60,7 @@ static __always_inline void pci_io_write_config8(pci_devfn_t dev, uint16_t reg, uint8_t value) { uint32_t addr = pci_io_encode_addr(dev, reg); - outl(0x80000000 | (addr & ~3), 0xCF8); + outl(addr, 0xCF8); outb(value, 0xCFC + (reg & 3)); } @@ -65,7 +68,7 @@ static __always_inline void pci_io_write_config16(pci_devfn_t dev, uint16_t reg, uint16_t value) { uint32_t addr = pci_io_encode_addr(dev, reg); - outl(0x80000000 | (addr & ~3), 0xCF8); + outl(addr, 0xCF8); outw(value, 0xCFC + (reg & 2)); } @@ -73,7 +76,7 @@ static __always_inline void pci_io_write_config32(pci_devfn_t dev, uint16_t reg, uint32_t value) { uint32_t addr = pci_io_encode_addr(dev, reg); - outl(0x80000000 | (addr & ~3), 0xCF8); + outl(addr, 0xCF8); outl(value, 0xCFC); } -- cgit v1.2.3