Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read VBT from UEFI FFS #23

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,4 @@ jobs:
rustup show active-toolchain || rustup toolchain install

- name: Build UEFI application
env:
FIRMWARE_OPEN_VBT: "../lemp9.vbt"
run: make
9 changes: 3 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
Binary file removed lemp9.vbt
Binary file not shown.
63 changes: 58 additions & 5 deletions src/gop_policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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;
Expand All @@ -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 {
Expand All @@ -86,6 +138,7 @@ impl GopPolicy {
pub fn install(self: Box<Self>) -> 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)(
Expand Down