diff --git a/Kernel/Library/IOWindow.cpp b/Kernel/Library/IOWindow.cpp index b89b94148a..de6d5beddf 100644 --- a/Kernel/Library/IOWindow.cpp +++ b/Kernel/Library/IOWindow.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -68,24 +69,18 @@ ErrorOr> IOWindow::create_for_pci_device_bar(PCI::Device { u64 pci_bar_value = PCI::get_BAR(pci_device_identifier, pci_bar); auto pci_bar_space_type = PCI::get_BAR_space_type(pci_bar_value); - if (pci_bar_space_type == PCI::BARSpaceType::Memory64BitSpace) { - // FIXME: In theory, BAR5 cannot be assigned to 64 bit as it is the last one... - // however, there might be 64 bit BAR5 for real bare metal hardware, so remove this - // if it makes a problem. - if (pci_bar == PCI::HeaderType0BaseRegister::BAR5) { - return Error::from_errno(EINVAL); - } - u64 next_pci_bar_value = PCI::get_BAR(pci_device_identifier, static_cast(to_underlying(pci_bar) + 1)); - pci_bar_value |= next_pci_bar_value << 32; - } - - auto pci_bar_space_size = PCI::get_BAR_space_size(pci_device_identifier, pci_bar); - if (pci_bar_space_size < space_length) - return Error::from_errno(EIO); if (pci_bar_space_type == PCI::BARSpaceType::IOSpace) { #if ARCH(X86_64) - if (Checked::addition_would_overflow(pci_bar_value, space_length)) + auto pci_bar_space_size = PCI::get_BAR_space_size(pci_device_identifier, pci_bar); + if (pci_bar_space_size < space_length) + return Error::from_errno(EIO); + + // X86 IO instructions use DX -a 16 bit register- as the "address" + // So we need to check against u16's + if (pci_bar_value > AK::NumericLimits::max()) + return Error::from_errno(EOVERFLOW); + if (Checked::addition_would_overflow(static_cast(pci_bar_value), static_cast(space_length))) return Error::from_errno(EOVERFLOW); auto io_address_range = TRY(adopt_nonnull_own_or_enomem(new (nothrow) IOAddressData((pci_bar_value & 0xfffffffc), space_length))); return TRY(adopt_nonnull_own_or_enomem(new (nothrow) IOWindow(move(io_address_range)))); @@ -95,13 +90,7 @@ ErrorOr> IOWindow::create_for_pci_device_bar(PCI::Device #endif } - if (pci_bar_space_type == PCI::BARSpaceType::Memory32BitSpace && Checked::addition_would_overflow(pci_bar_value, space_length)) - return Error::from_errno(EOVERFLOW); - if (pci_bar_space_type == PCI::BARSpaceType::Memory16BitSpace && Checked::addition_would_overflow(pci_bar_value, space_length)) - return Error::from_errno(EOVERFLOW); - if (pci_bar_space_type == PCI::BARSpaceType::Memory64BitSpace && Checked::addition_would_overflow(pci_bar_value, space_length)) - return Error::from_errno(EOVERFLOW); - auto memory_mapped_range = TRY(Memory::adopt_new_nonnull_own_typed_mapping(PhysicalAddress(pci_bar_value & PCI::bar_address_mask), space_length, Memory::Region::Access::ReadWrite)); + auto memory_mapped_range = TRY(PCI::adopt_new_nonnull_own_bar_mapping(pci_device_identifier, pci_bar, space_length)); return TRY(adopt_nonnull_own_or_enomem(new (nothrow) IOWindow(move(memory_mapped_range)))); }