mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 06:14:58 +00:00
Kernel: Use new PCI BAR API in IOWindow and correct IO bounds checks
The IO bounds checks were on 32 bit instead of the actual limit of 16 bit, which would have caused problems later down the line.
This commit is contained in:
parent
bd118f4eb0
commit
adac43ab1c
1 changed files with 11 additions and 22 deletions
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <Kernel/Bus/PCI/API.h>
|
||||
#include <Kernel/Bus/PCI/BarMapping.h>
|
||||
#include <Kernel/Bus/PCI/Definitions.h>
|
||||
#include <Kernel/Library/IOWindow.h>
|
||||
|
||||
|
@ -68,24 +69,18 @@ ErrorOr<NonnullOwnPtr<IOWindow>> 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<PCI::HeaderType0BaseRegister>(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<u64>::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<u16>::max())
|
||||
return Error::from_errno(EOVERFLOW);
|
||||
if (Checked<u16>::addition_would_overflow(static_cast<u16>(pci_bar_value), static_cast<u16>(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<NonnullOwnPtr<IOWindow>> IOWindow::create_for_pci_device_bar(PCI::Device
|
|||
#endif
|
||||
}
|
||||
|
||||
if (pci_bar_space_type == PCI::BARSpaceType::Memory32BitSpace && Checked<u32>::addition_would_overflow(pci_bar_value, space_length))
|
||||
return Error::from_errno(EOVERFLOW);
|
||||
if (pci_bar_space_type == PCI::BARSpaceType::Memory16BitSpace && Checked<u16>::addition_would_overflow(pci_bar_value, space_length))
|
||||
return Error::from_errno(EOVERFLOW);
|
||||
if (pci_bar_space_type == PCI::BARSpaceType::Memory64BitSpace && Checked<u64>::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<u8 volatile>(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<u8 volatile>(pci_device_identifier, pci_bar, space_length));
|
||||
return TRY(adopt_nonnull_own_or_enomem(new (nothrow) IOWindow(move(memory_mapped_range))));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue