Skip to content

Commit 0b87a09

Browse files
authored
Merge pull request #30 from josephlr/uefi
Support x86_64-unknown-uefi
2 parents ac7a542 + 8053d7e commit 0b87a09

File tree

4 files changed

+50
-12
lines changed

4 files changed

+50
-12
lines changed

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ matrix:
106106
- rustup target add x86_64-unknown-netbsd
107107
- rustup target add x86_64-unknown-redox
108108
- rustup target add x86_64-fortanix-unknown-sgx
109+
# For no_std targets
110+
- rustup component add rust-src
111+
- cargo install cargo-xbuild || true
109112
script:
110113
- cargo build --target=x86_64-sun-solaris --all-features
111114
- cargo build --target=x86_64-unknown-cloudabi --all-features
@@ -114,6 +117,7 @@ matrix:
114117
- cargo build --target=x86_64-unknown-netbsd --all-features
115118
- cargo build --target=x86_64-unknown-redox --all-features
116119
- cargo build --target=x86_64-fortanix-unknown-sgx --all-features
120+
- cargo xbuild --target=x86_64-unknown-uefi
117121
# also test minimum dependency versions are usable
118122
- cargo generate-lockfile -Z minimal-versions
119123
- cargo build --target=x86_64-sun-solaris --all-features
@@ -123,6 +127,7 @@ matrix:
123127
- cargo build --target=x86_64-unknown-netbsd --all-features
124128
- cargo build --target=x86_64-unknown-redox --all-features
125129
- cargo build --target=x86_64-fortanix-unknown-sgx --all-features
130+
- cargo xbuild --target=x86_64-unknown-uefi
126131

127132
# Trust cross-built/emulated targets. We must repeat all non-default values.
128133
- rust: stable

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,8 @@ stdweb = { version = "0.4.9", optional = true }
3939
[target.wasm32-wasi.dependencies]
4040
libc = "0.2.54"
4141

42+
[target.'cfg(any(target_env = "sgx", target_os = "uefi"))'.dependencies]
43+
lazy_static = { version = "1.3.0", features = ["spin_no_std"] }
44+
4245
[features]
4346
std = []

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ mod_use!(cfg(target_os = "redox"), use_file);
190190
mod_use!(cfg(target_os = "solaris"), solaris_illumos);
191191
mod_use!(cfg(windows), windows);
192192
mod_use!(cfg(target_env = "sgx"), rdrand);
193+
mod_use!(cfg(all(target_arch = "x86_64", target_os = "uefi")), rdrand);
193194
mod_use!(cfg(target_os = "wasi"), wasi);
194195

195196
mod_use!(
@@ -231,6 +232,7 @@ mod_use!(
231232
target_os = "openbsd",
232233
target_os = "redox",
233234
target_os = "solaris",
235+
all(target_arch = "x86_64", target_os = "uefi"),
234236
target_env = "sgx",
235237
windows,
236238
all(

src/rdrand.rs

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,61 @@
99
//! Implementation for SGX using RDRAND instruction
1010
use crate::Error;
1111
use core::mem;
12-
use core::arch::x86_64::_rdrand64_step;
12+
use core::arch::x86_64::{__cpuid, _rdrand64_step};
1313
use core::num::NonZeroU32;
14-
15-
#[cfg(not(target_feature = "rdrand"))]
16-
compile_error!("enable rdrand target feature!");
14+
use lazy_static::lazy_static;
1715

1816
// Recommendation from "Intel® Digital Random Number Generator (DRNG) Software
1917
// Implementation Guide" - Section 5.2.1 and "Intel® 64 and IA-32 Architectures
2018
// Software Developer’s Manual" - Volume 1 - Section 7.3.17.1.
2119
const RETRY_LIMIT: usize = 10;
2220
const WORD_SIZE: usize = mem::size_of::<u64>();
2321

24-
fn rdrand() -> Result<[u8; WORD_SIZE], Error> {
22+
#[target_feature(enable = "rdrand")]
23+
unsafe fn rdrand() -> Result<[u8; WORD_SIZE], Error> {
2524
for _ in 0..RETRY_LIMIT {
26-
unsafe {
27-
// SAFETY: we've checked RDRAND support, and u64 can have any value.
28-
let mut el = mem::uninitialized();
29-
if _rdrand64_step(&mut el) == 1 {
30-
return Ok(el.to_ne_bytes());
31-
}
32-
};
25+
let mut el = mem::uninitialized();
26+
if _rdrand64_step(&mut el) == 1 {
27+
return Ok(el.to_ne_bytes());
28+
}
3329
}
3430
error!("RDRAND failed, CPU issue likely");
3531
Err(Error::UNKNOWN)
3632
}
3733

34+
// "rdrand" target feature requires "+rdrnd" flag, see https://github.com/rust-lang/rust/issues/49653.
35+
#[cfg(all(target_env = "sgx", not(target_feature = "rdrand")))]
36+
compile_error!(
37+
"SGX targets require 'rdrand' target feature. Enable by using -C target-feature=+rdrnd."
38+
);
39+
40+
// TODO use is_x86_feature_detected!("rdrand") when that works in core. See:
41+
// https://github.com/rust-lang-nursery/stdsimd/issues/464
42+
fn is_rdrand_supported() -> bool {
43+
if cfg!(target_feature = "rdrand") {
44+
true
45+
} else {
46+
// SAFETY: All x86_64 CPUs support CPUID leaf 1
47+
const FLAG: u32 = 1 << 30;
48+
lazy_static! {
49+
static ref HAS_RDRAND: bool = unsafe { __cpuid(1).ecx & FLAG != 0 };
50+
}
51+
*HAS_RDRAND
52+
}
53+
}
54+
3855
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
56+
if !is_rdrand_supported() {
57+
return Err(Error::UNAVAILABLE);
58+
}
59+
60+
// SAFETY: After this point, rdrand is supported, so calling the rdrand
61+
// functions is not undefined behavior.
62+
unsafe { rdrand_exact(dest) }
63+
}
64+
65+
#[target_feature(enable = "rdrand")]
66+
unsafe fn rdrand_exact(dest: &mut [u8]) -> Result<(), Error> {
3967
// We use chunks_exact_mut instead of chunks_mut as it allows almost all
4068
// calls to memcpy to be elided by the compiler.
4169
let mut chunks = dest.chunks_exact_mut(WORD_SIZE);

0 commit comments

Comments
 (0)