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 f14d807..0000000 Binary files a/lemp9.vbt and /dev/null differ diff --git a/src/gop_policy.rs b/src/gop_policy.rs index ba7f928..c69def7 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 allocation so that it does not get dropped. let self_ptr = Box::into_raw(self); let mut handle = Handle(0); Result::from((uefi.BootServices.InstallProtocolInterface)(