Skip to content

uefi: Enable unsafe_op_in_unsafe_fn lint #1585

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

Merged
merged 16 commits into from
Mar 23, 2025
Merged
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
12 changes: 7 additions & 5 deletions uefi/src/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,11 @@ unsafe impl GlobalAlloc for Allocator {
// write is appropriately aligned for a `*mut u8` pointer because
// `align_ptr` is aligned, and alignments are always powers of two
// (as enforced by the `Layout` type).
let aligned_ptr = full_alloc_ptr.add(offset);
(aligned_ptr.cast::<*mut u8>()).sub(1).write(full_alloc_ptr);
aligned_ptr
unsafe {
let aligned_ptr = full_alloc_ptr.add(offset);
(aligned_ptr.cast::<*mut u8>()).sub(1).write(full_alloc_ptr);
aligned_ptr
}
} else {
// The requested alignment is less than or equal to eight, and
// `allocate_pool` always provides eight-byte alignment, so we can
Expand All @@ -108,13 +110,13 @@ unsafe impl GlobalAlloc for Allocator {
if layout.align() > 8 {
// Retrieve the pointer to the full allocation that was packed right
// before the aligned allocation in `alloc`.
ptr = (ptr as *const *mut u8).sub(1).read();
ptr = unsafe { (ptr as *const *mut u8).sub(1).read() };
}

// OK to unwrap: `ptr` is required to be a valid allocation by the trait API.
let ptr = NonNull::new(ptr).unwrap();

// Warning: this will panic after exiting boot services.
boot::free_pool(ptr).unwrap();
unsafe { boot::free_pool(ptr) }.unwrap();
}
}
101 changes: 57 additions & 44 deletions uefi/src/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub unsafe fn raise_tpl(tpl: Tpl) -> TplGuard {
let bt = unsafe { bt.as_ref() };

TplGuard {
old_tpl: (bt.raise_tpl)(tpl),
old_tpl: unsafe { (bt.raise_tpl)(tpl) },
}
}

Expand Down Expand Up @@ -381,15 +381,17 @@ pub unsafe fn create_event(

// Safety: the argument types of the function pointers are defined
// differently, but are compatible and can be safely transmuted.
let notify_fn: Option<uefi_raw::table::boot::EventNotifyFn> = mem::transmute(notify_fn);
let notify_fn: Option<uefi_raw::table::boot::EventNotifyFn> =
unsafe { mem::transmute(notify_fn) };

let notify_ctx = opt_nonnull_to_ptr(notify_ctx);

// Now we're ready to call UEFI
(bt.create_event)(event_ty, notify_tpl, notify_fn, notify_ctx, &mut event).to_result_with_val(
// OK to unwrap: event is non-null for Status::SUCCESS.
|| Event::from_ptr(event).unwrap(),
)
unsafe { (bt.create_event)(event_ty, notify_tpl, notify_fn, notify_ctx, &mut event) }
.to_result_with_val(
// OK to unwrap: event is non-null for Status::SUCCESS.
|| unsafe { Event::from_ptr(event) }.unwrap(),
)
}

/// Creates an event in an event group.
Expand Down Expand Up @@ -451,19 +453,22 @@ pub unsafe fn create_event_ex(

// Safety: the argument types of the function pointers are defined
// differently, but are compatible and can be safely transmuted.
let notify_fn: Option<uefi_raw::table::boot::EventNotifyFn> = mem::transmute(notify_fn);

(bt.create_event_ex)(
event_type,
notify_tpl,
notify_fn,
opt_nonnull_to_ptr(notify_ctx),
opt_nonnull_to_ptr(event_group),
&mut event,
)
let notify_fn: Option<uefi_raw::table::boot::EventNotifyFn> =
unsafe { mem::transmute(notify_fn) };

unsafe {
(bt.create_event_ex)(
event_type,
notify_tpl,
notify_fn,
opt_nonnull_to_ptr(notify_ctx),
opt_nonnull_to_ptr(event_group),
&mut event,
)
}
.to_result_with_val(
// OK to unwrap: event is non-null for Status::SUCCESS.
|| Event::from_ptr(event).unwrap(),
|| unsafe { Event::from_ptr(event) }.unwrap(),
)
}

Expand Down Expand Up @@ -696,13 +701,15 @@ pub unsafe fn install_protocol_interface(
let bt = unsafe { bt.as_ref() };

let mut handle = Handle::opt_to_ptr(handle);
((bt.install_protocol_interface)(
&mut handle,
protocol,
InterfaceType::NATIVE_INTERFACE,
interface,
))
.to_result_with_val(|| Handle::from_ptr(handle).unwrap())
unsafe {
(bt.install_protocol_interface)(
&mut handle,
protocol,
InterfaceType::NATIVE_INTERFACE,
interface,
)
}
.to_result_with_val(|| unsafe { Handle::from_ptr(handle) }.unwrap())
}

/// Reinstalls a protocol interface on a device handle. `old_interface` is replaced with `new_interface`.
Expand Down Expand Up @@ -730,8 +737,10 @@ pub unsafe fn reinstall_protocol_interface(
let bt = boot_services_raw_panicking();
let bt = unsafe { bt.as_ref() };

(bt.reinstall_protocol_interface)(handle.as_ptr(), protocol, old_interface, new_interface)
.to_result()
unsafe {
(bt.reinstall_protocol_interface)(handle.as_ptr(), protocol, old_interface, new_interface)
}
.to_result()
}

/// Removes a protocol interface from a device handle.
Expand All @@ -757,7 +766,7 @@ pub unsafe fn uninstall_protocol_interface(
let bt = boot_services_raw_panicking();
let bt = unsafe { bt.as_ref() };

(bt.uninstall_protocol_interface)(handle.as_ptr(), protocol, interface).to_result()
unsafe { (bt.uninstall_protocol_interface)(handle.as_ptr(), protocol, interface).to_result() }
}

/// Registers `event` to be signaled whenever a protocol interface is registered for
Expand Down Expand Up @@ -1035,19 +1044,21 @@ pub unsafe fn open_protocol<P: ProtocolPointer + ?Sized>(
let bt = unsafe { bt.as_ref() };

let mut interface = ptr::null_mut();
(bt.open_protocol)(
params.handle.as_ptr(),
&P::GUID,
&mut interface,
params.agent.as_ptr(),
Handle::opt_to_ptr(params.controller),
attributes as u32,
)
unsafe {
(bt.open_protocol)(
params.handle.as_ptr(),
&P::GUID,
&mut interface,
params.agent.as_ptr(),
Handle::opt_to_ptr(params.controller),
attributes as u32,
)
}
.to_result_with_val(|| {
let interface = if interface.is_null() {
None
} else {
NonNull::new(P::mut_ptr_from_ffi(interface))
NonNull::new(unsafe { P::mut_ptr_from_ffi(interface) })
};
ScopedProtocol {
interface,
Expand Down Expand Up @@ -1220,12 +1231,14 @@ pub unsafe fn exit(
let bt = boot_services_raw_panicking();
let bt = unsafe { bt.as_ref() };

(bt.exit)(
image_handle.as_ptr(),
exit_status,
exit_data_size,
exit_data.cast(),
)
unsafe {
(bt.exit)(
image_handle.as_ptr(),
exit_status,
exit_data_size,
exit_data.cast(),
)
}
}

/// Get the current memory map and exit boot services.
Expand All @@ -1241,7 +1254,7 @@ unsafe fn get_memory_map_and_exit_boot_services(buf: &mut [u8]) -> Result<Memory
// what boot services functions can be called. In UEFI 2.8 and earlier,
// only `get_memory_map` and `exit_boot_services` are allowed. Starting
// in UEFI 2.9 other memory allocation functions may also be called.
(bt.exit_boot_services)(image_handle().as_ptr(), memory_map.map_key.0)
unsafe { (bt.exit_boot_services)(image_handle().as_ptr(), memory_map.map_key.0) }
.to_result_with_val(|| memory_map)
}

Expand Down Expand Up @@ -1344,7 +1357,7 @@ pub unsafe fn install_configuration_table(
let bt = boot_services_raw_panicking();
let bt = unsafe { bt.as_ref() };

(bt.install_configuration_table)(guid_entry, table_ptr).to_result()
unsafe { (bt.install_configuration_table)(guid_entry, table_ptr) }.to_result()
}

/// Sets the watchdog timer.
Expand Down
14 changes: 7 additions & 7 deletions uefi/src/data_types/strs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,11 @@ impl CStr8 {
#[must_use]
pub unsafe fn from_ptr<'ptr>(ptr: *const Char8) -> &'ptr Self {
let mut len = 0;
while *ptr.add(len) != NUL_8 {
while unsafe { *ptr.add(len) } != NUL_8 {
len += 1
}
let ptr = ptr.cast::<u8>();
Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len + 1))
unsafe { Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len + 1)) }
}

/// Creates a CStr8 reference from bytes.
Expand All @@ -171,7 +171,7 @@ impl CStr8 {
/// null-terminated string, with no interior null bytes.
#[must_use]
pub const unsafe fn from_bytes_with_nul_unchecked(chars: &[u8]) -> &Self {
&*(ptr::from_ref(chars) as *const Self)
unsafe { &*(ptr::from_ref(chars) as *const Self) }
}

/// Returns the inner pointer to this CStr8.
Expand Down Expand Up @@ -352,11 +352,11 @@ impl CStr16 {
#[must_use]
pub unsafe fn from_ptr<'ptr>(ptr: *const Char16) -> &'ptr Self {
let mut len = 0;
while *ptr.add(len) != NUL_16 {
while unsafe { *ptr.add(len) } != NUL_16 {
len += 1
}
let ptr = ptr.cast::<u16>();
Self::from_u16_with_nul_unchecked(slice::from_raw_parts(ptr, len + 1))
unsafe { Self::from_u16_with_nul_unchecked(slice::from_raw_parts(ptr, len + 1)) }
}

/// Creates a `&CStr16` from a u16 slice, stopping at the first nul character.
Expand Down Expand Up @@ -405,7 +405,7 @@ impl CStr16 {
/// null-terminated string, with no interior null characters.
#[must_use]
pub const unsafe fn from_u16_with_nul_unchecked(codes: &[u16]) -> &Self {
&*(ptr::from_ref(codes) as *const Self)
unsafe { &*(ptr::from_ref(codes) as *const Self) }
}

/// Creates a `&CStr16` from a [`Char16`] slice, stopping at the first nul character.
Expand Down Expand Up @@ -455,7 +455,7 @@ impl CStr16 {
#[must_use]
pub const unsafe fn from_char16_with_nul_unchecked(chars: &[Char16]) -> &Self {
let ptr: *const [Char16] = chars;
&*(ptr as *const Self)
unsafe { &*(ptr as *const Self) }
}

/// Convert a [`&str`] to a `&CStr16`, backed by a buffer.
Expand Down
2 changes: 1 addition & 1 deletion uefi/src/helpers/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ static LOGGER: Logger = Logger::new();
/// disable() on exit from UEFI boot services.
pub unsafe fn init() {
// Connect the logger to stdout.
system::with_stdout(|stdout| {
system::with_stdout(|stdout| unsafe {
LOGGER.set_output(stdout);
});

Expand Down
1 change: 1 addition & 0 deletions uefi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@
clippy::use_self,
missing_debug_implementations,
missing_docs,
unsafe_op_in_unsafe_fn,
unused
)]

Expand Down
12 changes: 7 additions & 5 deletions uefi/src/proto/console/gop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ impl FrameBuffer<'_> {
#[inline]
pub unsafe fn write_byte(&mut self, index: usize, value: u8) {
debug_assert!(index < self.size, "Frame buffer accessed out of bounds");
self.base.add(index).write_volatile(value)
unsafe { self.base.add(index).write_volatile(value) }
}

/// Read the i-th byte of the frame buffer
Expand All @@ -603,7 +603,7 @@ impl FrameBuffer<'_> {
#[must_use]
pub unsafe fn read_byte(&self, index: usize) -> u8 {
debug_assert!(index < self.size, "Frame buffer accessed out of bounds");
self.base.add(index).read_volatile()
unsafe { self.base.add(index).read_volatile() }
}

/// Write a value in the frame buffer, starting at the i-th byte
Expand All @@ -624,8 +624,10 @@ impl FrameBuffer<'_> {
index.saturating_add(size_of::<T>()) <= self.size,
"Frame buffer accessed out of bounds"
);
let ptr = self.base.add(index).cast::<T>();
ptr.write_volatile(value)
unsafe {
let ptr = self.base.add(index).cast::<T>();
ptr.write_volatile(value)
}
}

/// Read a value from the frame buffer, starting at the i-th byte
Expand All @@ -647,6 +649,6 @@ impl FrameBuffer<'_> {
index.saturating_add(size_of::<T>()) <= self.size,
"Frame buffer accessed out of bounds"
);
(self.base.add(index) as *const T).read_volatile()
unsafe { (self.base.add(index) as *const T).read_volatile() }
}
}
11 changes: 7 additions & 4 deletions uefi/src/proto/debug/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl DebugSupport {
}

// Safety: As we've validated the `processor_index`, this should always be safe
(self.register_periodic_callback)(self, processor_index, callback).to_result()
unsafe { (self.register_periodic_callback)(self, processor_index, callback) }.to_result()
}

/// Registers a function to be called when a given processor exception occurs.
Expand All @@ -122,8 +122,10 @@ impl DebugSupport {
}

// Safety: As we've validated the `processor_index`, this should always be safe
(self.register_exception_callback)(self, processor_index, callback, exception_type)
.to_result()
unsafe {
(self.register_exception_callback)(self, processor_index, callback, exception_type)
}
.to_result()
}

/// Invalidates processor instruction cache for a memory range for a given `processor_index`.
Expand All @@ -144,7 +146,8 @@ impl DebugSupport {

// per the UEFI spec, this call should only return EFI_SUCCESS
// Safety: As we've validated the `processor_index`, this should always be safe
(self.invalidate_instruction_cache)(self, processor_index, start, length).to_result()
unsafe { (self.invalidate_instruction_cache)(self, processor_index, start, length) }
.to_result()
}
}

Expand Down
Loading