From 43ab3c538b63451d967e61b4bb1efb924624d6c4 Mon Sep 17 00:00:00 2001 From: Tim Crawford Date: Wed, 18 Dec 2024 11:46:57 -0700 Subject: [PATCH] Read VBT from UEFI FFS Remove the embedded VBT file and instead read it from a file added in edk2. Signed-off-by: Tim Crawford --- .github/workflows/ci.yml | 2 -- Cargo.lock | 9 ++---- Cargo.toml | 3 +- README.md | 14 +++++++-- lemp9.vbt | Bin 4608 -> 0 bytes src/gop_policy.rs | 63 +++++++++++++++++++++++++++++++++++---- 6 files changed, 74 insertions(+), 17 deletions(-) delete mode 100644 lemp9.vbt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de6348a..3a87c65 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,4 @@ jobs: rustup show active-toolchain || rustup toolchain install - name: Build UEFI application - env: - FIRMWARE_OPEN_VBT: "../lemp9.vbt" run: make diff --git a/Cargo.lock b/Cargo.lock index d984a98..f61b037 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,14 +5,12 @@ version = 3 [[package]] name = "redox_uefi" version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d69301333534a04b380995f5d9e604f46a7cbd8d8c62c996ee27447efdeba4" +source = "git+https://gitlab.redox-os.org/tcrawford/uefi.git?branch=dev/vbt#277d3422898c6519c9a81f94fd49e27de9e39f6c" [[package]] name = "redox_uefi_alloc" version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df364cdf289d9df9201f147aeeb5e7387f29f0824bee2e41e960eb98eaf03f1" +source = "git+https://gitlab.redox-os.org/tcrawford/uefi.git?branch=dev/vbt#277d3422898c6519c9a81f94fd49e27de9e39f6c" dependencies = [ "redox_uefi", ] @@ -20,8 +18,7 @@ dependencies = [ [[package]] name = "redox_uefi_std" version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b81203f45b2e08804d80274a2951f1615828d9aa5629d3a5d267878c70feb96d" +source = "git+https://gitlab.redox-os.org/tcrawford/uefi.git?branch=dev/vbt#277d3422898c6519c9a81f94fd49e27de9e39f6c" dependencies = [ "redox_uefi", "redox_uefi_alloc", diff --git a/Cargo.toml b/Cargo.toml index d74b131..a4ec206 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,5 @@ license = "GPL-3.0-only" lto = true [dependencies] -redox_uefi_std = "0.1.13" +#redox_uefi_std = "0.1.13" +redox_uefi_std = { git = "https://gitlab.redox-os.org/tcrawford/uefi.git", branch = "dev/vbt" } diff --git a/README.md b/README.md index bbfbec6..d46c80e 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,24 @@ # System76 Platform GOP Policy -A VBT file is required for building. +A driver that installs the Intel Platform GOP Policy protocol. Requires a VBT +file included in the UEFI FFS with a specific GUID. ``` -FIRMWARE_OPEN_VBT=../lemp9.vbt make +FILE FREEFORM = 56752da9-de6b-4895-8819-1945b6b76c22 { + SECTION RAW = vbt.rom + SECTION UI = "IntelGopVbt" +} +``` + +``` +make ``` The `qemu` target will use the target directory as a pseudo-drive so the driver files can be viewed. ``` -FIRMWARE_OPEN_VBT=../lemp9.vbt make qemu +make qemu ``` In QEMU, the driver can be loaded using the UEFI Shell `load` command. diff --git a/lemp9.vbt b/lemp9.vbt deleted file mode 100644 index f14d8073e9217b16ea178678795c290f6d2067f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4608 zcmeHKU2GIp6h5=l{kuD}oeo5{E7rqLU|VRJEwExOakjg~E?wAdw=_#MX@Om^q0rhN zEe6vyX_N;g`=A63N?(ZD7xBsXhHp(wlxTuaModgle38hD0U6JoncY&FmX#<9@$8;^ z?!9y7n{&=RbMKk8y=^_1>D-%)cDAEUIndx-O#`(HsV$Mp^u?n+(Z051D%OcV!Xq$N zbL%QVP7rFPu%?9*N5}Gmq3(KuP2#Sh{R4yfP4WEb;jy7%Ove%!J#ZjDm>=0Umd|0P z_n9biOqsQf4-DpT_xO?h`H>bRAdR#!yrpUL7R2zTX8LR4t<=?8!jYD(Ps%Lb9!u>? zCz8>gL~1vtx-p)}L^GN8U2Vy|nC?z>B-#=^?Qxlv-G~hh9~&7s^!ylxV)fWe&uBD3 zO_MP;G&0%snq!?q*@OgssUH-@qk63=H-9iEML?@VeIx_EHr3YJY7PMU za}v<*a5dyJgch;Y_|PH&t*6rnEk_guI&3vxNekzxm1gg&6a|2rFViDQauPt`1mG7m zIO(l}lo*2Jq61zNw?RYIENEVYj8}n!#K(xgaWeRh_zLkg;v2+H7lUfzTH-atjl@q7 zM~OR$_Yn6H4-mV?;ilmz0IdX3L9k_wB|)izll4$IW6z(l=e@tuq7yM&`fO=VR?rxR z+YPsjF9Tp0p6%QMoe;=vA#Nje*fMEKQB2$89+Es(S$k|4-hLW7%mn%SThT;jUqJb# zGmMgd4{A?Z20Q6Z6g{m|D@|Ya02pUw5hj4u&<z|T|(Iv@lAh{IY~4*ife>no4B56=r} zWmAYyT|V09-CrJr>Zni|Ee}hb86vA+{}zac7{1BWvy6Sj@GGYNz}PPgYkcY&A8Yhs z#;4|eY{-Xi`_vD7>=Pe;>r;RBvEO`HE2$eKwpGGsCH08JUXt)VN&Q%2pGo+=q+XNQ z4GCAt>Smd3m+^qCj>~LP#&fdzsmwl?@rtbeE;G@O^?vm!KWq2nVZZu{pS|vv8&qe( zaakzT_|2loGa}Lclyyj^ye=ptoz?5$Jd$h=mY{Oo~=5M`l75M`)$uYH=^L1~}aXnyw9-TO9z| zKsRzUX~G$-2w?)df{L!(h9DH3e*xjcO%s>9g6s6`={XyOqRT|kUFR#Xq2p;?+kd`U z*DuT=xU4Ek>UCBU$%CtUXS$$H+flUFf=9Awp08v|C2=_3RGjV)*6AABYeA8$Dw>wDfBhU*S$ d(gZkBrU#>IEl26&<-W_!3%=2p&X0S%`X>cK)*k=> diff --git a/src/gop_policy.rs b/src/gop_policy.rs index ba7f928..aa34de9 100644 --- a/src/gop_policy.rs +++ b/src/gop_policy.rs @@ -4,10 +4,14 @@ #![allow(unused)] use std::prelude::*; -use std::uefi::boot::InterfaceType; +use std::uefi::boot::{InterfaceType, LocateSearchType}; +use std::uefi::firmware::{FirmwareVolume2, SectionType}; use std::uefi::memory::PhysicalAddress; -static VBT: &[u8] = include_bytes!(env!("FIRMWARE_OPEN_VBT")); +// From edk2 +const VBT_FILE_GUID: Guid = guid!("56752da9-de6b-4895-8819-1945b6b76c22"); + +// Protocol definition #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] #[repr(transparent)] @@ -46,6 +50,8 @@ impl GopPolicy { pub const REVISION_03: u32 = 0x03; } +// Protocol implementation + extern "efiapi" fn GetPlatformLidStatus(CurrentLidStatus: *mut LidStatus) -> Status { if CurrentLidStatus.is_null() { return Status::INVALID_PARAMETER; @@ -62,10 +68,56 @@ extern "efiapi" fn GetVbtData(VbtAddress: *mut PhysicalAddress, VbtSize: *mut u3 return Status::INVALID_PARAMETER; } - unsafe { *VbtAddress = PhysicalAddress(VBT.as_ptr() as u64) }; - unsafe { *VbtSize = VBT.len() as u32 }; + let mut status = Status::SUCCESS; + let uefi = unsafe { std::system_table_mut() }; + + let mut count = 0; + let mut hbuffer = core::ptr::null_mut(); + status = (uefi.BootServices.LocateHandleBuffer)( + LocateSearchType::ByProtocol, + &FirmwareVolume2::GUID, + core::ptr::null(), + &mut count, + &mut hbuffer, + ); + if status.is_error() { + return Status::NOT_FOUND; + } - Status::SUCCESS + let handles = unsafe { core::slice::from_raw_parts(hbuffer, count) }; + for handle in handles { + let mut interface = 0; + let _ = (uefi.BootServices.HandleProtocol)( + *handle, + &FirmwareVolume2::GUID, + &mut interface, + ); + + let mut vbt_ptr = core::ptr::null_mut(); + let mut vbt_size = 0; + let mut auth_status = 0; + + let fv: &FirmwareVolume2 = unsafe { &*(interface as *const FirmwareVolume2) }; + let status = (fv.ReadSection)( + fv, + &VBT_FILE_GUID, + SectionType::RAW, + 0, + &mut vbt_ptr, + &mut vbt_size, + &mut auth_status, + ); + + if status.is_success() { + unsafe { *VbtAddress = PhysicalAddress(vbt_ptr as u64) }; + unsafe { *VbtSize = vbt_size as u32 }; + break; + } + } + + (uefi.BootServices.FreePool)(hbuffer as usize); + + status } extern "efiapi" fn GetPlatformDockStatus(_CurrentDockStatus: DockStatus) -> Status { @@ -86,6 +138,7 @@ impl GopPolicy { pub fn install(self: Box) -> Result<()> { let uefi = unsafe { std::system_table_mut() }; + // NOTE: This leaks the handle so that it does not get dropped. let self_ptr = Box::into_raw(self); let mut handle = Handle(0); Result::from((uefi.BootServices.InstallProtocolInterface)(