Skip to content

uefi-raw: Add binding for EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL #1658

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions uefi-raw/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# uefi-raw - [Unreleased]

## Added
- Added `AllocateType`.
- Added `PciRootBridgeIoProtocol`.


# uefi-raw - 0.11.0 (2025-05-04)

Expand Down
1 change: 1 addition & 0 deletions uefi-raw/src/protocol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub mod memory_protection;
pub mod misc;
pub mod network;
pub mod nvme;
pub mod pci;
pub mod rng;
pub mod scsi;
pub mod shell_params;
Expand Down
3 changes: 3 additions & 0 deletions uefi-raw/src/protocol/pci/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

pub mod root_bridge;
181 changes: 181 additions & 0 deletions uefi-raw/src/protocol/pci/root_bridge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

use crate::table::boot::{AllocateType, MemoryType};
use crate::{Handle, PhysicalAddress, Status};
use core::ffi::c_void;
use uguid::{guid, Guid};

newtype_enum! {
/// Corresponds to the `EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH` enum.
pub enum PciRootBridgeIoProtocolWidth: u32 => {
UINT8 = 0,
UINT16 = 1,
UINT32 = 2,
UINT64 = 3,
FIFO_UINT8 = 4,
FIFO_UINT16 = 5,
FIFO_UINT32 = 6,
FIFO_UINT64 = 7,
FILL_UINT8 = 8,
FILL_UINT16 = 9,
FILL_UINT32 = 10,
FILL_UINT64 = 11,
MAXIMUM = 12,
}
}

newtype_enum! {
/// Corresponds to the `EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION` enum.
pub enum PciRootBridgeIoProtocolOperation: u32 => {
BUS_MASTER_READ = 0,
BUS_MASTER_WRITE = 1,
BUS_MASTER_COMMON_BUFFER = 2,
BUS_MASTER_READ64 = 3,
BUS_MASTER_WRITE64 = 4,
BUS_MASTER_COMMON_BUFFER64 = 5,
MAXIMUM = 6,
}
}

/// Structure representing a PCI Address for Pci.Read() and Pci.Write()
#[repr(C, packed)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PciIoAddress {
pub reg: u8,
pub fun: u8,
pub dev: u8,
pub bus: u8,
pub ext_reg: u32,
}

impl PciIoAddress {
/// Create address pointing to the device identified by `bus`, `dev` and `fun` ids.
#[must_use]
pub const fn new(bus: u8, dev: u8, fun: u8) -> Self {
Self {
bus,
dev,
fun,
reg: 0,
ext_reg: 0,
}
}

/// Configure the **byte**-offset of the register to access.
#[must_use]
pub const fn with_register(&self, reg: u8) -> Self {
let mut addr = *self;
addr.reg = reg;
addr.ext_reg = 0;
addr
}

/// Configure the **byte**-offset of the extended register to access.
#[must_use]
pub const fn with_extended_register(&self, ext_reg: u32) -> Self {
let mut addr = *self;
addr.reg = 0;
addr.ext_reg = ext_reg;
addr
}
}

impl From<PciIoAddress> for u64 {
fn from(value: PciIoAddress) -> Self {
unsafe { core::mem::transmute(value) }
}
}

#[derive(Debug)]
#[repr(C)]
pub struct PciRootBridgeIoAccess {
pub read: unsafe extern "efiapi" fn(
this: *mut PciRootBridgeIoProtocol,
width: PciRootBridgeIoProtocolWidth,
address: u64,
count: usize,
buffer: *mut c_void,
) -> Status,
pub write: unsafe extern "efiapi" fn(
this: *mut PciRootBridgeIoProtocol,
width: PciRootBridgeIoProtocolWidth,
address: u64,
count: usize,
buffer: *const c_void,
) -> Status,
}

#[derive(Debug)]
#[repr(C)]
pub struct PciRootBridgeIoProtocol {
pub parent_handle: Handle,
pub poll_mem: unsafe extern "efiapi" fn(
this: *mut Self,
width: PciRootBridgeIoProtocolWidth,
address: u64,
mask: u64,
value: u64,
delay: u64,
result: *mut u64,
) -> Status,
pub poll_io: unsafe extern "efiapi" fn(
this: *mut Self,
width: PciRootBridgeIoProtocolWidth,
address: u64,
mask: u64,
value: u64,
delay: u64,
result: *mut u64,
) -> Status,
pub mem: PciRootBridgeIoAccess,
pub io: PciRootBridgeIoAccess,
pub pci: PciRootBridgeIoAccess,
pub copy_mem: unsafe extern "efiapi" fn(
this: *mut Self,
width: PciRootBridgeIoProtocolWidth,
dest_addr: u64,
src_addr: u64,
count: usize,
) -> Status,
pub map: unsafe extern "efiapi" fn(
this: *const Self,
operation: PciRootBridgeIoProtocolOperation,
host_addr: *const c_void,
num_bytes: *mut usize,
device_addr: *mut PhysicalAddress,
mapping: *mut *mut c_void,
) -> Status,
pub unmap: unsafe extern "efiapi" fn(this: *const Self, mapping: *const c_void) -> Status,
pub allocate_buffer: unsafe extern "efiapi" fn(
this: *const Self,
alloc_ty: AllocateType,
memory_ty: MemoryType,
pages: usize,
host_addr: *mut *const c_void,
attributes: u64,
) -> Status,
pub free_buffer: unsafe extern "efiapi" fn(
this: *const Self,
pages: usize,
host_addr: *const c_void,
) -> Status,
pub flush: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
pub get_attributes: unsafe extern "efiapi" fn(
this: *const Self,
supports: *mut u64,
attributes: *mut u64,
) -> Status,
pub set_attributes: unsafe extern "efiapi" fn(
this: *mut Self,
attributes: u64,
resource_base: *mut u64,
resource_length: *mut u64,
) -> Status,
pub configuration:
unsafe extern "efiapi" fn(this: *const Self, resources: *mut *const c_void) -> Status,
pub segment_number: u32,
}

impl PciRootBridgeIoProtocol {
pub const GUID: Guid = guid!("2f707ebb-4a1a-11d4-9a38-0090273fc14d");
}
11 changes: 10 additions & 1 deletion uefi-raw/src/table/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ use bitflags::bitflags;
use core::ffi::c_void;
use core::ops::RangeInclusive;

newtype_enum! {
pub enum AllocateType: u32 => {
ANY_PAGES = 0,
MAX_ADDRESS = 1,
ADDRESS = 2,
MAX_ALLOCATE_TYPE = 3,
}
}

/// Table of pointers to all the boot services.
#[derive(Debug)]
#[repr(C)]
Expand All @@ -21,7 +30,7 @@ pub struct BootServices {

// Memory allocation functions
pub allocate_pages: unsafe extern "efiapi" fn(
alloc_ty: u32,
alloc_ty: AllocateType,
mem_ty: MemoryType,
count: usize,
addr: *mut PhysicalAddress,
Expand Down
8 changes: 4 additions & 4 deletions uefi/src/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use core::ptr::{self, NonNull};
use core::sync::atomic::{AtomicPtr, Ordering};
use core::time::Duration;
use core::{mem, slice};
use uefi_raw::table::boot::{InterfaceType, TimerDelay};
use uefi_raw::table::boot::{AllocateType as RawAllocateType, InterfaceType, TimerDelay};
#[cfg(feature = "alloc")]
use {alloc::vec::Vec, uefi::ResultExt};

Expand Down Expand Up @@ -136,9 +136,9 @@ pub fn allocate_pages(ty: AllocateType, mem_ty: MemoryType, count: usize) -> Res
let bt = unsafe { bt.as_ref() };

let (ty, initial_addr) = match ty {
AllocateType::AnyPages => (0, 0),
AllocateType::MaxAddress(addr) => (1, addr),
AllocateType::Address(addr) => (2, addr),
AllocateType::AnyPages => (RawAllocateType::ANY_PAGES, 0),
AllocateType::MaxAddress(addr) => (RawAllocateType::MAX_ADDRESS, addr),
AllocateType::Address(addr) => (RawAllocateType::ADDRESS, addr),
};

let mut addr1 = initial_addr;
Expand Down