Skip to content

Commit 224d3d7

Browse files
file: use a nightly API for DST initialization
The `FileInfo`, `FileSystemInfo`, and `FileSystemVolumeLabel` structs are all DSTs because they end with a `Char16` slice containing a name. A wide pointer (or reference) to such a struct contains two parts: the base memory address, and the number of elements in the slice. Previously there was no officially-documented way to create such a wide pointer, so uefi-rs used a trick that is used [elsewhere in the Rust ecosystem][1]: create a slice matching the type and length of the slice at the end of the struct, but passing in the desired base pointer instead. Then the slice type is cast to match the desired struct type. There is now a standard (albeit currently unstable) API for performing this construction added by [RFC 2580][2]. This requires enabling the `ptr_metadata` feature. The runtime result should be the same, but without relying on undocumented Rust internals. [1]: rust-lang/unsafe-code-guidelines#288 (comment) [2]: https://rust-lang.github.io/rfcs/2580-ptr-meta.html
1 parent f53256e commit 224d3d7

File tree

2 files changed

+15
-11
lines changed

2 files changed

+15
-11
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#![feature(try_trait_v2)]
3030
#![feature(abi_efiapi)]
3131
#![feature(negative_impls)]
32+
#![feature(ptr_metadata)]
3233
#![no_std]
3334
// Enable some additional warnings and lints.
3435
#![warn(missing_docs, unused)]

src/proto/media/file/info.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ use super::FileAttribute;
22
use crate::data_types::{chars::NUL_16, Align};
33
use crate::table::runtime::Time;
44
use crate::{unsafe_guid, CStr16, Char16, Identify};
5-
use core::cmp;
65
use core::convert::TryInto;
76
use core::ffi::c_void;
8-
use core::mem;
9-
use core::slice;
7+
use core::{cmp, mem, ptr};
108

119
/// Common trait for data structures that can be used with
1210
/// `File::set_info()` or `File::get_info()`.
@@ -89,11 +87,17 @@ impl<Header> NamedFileProtocolInfo<Header> {
8987
// Drop implementation. Thus, we are now ready to build a correctly
9088
// sized &mut Self and go back to the realm of safe code.
9189
debug_assert!(!mem::needs_drop::<Char16>());
92-
let info_ptr = unsafe {
93-
slice::from_raw_parts_mut(storage.as_mut_ptr() as *mut Char16, name_length_ucs2)
94-
as *mut [Char16] as *mut Self
90+
let info = unsafe {
91+
// A wide pointer to a dynamically-sized struct ending with
92+
// a slice contains a pointer to the start of the memory,
93+
// followed by the number of elements in the slice.
94+
//
95+
// For more details of wide pointers, see
96+
// https://doc.rust-lang.org/nightly/core/ptr/trait.Pointee.html
97+
let fat_ptr =
98+
ptr::from_raw_parts_mut::<Self>(storage.as_mut_ptr() as *mut (), name_length_ucs2);
99+
&mut *fat_ptr
95100
};
96-
let info = unsafe { &mut *info_ptr };
97101
debug_assert_eq!(info.name.len(), name_length_ucs2);
98102

99103
// Write down the UCS-2 name before returning the storage reference
@@ -119,10 +123,9 @@ impl<Header> FromUefi for NamedFileProtocolInfo<Header> {
119123
let byte_ptr = ptr as *mut u8;
120124
let name_ptr = byte_ptr.add(mem::size_of::<Header>()) as *mut Char16;
121125
let name = CStr16::from_ptr(name_ptr);
122-
let name_len = name.to_u16_slice_with_nul().len();
123-
let fat_ptr = slice::from_raw_parts_mut(ptr as *mut Char16, name_len);
124-
let self_ptr = fat_ptr as *mut [Char16] as *mut Self;
125-
&mut *self_ptr
126+
let name_len_chars = name.as_slice().len();
127+
let fat_ptr = ptr::from_raw_parts_mut::<Self>(ptr as *mut (), name_len_chars);
128+
&mut *fat_ptr
126129
}
127130
}
128131

0 commit comments

Comments
 (0)