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

tock-responder: Implement more libc stubs #37

Merged
merged 2 commits into from
Jan 12, 2024
Merged
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
100 changes: 88 additions & 12 deletions tock-responder/src/libc_stubs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,36 @@ fn libspdm_get_random_number_64(rand_data: *mut u64) -> bool {
if let Err(why) = Rng::get_bytes_sync(&mut rng_buf, 8) {
panic!("rng error: {:?}", why);
}
assert!(
rng_buf.iter().any(|&x| x != 0),
"Unlikely that all elements are zero"
);
let rng = u64::from_be_bytes(rng_buf);
assert_ne!(rng, 0);
unsafe {
*rand_data = u64::from_be_bytes(rng_buf);
*rand_data = rng;
}
true
}

#[no_mangle]
/// Return a random integer between [0 and i32::MAX].
pub extern "C" fn rand() -> i32 {
if let Err(why) = Rng::exists() {
panic!("rng error: {:?}", why);
}
// Request 4 bytes of RNG.
let mut rng_buf: [u8; 4] = [0; 4];
if let Err(why) = Rng::get_bytes_sync(&mut rng_buf, 4) {
panic!("rng error: {:?}", why);
}

let mut rng = i32::from_be_bytes(rng_buf);
// The valid output range is [0, i32::MAX], so if the signed bit is
// set from HW RNG, invert it.
if rng < 0 {
rng = rng.wrapping_neg();
}
assert_ne!(rng, 0);
rng
}

// Based on https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/builtins/bswapsi2.c
#[no_mangle]
pub extern "C" fn __bswapsi2(u: u32) -> u32 {
Expand Down Expand Up @@ -103,8 +123,69 @@ pub extern "C" fn time() {
}

#[no_mangle]
pub extern "C" fn strncmp() {
todo!("libc/stub: strncmp(): not yet implemented");
/// Compare no more than N characters of S1 and S2,
/// returning less than, equal to or greater than zero
/// if S1 is lexicographically less than, equal to or
/// greater than S2.
/// Based on: https://github.com/zerovm/glibc/blob/3f07350498160f552350dc39f6fe6d237c7c3b03/string/strncmp.c#L28C4-L29C20
pub extern "C" fn strncmp(s1: *const c_char, s2: *const c_char, n: usize) -> i32 {
let mut s1 = s1;
let mut s2 = s2;
let mut n = n;

let mut c1: u8 = b'\0';
let mut c2: u8 = b'\0';

if n >= 4 {
let mut n4 = n >> 2;
while n4 > 0 {
c1 = unsafe { *s1 as u8 };
s1 = unsafe { s1.offset(1) };
c2 = unsafe { *s2 as u8 };
s2 = unsafe { s2.offset(1) };
if c1 == b'\0' || c1 != c2 {
return (c1 as i32) - (c2 as i32);
}
c1 = unsafe { *s1 as u8 };
s1 = unsafe { s1.offset(1) };
c2 = unsafe { *s2 as u8 };
s2 = unsafe { s2.offset(1) };
if c1 == b'\0' || c1 != c2 {
return (c1 as i32) - (c2 as i32);
}
c1 = unsafe { *s1 as u8 };
s1 = unsafe { s1.offset(1) };
c2 = unsafe { *s2 as u8 };
s2 = unsafe { s2.offset(1) };
if c1 == b'\0' || c1 != c2 {
return (c1 as i32) - (c2 as i32);
}
c1 = unsafe { *s1 as u8 };
s1 = unsafe { s1.offset(1) };
c2 = unsafe { *s2 as u8 };
s2 = unsafe { s2.offset(1) };
if c1 == b'\0' || c1 != c2 {
return (c1 as i32) - (c2 as i32);
}

n4 -= 1;
}
n &= 3;
}

while n > 0 {
c1 = unsafe { *s1 as u8 };
s1 = unsafe { s1.offset(1) };
c2 = unsafe { *s2 as u8 };
s2 = unsafe { s2.offset(1) };
if c1 == b'\0' || c1 != c2 {
return (c1 as i32) - (c2 as i32);
}

n -= 1;
}

(c1 as i32) - (c2 as i32)
}

#[no_mangle]
Expand All @@ -121,8 +202,3 @@ pub extern "C" fn strchr() {
pub extern "C" fn strcmp() {
todo!("libc/stub: strcmp(): not yet implemented");
}

#[no_mangle]
pub extern "C" fn rand() {
todo!("libc/stub: rand(): not yet implemented");
}