Skip to content

Commit d2c59fb

Browse files
committed
uefi: Use RefCell for allocate_buffer and map
1 parent 3157650 commit d2c59fb

File tree

5 files changed

+140
-86
lines changed

5 files changed

+140
-86
lines changed

uefi-test-runner/src/proto/pci/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ pub fn test() {
66
root_bridge::test_io();
77
root_bridge::test_buffer();
88
root_bridge::test_mapping();
9+
root_bridge::test_copy();
910
}

uefi-test-runner/src/proto/pci/root_bridge.rs

Lines changed: 69 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
// SPDX-License-Identifier: MIT OR Apache-2.0
22

3+
use core::cell::RefCell;
34
use core::mem;
4-
use qcell::{QCell, QCellOwner};
5-
use uefi::Handle;
6-
use uefi::boot::{OpenProtocolAttributes, OpenProtocolParams, ScopedProtocol, image_handle};
7-
use uefi::proto::ProtocolPointer;
8-
use uefi::proto::pci::PciIoAddress;
5+
use uefi::boot::{image_handle, OpenProtocolAttributes, OpenProtocolParams, ScopedProtocol};
96
use uefi::proto::pci::root_bridge::PciRootBridgeIo;
10-
use uefi_raw::protocol::pci::root_bridge::{PciRootBridgeIoProtocolAttribute, PciRootBridgeIoProtocolOperation, PciRootBridgeIoProtocolWidth};
7+
use uefi::proto::pci::PciIoAddress;
8+
use uefi::proto::ProtocolPointer;
9+
use uefi::Handle;
10+
use uefi_raw::protocol::pci::root_bridge::{
11+
PciRootBridgeIoProtocolAttribute, PciRootBridgeIoProtocolOperation,
12+
PciRootBridgeIoProtocolWidth,
13+
};
1114
use uefi_raw::table::boot::{MemoryType, PAGE_SIZE};
1215

1316
const RED_HAT_PCI_VENDOR_ID: u16 = 0x1AF4;
@@ -75,14 +78,15 @@ pub fn test_buffer() {
7578

7679
for pci_handle in pci_handles {
7780
let pci_proto = get_open_protocol::<PciRootBridgeIo>(pci_handle);
78-
79-
let mut buffer = pci_proto
80-
.allocate_buffer::<[u8; 4096]>(
81-
MemoryType::BOOT_SERVICES_DATA,
82-
None,
83-
PciRootBridgeIoProtocolAttribute::PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
84-
)
85-
.unwrap();
81+
let pci_proto: RefCell<_> = pci_proto.into();
82+
83+
let mut buffer = PciRootBridgeIo::allocate_buffer::<[u8; 4096]>(
84+
&pci_proto,
85+
MemoryType::BOOT_SERVICES_DATA,
86+
None,
87+
PciRootBridgeIoProtocolAttribute::PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
88+
)
89+
.unwrap();
8690
let buffer = unsafe {
8791
buffer.assume_init_mut().fill(0);
8892
buffer.assume_init()
@@ -96,19 +100,25 @@ pub fn test_mapping() {
96100

97101
for pci_handle in pci_handles {
98102
let pci_proto = get_open_protocol::<PciRootBridgeIo>(pci_handle);
99-
100-
let mut buffer = pci_proto
101-
.allocate_buffer::<[u8; 4096]>(
102-
MemoryType::BOOT_SERVICES_DATA,
103-
None,
104-
PciRootBridgeIoProtocolAttribute::PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
105-
)
106-
.unwrap();
103+
let pci_proto: RefCell<_> = pci_proto.into();
104+
105+
let mut buffer = PciRootBridgeIo::allocate_buffer::<[u8; 4096]>(
106+
&pci_proto,
107+
MemoryType::BOOT_SERVICES_DATA,
108+
None,
109+
PciRootBridgeIoProtocolAttribute::PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
110+
)
111+
.unwrap();
107112
let buffer = unsafe {
108113
buffer.assume_init_mut().fill(0);
109114
buffer.assume_init()
110115
};
111-
let mapped = pci_proto.map(PciRootBridgeIoProtocolOperation::BUS_MASTER_COMMON_BUFFER64, buffer.as_ref());
116+
117+
let mapped = PciRootBridgeIo::map(
118+
&pci_proto,
119+
PciRootBridgeIoProtocolOperation::BUS_MASTER_COMMON_BUFFER64,
120+
buffer.as_ref(),
121+
);
112122
if mapped.region().device_address == buffer.as_ptr().addr() as u64 {
113123
info!("This PCI device uses identity mapping");
114124
} else {
@@ -121,35 +131,48 @@ pub fn test_copy() {
121131
let pci_handles = uefi::boot::find_handles::<PciRootBridgeIo>().unwrap();
122132

123133
for pci_handle in pci_handles {
124-
let mut owner = QCellOwner::new();
125-
let item = QCell::new(&owner, get_open_protocol::<PciRootBridgeIo>(pci_handle));
126-
let pci_proto = owner.rw(&item);
127-
128-
let mut src = pci_proto
129-
.allocate_buffer::<[u32; 4096 / 4]>(
130-
MemoryType::BOOT_SERVICES_DATA,
131-
None,
132-
PciRootBridgeIoProtocolAttribute::PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
133-
)
134-
.unwrap();
134+
let pci_proto = get_open_protocol::<PciRootBridgeIo>(pci_handle);
135+
let pci_proto: RefCell<_> = pci_proto.into();
136+
137+
let mut src = PciRootBridgeIo::allocate_buffer::<[u32; 4096 / 4]>(
138+
&pci_proto,
139+
MemoryType::BOOT_SERVICES_DATA,
140+
None,
141+
PciRootBridgeIoProtocolAttribute::PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
142+
)
143+
.unwrap();
135144
assert_eq!(size_of_val(src.as_ref()), size_of::<[u8; PAGE_SIZE]>());
136145
let src = unsafe {
137146
src.assume_init_mut().fill(0xDEADBEEF);
138147
src.assume_init()
139148
};
140-
let src_mapped = pci_proto.map(PciRootBridgeIoProtocolOperation::BUS_MASTER_READ, src.as_ref());
141-
142-
let dst = pci_proto
143-
.allocate_buffer::<[u32; 4096 / 4]>(
144-
MemoryType::BOOT_SERVICES_DATA,
145-
None,
146-
PciRootBridgeIoProtocolAttribute::PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
147-
)
148-
.unwrap();
149+
let src_mapped = PciRootBridgeIo::map(
150+
&pci_proto,
151+
PciRootBridgeIoProtocolOperation::BUS_MASTER_READ,
152+
src.as_ref(),
153+
);
154+
155+
let dst = PciRootBridgeIo::allocate_buffer::<[u32; 4096 / 4]>(
156+
&pci_proto,
157+
MemoryType::BOOT_SERVICES_DATA,
158+
None,
159+
PciRootBridgeIoProtocolAttribute::PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
160+
)
161+
.unwrap();
149162
assert_eq!(size_of_val(dst.as_ref()), size_of::<[u8; PAGE_SIZE]>());
150-
let dst_mapped = pci_proto.map(PciRootBridgeIoProtocolOperation::BUS_MASTER_WRITE, dst.as_ref());
151-
152-
pci_proto.copy(PciRootBridgeIoProtocolWidth::UINT32, dst_mapped.region(), src_mapped.region()).unwrap();
163+
let dst_mapped = PciRootBridgeIo::map(
164+
&pci_proto,
165+
PciRootBridgeIoProtocolOperation::BUS_MASTER_WRITE,
166+
dst.as_ref(),
167+
);
168+
169+
PciRootBridgeIo::copy(
170+
&pci_proto,
171+
PciRootBridgeIoProtocolWidth::UINT32,
172+
dst_mapped.region(),
173+
src_mapped.region(),
174+
)
175+
.unwrap();
153176
drop(dst_mapped);
154177
let dst = unsafe { dst.assume_init() };
155178

uefi/src/proto/pci/buffer.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22

33
//! Defines wrapper allocated by PCI Root Bridge protocol.
44
5+
use core::cell::RefCell;
56
use core::mem::{ManuallyDrop, MaybeUninit};
67
use core::num::NonZeroUsize;
78
use core::ops::{Deref, DerefMut};
8-
use core::ptr;
99
use core::ptr::NonNull;
1010
use log::debug;
1111
use uefi_raw::Status;
12-
use uefi_raw::protocol::pci::root_bridge::PciRootBridgeIoProtocol;
12+
use crate::boot::ScopedProtocol;
13+
use crate::proto::pci::root_bridge::PciRootBridgeIo;
1314

1415
/// Smart pointer for wrapping owned buffer allocated by PCI Root Bridge protocol.
1516
#[derive(Debug)]
1617
pub struct PciBuffer<'p, T> {
1718
base: NonNull<T>,
1819
pages: NonZeroUsize,
19-
proto_lifetime: &'p (),
20-
proto: *const PciRootBridgeIoProtocol,
20+
proto: &'p RefCell<ScopedProtocol<PciRootBridgeIo>>,
2121
}
2222

2323
impl<'p, T> PciBuffer<'p, MaybeUninit<T>> {
@@ -26,12 +26,11 @@ impl<'p, T> PciBuffer<'p, MaybeUninit<T>> {
2626
/// Passed protocol is stored as a pointer along with its lifetime so that it doesn't
2727
/// block others from using its mutable functions.
2828
#[must_use]
29-
pub const fn new(base: NonNull<MaybeUninit<T>>, pages: NonZeroUsize, proto: &'p PciRootBridgeIoProtocol) -> Self {
29+
pub const fn new(base: NonNull<MaybeUninit<T>>, pages: NonZeroUsize, proto: &'p RefCell<ScopedProtocol<PciRootBridgeIo>>) -> Self {
3030
Self {
3131
base,
3232
pages,
33-
proto_lifetime: &(),
34-
proto: ptr::from_ref(proto),
33+
proto,
3534
}
3635
}
3736

@@ -45,7 +44,6 @@ impl<'p, T> PciBuffer<'p, MaybeUninit<T>> {
4544
PciBuffer {
4645
base: old.base.cast(),
4746
pages: old.pages,
48-
proto_lifetime: old.proto_lifetime,
4947
proto: old.proto,
5048
}
5149
}
@@ -79,10 +77,7 @@ impl<'p, T> DerefMut for PciBuffer<'p, T> {
7977

8078
impl<'p, T> Drop for PciBuffer<'p, T> {
8179
fn drop(&mut self) {
82-
let status = unsafe {
83-
let proto = self.proto.as_ref().unwrap();
84-
(proto.free_buffer)(proto, self.pages.get(), self.base.as_ptr().cast())
85-
};
80+
let status = PciRootBridgeIo::free_buffer(&self.proto, self.pages, self.base);
8681
match status {
8782
Status::SUCCESS => {
8883
debug!(

uefi/src/proto/pci/region.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
//! Defines wrapper for region mapped by PCI Root Bridge I/O protocol.
44
5+
use core::cell::RefCell;
56
use core::ffi::c_void;
7+
use core::marker::PhantomData;
68
use core::ptr;
79
use log::debug;
810
use uefi_raw::Status;
9-
use uefi_raw::protocol::pci::root_bridge::PciRootBridgeIoProtocol;
11+
use crate::boot::ScopedProtocol;
12+
use crate::proto::pci::root_bridge::PciRootBridgeIo;
1013

1114
/// Represents a region of memory mapped by PCI Root Bridge I/O protocol.
1215
/// The region will be unmapped automatically when it is dropped.
@@ -22,9 +25,9 @@ where
2225
'p: 'r,
2326
{
2427
region: PciRegion,
25-
_lifetime_holder: &'r (),
28+
_lifetime_holder: PhantomData<&'r ()>,
2629
key: *const c_void,
27-
proto: &'p PciRootBridgeIoProtocol,
30+
proto: &'p RefCell<ScopedProtocol<PciRootBridgeIo>>,
2831
}
2932

3033
/// Represents a region of memory in PCI root bridge memory space.
@@ -45,22 +48,17 @@ impl<'p, 'r> PciMappedRegion<'p, 'r> where 'p: 'r {
4548
device_address: u64,
4649
length: usize,
4750
key: *const c_void,
48-
to_map: &'r T,
49-
proto: &'p PciRootBridgeIoProtocol,
51+
_to_map: &'r T,
52+
proto: &'p RefCell<ScopedProtocol<PciRootBridgeIo>>,
5053
) -> Self {
51-
let _lifetime_holder: &'r () = unsafe {
52-
let ptr = ptr::from_ref(to_map);
53-
ptr.cast::<()>().as_ref().unwrap()
54-
};
55-
5654
let end = device_address + length as u64;
5755
debug!("Mapped new region [0x{:X}..0x{:X}]", device_address, end);
5856
Self {
5957
region: PciRegion {
6058
device_address,
6159
length,
6260
},
63-
_lifetime_holder,
61+
_lifetime_holder: PhantomData,
6462
key,
6563
proto,
6664
}
@@ -79,7 +77,7 @@ impl<'p, 'r> PciMappedRegion<'p, 'r> where 'p: 'r {
7977

8078
impl<'p, 'r> Drop for PciMappedRegion<'p, 'r> {
8179
fn drop(&mut self) {
82-
let status = unsafe { (self.proto.unmap)(self.proto, self.key) };
80+
let status = PciRootBridgeIo::unmap(self.proto, self.key);
8381
match status {
8482
Status::SUCCESS => {
8583
let end = self.region.device_address + self.region.length as u64;

0 commit comments

Comments
 (0)