Commit graph

3549 commits

Author SHA1 Message Date
Philipp Schuster
a830de7fcf
Merge pull request #2024 from rust-osdev/revert-2007-push-qrstumutxspt
Some checks failed
Book / deploy (push) Failing after 0s
Developer Productivity / changes (push) Failing after 2s
QA / Spellcheck (push) Failing after 2s
QA / Lints (push) Failing after 2s
Release / release (push) Failing after 2s
Developer Productivity / Nix shell toolchain: `cargo xtask run` works (push) Failing after 0s
Rust / Integration Test (AArch64) (push) Has been cancelled
Rust / Integration Test (x86_64) (push) Has been cancelled
Rust / Integration Test (IA-32) (push) Has been cancelled
Rust / Integration Test (x86_64 Windows) (push) Has been cancelled
Rust / Unit + Doc Tests (push) Has been cancelled
Rust / Build (stable MSRV) (push) Has been cancelled
Rust / Build (uefi-raw MSRV) (push) Has been cancelled
Rust / Build (feature permutations) (push) Has been cancelled
Rust / Nightly (build, test, doc) (push) Has been cancelled
Rust / Unit + Doc Tests (Miri) (push) Has been cancelled
Rust / Build Standard Binary (nightly) (push) Has been cancelled
Rust / Test Coverage (push) Has been cancelled
Revert "Make memory maps repr(C)"
2026-08-25 04:04:57 +00:00
Philipp Schuster
0cf91a1307 Revert "Make memory maps repr(C)" 2026-08-24 21:02:11 +02:00
Philipp Schuster
345386ab9c
Merge pull request #2052 from rust-osdev/miri-bughunt
uefi: various UB fixes
2026-08-24 18:40:23 +00:00
Philipp Schuster
97a1dfcb65
proto: bind SCSI/ATA/NVMe response accessors to &self
The response accessors returned `&'a` instead of borrowing from `self`.
So any returned value was bound to the lifetime of the underlying buffer
which is wrong semantics.
2026-08-24 20:35:26 +02:00
Philipp Schuster
a09fabe0d7
media/file: store FileSystemInfo::read_only as Boolean
The field was materialized in place from firmware memory as a Rust
`bool`, but the UEFI spec types it as `Boolean`, where any byte value is
valid.
2026-08-24 20:35:26 +02:00
Philipp Schuster
80079fbc92
uefi-raw: add helpers to Boolean type for logical equality 2026-08-24 20:35:26 +02:00
Philipp Schuster
4f8ca7069c
mem/memory_map: validate desc_size in MemoryMapOwned constructor
`from_initialized_mem` only checked that `desc_size` was large enough,
unlike the `MemoryMapRef`/`MemoryMapRefMut` constructors, which also
require it to be a multiple of the descriptor alignment. With an
unaligned `desc_size`, every entry but the first was accessed through a
misaligned `&MemoryDescriptor`.

Reuse `validate_meta` so all constructors enforce the same invariant.
2026-08-24 20:24:28 +02:00
Philipp Schuster
b17551c70e
media/file: clamp firmware-reported read length in read_chunked
`read_chunked` trusted the byte count reported by the read callback. A
firmware reporting more than the requested size made `remaining_size`
underflow and advanced `output_ptr` past the end of the caller buffer,
causing out-of-bounds writes on the following chunk.

Clamp the reported length to the requested size.
2026-08-24 20:24:28 +02:00
Philipp Schuster
e06b2e8330
ip4config2: fix UB in get_interface_info
The buffer is a byte-aligned `Vec<u8>`, but the code formed a
`&Ip4Config2InterfaceInfo` reference into it. That type has an alignment
of 8 (it contains a pointer), so the reference was misaligned -
undefined behavior.
2026-08-24 20:24:28 +02:00
Philipp Schuster
e50073191f
Merge pull request #2048 from rust-osdev/spec-compliance-fixes-4
Spec Fixes: various smaller fixes regarding protocols
2026-08-24 08:07:00 +00:00
Philipp Schuster
8b051cae03 test: extend coverage for str_to_fat()
Test for the recently fixed issue.
2026-08-24 10:02:38 +02:00
Philipp Schuster
b91ec569ba uefi: fix result handling of UnicodeCollation::str_to_fat
Per spec and the EDK2 reference implementation, StrToFat writes only
the converted characters and no NUL terminator; the rest of the
caller's buffer keeps whatever content it had.
2026-08-24 10:02:38 +02:00
Philipp Schuster
595882f219 uefi: locate DevicePathUtilities by its own GUID
open_utility_protocol() searched for handles carrying DevicePathToText
and then opened DevicePathUtilities on the first match. This only
works if the firmware happens to install both protocols on the same
handle; otherwise DevicePath::to_pool, append_path, and append_node
(and PciTree::device_path, which builds on them) fail or open the
wrong handle.
2026-08-24 10:02:38 +02:00
Philipp Schuster
d76b303061 uefi: gate revision-dependent Block I/O media fields
Per spec, the EFI_BLOCK_IO_MEDIA members LowestAlignedLba and
LogicalBlocksPerPhysicalBlock are only present if the protocol
revision is at least 2, and OptimalTransferLengthGranularity only
with revision 3. The BlockIOMedia accessors read these fields
unconditionally, i.e. past the firmware-defined structure on
revision-1 implementations.

Since the media struct itself does not carry the revision, move the
three accessors to BlockIO (which does) and return None on old
revisions. They are intentionally not offered on BlockIO2: that
protocol has no revision field of its own, and the spec ties the
fields' presence to the Block I/O protocol revision.
2026-08-24 10:02:38 +02:00
Philipp Schuster
b49072be6c test: add test_get_processor_info_extended() 2026-08-24 10:02:38 +02:00
Philipp Schuster
23e1b8ec71 uefi: add missing ExtendedInformation to ProcessorInformation
The PI spec defines EFI_PROCESSOR_INFORMATION with a trailing
EXTENDED_PROCESSOR_INFORMATION member (a union whose only member is
the 24-byte EFI_CPU_PHYSICAL_LOCATION2), making the struct 48 bytes.
The Rust struct was only 24 bytes.

get_processor_info passes the processor number through unvalidated,
so a caller could already set CPU_V2_EXTENDED_TOPOLOGY (bit 24) and
make the firmware write the extended topology 24 bytes past the
stack-allocated struct. Firmware performing a whole-struct copy
overflowed it even without that flag.

Add the missing field plus the CPU_V2_EXTENDED_TOPOLOGY constant so
the extended topology is actually usable.
2026-08-24 10:02:38 +02:00
Philipp Schuster
16666496e5
Merge pull request #2044 from rust-osdev/spec-compliance-fixes-3
Spec Fixes: Address various smaller size/buffer mismatches
2026-08-24 07:55:08 +00:00
Philipp Schuster
1047f2e24a
uefi: fix buffer size check in DiscoverInfo::new_in_buffer
We missed two padding bytes. We cannot use the
`offset_of!(DiscoverInfo, srv_list)` unfortunately as the type is not
Sized. Further, the alignment check was missing. The new unit test
without the fixes uncovers all issues when executed in Miri.
2026-08-24 09:50:40 +02:00
Philipp Schuster
d7b3794ebb
uefi: fix length of USB supported-languages table
Slice was accidentally twice as long.

Spec: 2.11, 17.2.17. EFI_USB_IO_PROTOCOL.UsbGetSupportedLanguages()
2026-08-24 09:20:19 +02:00
Philipp Schuster
2c22df0509
uefi: fix data size passed to SetWatchdogTimer
Function consumes byte size, not number of elements. Previously, only
half of the data was passed.

Spec: 2.11, 7.5.1. EFI_BOOT_SERVICES.SetWatchdogTimer()
2026-08-24 09:03:24 +02:00
Philipp Schuster
cb6c6ccce8
Merge pull request #2045 from rust-osdev/cargolock
cargo: update deps
2026-08-24 06:39:01 +00:00
Philipp Schuster
099ebe9b86
cargo: update deps 2026-08-24 08:34:04 +02:00
Philipp Schuster
95c6b778bf
Merge pull request #2041 from rust-osdev/spec-compliance-fixes-2
Spec Fixes: Various Smaller Fixes or Additions
2026-08-23 20:42:15 +00:00
Philipp Schuster
ca8e53b904
uefi: correct CRC algorithm in table header docs
The spec mandates the standard CRC-32 (ITU-T V.42 / IEEE 802.3,
polynomial 0x04C11DB7) for EFI_TABLE_HEADER.CRC32, not CRC-32C
(Castagnoli, polynomial 0x1EDC6F41). The crate never computes this
checksum itself, but anyone verifying or recomputing table CRCs based
on this doc got mismatches on every conforming system.

Spec: 2.11, 4.2.1. EFI_TABLE_HEADER
2026-08-23 22:33:22 +02:00
Philipp Schuster
0d6da74fcb
uefi: fix GPT type-specific attribute bit constants
The spec reserves bits 48-63 of the GPT partition entry attributes
for GUID-specific use; bits 3-47 are "undefined and must be zero".

EDK2: 7735ed4f8e/MdePkg/Include/Uefi/UefiGpt.h (L124)
2026-08-23 22:33:22 +02:00
Philipp Schuster
886e0d5013
uefi: add missing IFAR field to SystemContextARM
EDK2: 7735ed4f8e/MdePkg/Include/Protocol/DebugSupport.h (L510)
2026-08-23 22:33:22 +02:00
Philipp Schuster
d6c6441e8d
uefi-raw: add Block I/O protocol revision constants 2026-08-23 22:33:22 +02:00
Philipp Schuster
0e8bab3e9a
uefi-raw: fix Volatile parameter of ShellProtocol::get_alias
The UEFI Shell spec 2.2 defines EFI_SHELL_GET_ALIAS as

  CONST CHAR16 * (EFIAPI *EFI_SHELL_GET_ALIAS)(
    IN  CONST CHAR16 *Alias,
    OUT BOOLEAN      *Volatile OPTIONAL);
2026-08-23 22:33:20 +02:00
Philipp Schuster
549e785328
Merge pull request #2040 from rust-osdev/spec-compliance-fixes-packed
UEFI Spec Compliance: Various repr/packed fixes
2026-08-23 18:55:35 +00:00
Philipp Schuster
a8d71233ca
uefi: make PCI register views repr(C)
PciRegister0/2/3 and PciHeader1Register6 map spec-defined PCI
configuration space dwords onto struct fields via transmute_copy, but
used the default Rust representation, which guarantees no field
order. The mapping only worked because current rustc happens to keep
declaration order for these structs. repr(C) makes the byte-to-field
mapping a language guarantee.
2026-08-23 20:49:43 +02:00
Philipp Schuster
b7f118d438
uefi-raw: match packed layout of HII IFR type values
The spec defines EFI_IFR_TYPE_VALUE and its member types EFI_HII_REF,
EFI_HII_TIME, and EFI_HII_DATE with 1-byte packing (UEFI 2.11, 35.5.4;
EDK2 declares them inside #pragma pack(1)): the union is 22 bytes with
alignment 1. The natural repr(C) layout was 24 bytes with alignment 8.
2026-08-23 20:48:47 +02:00
Philipp Schuster
a2192b7588
uefi-raw: fix layout of HII keyboard layout types
The spec defines EFI_HII_KEYBOARD_LAYOUT and EFI_KEY_DESCRIPTOR with
1-byte packing (UEFI 2.11, 34.8.10; EDK2 declares them inside
#pragma pack(1)).
2026-08-23 20:45:30 +02:00
Philipp Schuster
a402aa6f33
uefi-raw: pack USB descriptor structs
The USB 2.0 specification defines all standard descriptors with 1-byte
packing, and EDK2 declares EFI_USB_*_DESCRIPTOR inside #pragma pack(1)
accordingly [0]. With natural repr(C) layout, ConfigDescriptor was 10
bytes (spec: 9) and EndpointDescriptor 8 bytes (spec: 7) due to the
u16 member; DeviceRequest and DeviceDescriptor deviated in alignment
only.

[0]: 7735ed4f8e/MdePkg/Include/IndustryStandard/Usb.h (L85)
2026-08-23 18:03:54 +02:00
Philipp Schuster
ef8641b510
Merge pull request #2039 from rust-osdev/abi
replace ABI-related unit tests with const checks
2026-08-23 13:34:19 +00:00
Philipp Schuster
7a76937a94
uefi: replace ABI-related unit tests with consts checks
This is best practice in the ecosystem and ensures that the ABI is
correct for the target platform - which may be different from the
test platform.
2026-08-23 15:29:54 +02:00
Philipp Schuster
4a3d96ea33
uefi-raw: replace ABI-related unit tests with consts checks
This is best practice in the ecosystem and ensures that the ABI is
correct for the target platform - which may be different from the
test platform.
2026-08-23 15:29:54 +02:00
Philipp Schuster
3afc565b35
Merge pull request #2038 from rust-osdev/nightly-clippy
clippy: adjust latest nightly findings
2026-08-23 12:48:54 +00:00
Philipp Schuster
1ff2c5d528
clippy: adjust latest nightly findings 2026-08-23 14:44:00 +02:00
Philipp Schuster
2fa6c6f1e1
Merge pull request #2036 from rust-osdev/fix
uefi-raw: make MemoryDescriptor layout portable across x86 targets
2026-08-19 19:22:30 +00:00
Philipp Schuster
049cb57a09
xtask: allow anonymous unit constant
Helpful for checks such as:

```rust
const _: () = {
    assert!(size_of::<MemoryDescriptor>() == 40);
    assert!(align_of::<MemoryDescriptor>() == 8);

    assert!(offset_of!(MemoryDescriptor, ty) == 0);
    assert!(offset_of!(MemoryDescriptor, phys_start) == 8);
    assert!(offset_of!(MemoryDescriptor, virt_start) == 16);
    assert!(offset_of!(MemoryDescriptor, page_count) == 24);
    assert!(offset_of!(MemoryDescriptor, att) == 32);
};
```
2026-08-19 17:34:16 +02:00
Philipp Schuster
0cfe38cf30
xtask: allow align 8 in check-raw
We need this for the layout fix for MemoryDescriptor.
2026-08-19 08:35:29 +02:00
Philipp Schuster
e72d1269c9
uefi-raw: make MemoryDescriptor layout portable across x86 targets
TL;DR: Add an explicit 32-bit padding field after `MemoryDescriptor::ty`
so UEFI memory maps can be parsed correctly from non-UEFI targets such
as kernels and bootloaders compiled for generic i686 targets.

UEFI's `EFI_MEMORY_DESCRIPTOR` places `PhysicalStart` at offset 8. This
happens implicitly on x86_64 and also on IA32 UEFI, where 64-bit values
are 8-byte aligned. EDK II enforces this for GCC IA32 builds with
`-malign-double` [0], and Rust's `i686-unknown-uefi` target explicitly
uses `i64:64` in its LLVM data layout [1].

This differs from the standard x86-32 ABI. GCC normally aligns
`long long` to one word on x86-32 and documents `-malign-double` as an
ABI-changing option [2]. Rust/LLVM follows the standard x86-32 layout
for targets such as `i686-unknown-linux-gnu`, where `u64` has 4-byte ABI
alignment [3]. Consequently, `#[repr(C)]` alone places `phys_start` at
offset 4 instead of the UEFI-required offset 8.

This matters outside UEFI applications. Kernels and bootloaders may
receive and parse a UEFI memory map while being compiled for a generic
target such as a bare-metal i686 target.

For example, the multiboot2 crate re-exports this type as
`EFIMemoryDesc` and uses it to parse EFI memory-map data [4]. The type
therefore needs to describe the UEFI binary layout independently of the
consumer's target ABI.

Reproducer without the explicit padding:

```rust
#[repr(C)]
pub struct MemoryDescriptor {
    pub ty: u32,
    pub phys_start: u64,
    pub virt_start: u64,
    pub page_count: u64,
    pub att: u64,
}

const _: () = {
    assert!(core::mem::offset_of!(MemoryDescriptor, phys_start) == 8);
};
```

```console
# works
cargo check --target x86_64-unknown-linux-gnu

# fails: phys_start is at offset 4
cargo check --target i686-unknown-linux-gnu

# both UEFI targets already have the required layout
cargo check --target x86_64-unknown-uefi
cargo check --target i686-unknown-uefi
```

The explicit padding makes the UEFI-defined field offsets independent
of whether the compilation target itself uses the UEFI ABI.

[0]: 2970e5699b/BaseTools/Conf/tools_def.template (L620)
[1]: 9ba81c26fe/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs (L96)
[2]: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
[3]: 9ba81c26fe/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs (L36)
[4]: 5ccb9629df/multiboot2/src/memory_map.rs (L5)
2026-08-19 08:28:13 +02:00
Philipp Schuster
a30ecd2a52
Revert "uefi-raw: fix MemoryDescriptor layout on 32-bit targets"
This reverts commit 6424087aa5.
2026-08-19 08:28:13 +02:00
Philipp Schuster
6ec342a547
Merge pull request #2029 from rust-osdev/contributing-overhaul
contributing: streamline contribution guidance + AI/LLM Policy
2026-08-18 15:50:57 +00:00
Philipp Schuster
146342326b contributing: streamline contribution guidance
This reflects the status-quo and updates the outdated CONTRIBUTING.md.

- expectations on code style
- expectations on commit style
- expextations on AI/LLM-assisted contributions
2026-08-18 17:40:08 +02:00
Philipp Schuster
a34b22476b
Merge pull request #2031 from cwize1/char16Macro
uefi: add convenient char16!() macro
2026-08-18 14:32:13 +00:00
Chris Gunn
49a94a9250 uefi: add char16!() macro
Add a `char16!` macro that creates a const `Char16` value from a
character literal. This is nicer than using `Char16::from_u16_unchecked`
since it doesn't require an unsafe block and will trigger a compiler
error if the character is not valid in UCS-2.

Also, go through and replace uses of `Char16::from_u16_unchecked` and
`Char16::try_from` with `char16!` where appropriate.

Also, add `PartialEq` to `CharConversionError` to make writing unit
tests easier.
2026-08-18 16:22:03 +02:00
Philipp Schuster
e73ce6849b
Merge pull request #2035 from rust-osdev/fix
uefi-raw: fix MemoryDescriptor layout on 32-bit
2026-08-17 07:03:01 +00:00
Philipp Schuster
6424087aa5 uefi-raw: fix MemoryDescriptor layout on 32-bit targets
On 64-bit, there is implicit padding. On 32-bit targets, this is missing
and makes parsing the memory map impossible. The issue was found in an
external 32-bit integration test [0].

[0] https://github.com/rust-osdev/multiboot2/pull/225
2026-08-17 08:59:09 +02:00
Philipp Schuster
ef2b4bc72f
Merge pull request #2034 from rust-osdev/renovate/crate-time-vulnerability
chore(deps): update rust crate time to v0.3.47 [security]
2026-08-17 06:38:43 +00:00