Skip to main content

vck_loader/hook/
block_io2.rs

1// SPDX-FileCopyrightText: 2026 JC-Lab <joseph@jc-lab.net>
2//
3// SPDX-License-Identifier: Apache-2.0
4
5//! `EFI_BLOCK_IO2_PROTOCOL` hooking (`ReadBlocksEx`).
6//!
7//! Mirrors [`block_io`](crate::hook::block_io) but for the asynchronous
8//! `EFI_BLOCK_IO2_PROTOCOL`. Saves the original `ReadBlocksEx` pointer, patches
9//! the vtable with [`hooked_read_blocks_ex`], and restores it on uninstall.
10
11use vck_common::VckResult;
12
13/// Saved state for a single hooked `EFI_BLOCK_IO2_PROTOCOL` instance.
14pub struct BlockIo2Hook {
15    // TODO(loader): hold raw pointers to the protocol instance and its Media,
16    // plus the original ReadBlocksEx fn pointer so it can be restored/called.
17    //
18    // protocol:         *mut EFI_BLOCK_IO2_PROTOCOL,
19    // original_read_ex: EFI_BLOCK_IO2_READ_BLOCKS_EX,
20    _private: (),
21}
22
23impl BlockIo2Hook {
24    /// Saves the original `ReadBlocksEx` pointer and installs the hook into the
25    /// protocol vtable for the matched partition handle.
26    pub fn install(/* protocol handle / pointer */) -> VckResult<Self> {
27        // TODO(loader): OpenProtocol(EFI_BLOCK_IO2_PROTOCOL), save ReadEx pointer,
28        // overwrite the vtable ReadBlocksEx slot with hooked_read_blocks_ex.
29        todo!("save original ReadBlocksEx and patch EFI_BLOCK_IO2_PROTOCOL vtable")
30    }
31
32    /// Restores the original `ReadBlocksEx` pointer in the protocol vtable.
33    pub fn uninstall(self) -> VckResult<()> {
34        // TODO(loader): write self.original_read_ex back into the vtable slot.
35        let _ = self;
36        todo!("restore original EFI_BLOCK_IO2_PROTOCOL ReadBlocksEx pointer")
37    }
38}
39
40/// Replacement `ReadBlocksEx` (`EFI_BLOCK_IO2_PROTOCOL.ReadBlocksEx`).
41///
42/// Asynchronous variant: the EFI ABI adds an `EFI_BLOCK_IO2_TOKEN` so the read
43/// may complete later. The decryption decision must run after the underlying
44/// read has actually completed (e.g. by chaining the token's event), then call
45/// the engine's per-sector AES-XTS decision.
46// TODO(loader): give this the exact `extern "efiapi"` signature
47// `(This, MediaId, Lba, Token, BufferSize, Buffer) -> Status`, hook the token
48// completion to run decrypt_after_read before signaling the caller's event.
49pub extern "efiapi" fn hooked_read_blocks_ex() {
50    todo!("hooked EFI_BLOCK_IO2_PROTOCOL.ReadBlocksEx: original read then AES-XTS decrypt on completion")
51}