Skip to content

Commit

Permalink
Move uefi-exts into core as an optional feature
Browse files Browse the repository at this point in the history
  • Loading branch information
GabrielMajeri committed Sep 26, 2019
1 parent e9fc29d commit 502aecd
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 126 deletions.
10 changes: 7 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
[package]
name = "uefi"
version = "0.3.1"
version = "0.3.2"
authors = ["Gabriel Majeri <[email protected]>"]
readme = "README.md"
edition = "2018"
exclude = ["uefi-test-runner/**"]
exclude = [
"uefi-macros/**",
"uefi-services/**",
"uefi-test-runner/**",
]
description = "Safe and easy-to-use wrapper for building UEFI apps"
repository = "https://github.com/rust-osdev/uefi-rs"
keywords = ["uefi", "efi"]
Expand All @@ -19,6 +23,7 @@ is-it-maintained-open-issues = { repository = "rust-osdev/uefi-rs" }
[features]
default = []
alloc = []
exts = []
logger = []

[dependencies]
Expand All @@ -29,7 +34,6 @@ uefi-macros = "0.2.1"

[workspace]
members = [
"uefi-exts",
"uefi-macros",
"uefi-services",
"uefi-test-runner",
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ This project contains multiple sub-crates:
- `logger`: logging implementation for the standard [log] crate.
- Prints output to console.
- No buffering is done: this is not a high-performance logger.

- `uefi-exts`: extension traits providing utility functions for common patterns.
- Requires the `alloc` crate (either enable the `alloc` optional feature or your own custom allocator).
- `exts`: extensions providing utility functions for common patterns.
- Requires the `alloc` crate (either enable the `alloc` optional feature or your own custom allocator).

- `uefi-macros`: procedural macros that are used to derive some traits in `uefi`.

Expand Down
20 changes: 4 additions & 16 deletions uefi-exts/src/lib.rs → src/exts.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,16 @@
//! Utility functions for the most common UEFI patterns.
//!
//! This crate simply exports some extension traits
//! which add utility functions to various UEFI objects.
#![no_std]
#![feature(alloc_layout_extra, allocator_api)]

extern crate alloc;

mod boot;
mod file;

pub use self::boot::BootServicesExt;
pub use self::file::FileExt;

use alloc::{
use alloc_api::{
alloc::{handle_alloc_error, Alloc, Global, Layout},
boxed::Box,
};
use core::slice;

/// Creates a boxed byte buffer using the standard allocator
///
/// # Panics
/// Calls handle_alloc_error if the layout has a size of zero or allocation fails.
///
/// Calls `handle_alloc_error` if the layout has a size of zero or allocation fails.
pub fn allocate_buffer(layout: Layout) -> Box<[u8]> {
if layout.size() == 0 {
handle_alloc_error(layout);
Expand Down
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,18 @@
//! For example, a PC with no network card might not contain a network driver,
//! therefore all the network protocols will be unavailable.
#![cfg_attr(feature = "exts", feature(allocator_api, alloc_layout_extra))]
#![feature(optin_builtin_traits)]
#![feature(try_trait)]
#![no_std]
// Enable some additional warnings and lints.
#![warn(missing_docs, unused)]
#![deny(clippy::all)]

// `uefi-exts` requires access to memory allocation APIs.
#[cfg(feature = "exts")]
extern crate alloc as alloc_api;

#[macro_use]
pub mod data_types;
pub use self::data_types::{unsafe_guid, Identify};
Expand All @@ -47,5 +52,8 @@ pub mod prelude;
#[cfg(feature = "alloc")]
pub mod alloc;

#[cfg(feature = "exts")]
pub mod exts;

#[cfg(feature = "logger")]
pub mod logger;
43 changes: 43 additions & 0 deletions src/proto/media/file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ mod regular;

use crate::prelude::*;
use crate::{CStr16, Char16, Guid, Result, Status};
#[cfg(feature = "exts")]
use alloc_api::{alloc::Layout, boxed::Box};
use bitflags::bitflags;
use core::ffi::c_void;
use core::mem;
Expand Down Expand Up @@ -168,6 +170,47 @@ pub trait File: Sized {
fn flush(&mut self) -> Result {
(self.imp().flush)(self.imp()).into()
}

#[cfg(feature = "exts")]
/// Get the dynamically allocated info for a file
fn get_boxed_info<Info: FileProtocolInfo + ?Sized>(&mut self) -> Result<Box<Info>> {
// Initially try get_info with an empty array, this should always fail
// as all Info types at least need room for a null-terminator.
let size = match self
.get_info::<Info>(&mut [])
.expect_error("zero sized get_info unexpectedly succeeded")
.split()
{
(s, None) => return Err(s.into()),
(_, Some(size)) => size,
};

// We add trailing padding because the size of a rust structure must
// always be a multiple of alignment.
let layout = Layout::from_size_align(size, Info::alignment())
.unwrap()
.pad_to_align()
.unwrap();
let mut buffer = crate::exts::allocate_buffer(layout);
let buffer_start = buffer.as_ptr();

let info = self
.get_info(&mut buffer)
.discard_errdata()?
.map(|info_ref| {
// This operation is safe because info uses the exact memory
// of the provied buffer (so no memory is leaked), and the box
// is created if and only if buffer is leaked (so no memory can
// ever be freed twice).

assert_eq!(mem::size_of_val(info_ref), layout.size());
assert_eq!(info_ref as *const Info as *const u8, buffer_start);
unsafe { Box::from_raw(info_ref as *mut _) }
});
mem::forget(buffer);

Ok(info)
}
}

// Internal File helper methods to access the funciton pointer table.
Expand Down
34 changes: 34 additions & 0 deletions src/table/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use super::Header;
use crate::data_types::Align;
use crate::proto::Protocol;
use crate::{Event, Guid, Handle, Result, Status};
#[cfg(feature = "exts")]
use alloc_api::vec::Vec;
use bitflags::bitflags;
use core::cell::UnsafeCell;
use core::ffi::c_void;
Expand Down Expand Up @@ -485,6 +487,38 @@ impl BootServices {
}
}

#[cfg(feature = "exts")]
impl BootServices {
/// Returns all the handles implementing a certain protocol.
pub fn find_handles<P: Protocol>(&self) -> Result<Vec<Handle>> {
// Search by protocol.
let search_type = SearchType::from_proto::<P>();

// Determine how much we need to allocate.
let (status1, buffer_size) = self.locate_handle(search_type, None)?.split();

// Allocate a large enough buffer.
let mut buffer = Vec::with_capacity(buffer_size);

unsafe {
buffer.set_len(buffer_size);
}

// Perform the search.
let (status2, buffer_size) = self.locate_handle(search_type, Some(&mut buffer))?.split();

// Once the vector has been filled, update its size.
unsafe {
buffer.set_len(buffer_size);
}

// Emit output, with warnings
status1
.into_with_val(|| buffer)
.map(|completion| completion.with_status(status2))
}
}

impl super::Table for BootServices {
const SIGNATURE: u64 = 0x5652_4553_544f_4f42;
}
Expand Down
9 changes: 0 additions & 9 deletions uefi-exts/Cargo.toml

This file was deleted.

41 changes: 0 additions & 41 deletions uefi-exts/src/boot.rs

This file was deleted.

51 changes: 0 additions & 51 deletions uefi-exts/src/file.rs

This file was deleted.

3 changes: 1 addition & 2 deletions uefi-test-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ publish = false
edition = "2018"

[dependencies]
uefi = { path = ".." }
uefi = { path = "..", features = ['exts'] }
uefi-services = { path = "../uefi-services" }
uefi-exts = { path = "../uefi-exts" }

log = { version = "0.4.8", default-features = false }

Expand Down
1 change: 0 additions & 1 deletion uefi-test-runner/src/proto/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use uefi::prelude::*;
use uefi_exts::BootServicesExt;

use uefi::proto;

Expand Down

0 comments on commit 502aecd

Please sign in to comment.