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}