#![no_std]
#![feature(asm_const, asm_sym, naked_functions)]
#![deny(clippy::all)]
#![deny(missing_docs)]
#![warn(rust_2018_idioms)]
#![no_main]
#[allow(unused_extern_crates)]
extern crate rcrt1;
use core::arch::asm;
use enarx_shim_sgx::{
entry, handler, shim_address, ATTR, BLOCK_SIZE, ENARX_EXEC_START, ENARX_SHIM_ADDRESS,
ENCL_SIZE, ENCL_SIZE_BITS, MISC,
};
#[panic_handler]
#[cfg(not(test))]
#[allow(clippy::empty_loop)]
fn panic(_info: &core::panic::PanicInfo<'_>) -> ! {
loop {}
}
use noted::noted;
use sallyport::{elf::note, REQUIRES};
use sgx::parameters::{Attributes, MiscSelect};
use sgx::ssa::{GenPurposeRegs, StateSaveArea};
noted! {
static NOTE_REQUIRES<note::NAME, note::REQUIRES, [u8; REQUIRES.len()]> = REQUIRES;
static NOTE_BLOCK_SIZE<note::NAME, note::BLOCK_SIZE, u64> = BLOCK_SIZE as u64;
static NOTE_BITS<note::NAME, note::sgx::BITS, u8> = ENCL_SIZE_BITS;
static NOTE_SSAP<note::NAME, note::sgx::SSAP, u8> = 1;
static NOTE_PID<note::NAME, note::sgx::PID, u16> = 0;
static NOTE_SVN<note::NAME, note::sgx::SVN, u16> = 0;
static NOTE_MISC<note::NAME, note::sgx::MISC, MiscSelect> = MISC;
static NOTE_MISCMASK<note::NAME, note::sgx::MISCMASK, MiscSelect> = MISC;
static NOTE_ATTR<note::NAME, note::sgx::ATTR, Attributes> = ATTR;
static NOTE_ATTRMASK<note::NAME, note::sgx::ATTRMASK, Attributes> = ATTR;
}
#[naked]
extern "sysv64" fn clearx() {
use const_default::ConstDefault;
static XSAVE: xsave::XSave = <xsave::XSave as ConstDefault>::DEFAULT;
unsafe {
asm!(
"xor r10, r10",
"xor r11, r11",
"push QWORD PTR 0",
"popfq",
"push rax ", "push rdx ", "mov rdx, ~0 ", "mov rax, ~0 ", "xrstor [rip + {XSAVE}]", "pop rdx ", "pop rax ",
"ret",
XSAVE = sym XSAVE,
options(noreturn)
)
}
}
#[naked]
extern "sysv64" fn clearp() {
unsafe {
asm!(
"xor rax, rax",
"xor rdi, rdi",
"xor rsi, rsi",
"xor rdx, rdx",
"xor rcx, rcx",
"xor r8, r8",
"xor r9, r9",
"ret",
options(noreturn)
)
}
}
#[naked]
unsafe extern "sysv64" fn relocate() {
asm!(
"push rax",
"push rdi",
"push rsi",
"push rdx",
"push rcx",
"push r8",
"push r9",
"push r10",
"push r11",
"lea rdi, [rip + _DYNAMIC]", "lea rsi, [rip + {ENARX_SHIM_ADDRESS}]", "call {DYN_RELOC}",
"pop r11",
"pop r10",
"pop r9",
"pop r8",
"pop rcx",
"pop rdx",
"pop rsi",
"pop rdi",
"pop rax",
"ret",
DYN_RELOC = sym rcrt1::dyn_reloc,
ENARX_SHIM_ADDRESS = sym ENARX_SHIM_ADDRESS,
options(noreturn)
)
}
#[naked]
#[no_mangle]
pub unsafe extern "sysv64" fn _start() -> ! {
use core::mem::size_of;
asm!(
"cld ", "xchg rbx, rcx ",
"cmp rax, 0 ", "jne 2f ", "mov r10, rcx ", "jmp 3f ",
"2: ",
"mov r10, rax ", "shl r10, 12 ", "add r10, rcx ",
"mov r11, [r10 + {EXTO}] ", "cmp r11, 0 ", "je 2b ",
"mov r10, [r10 + {RSPO}] ", "sub r10, 128 ",
"3: ",
"and r10, ~0xf ", "xchg rsp, r10 ", "sub rsp, 8 ", "push r10 ",
"cmp rax, 0 ", "jne 4f ", "call {RELOC} ",
"4: ", "lea rsi, [rcx + 4096] ", "mov rdx, rax ", "call {CLEARX} ", "call {ENTRY} ", "call {CLEARX} ", "call {CLEARP} ",
"pop rsp ", "mov rax, {EEXIT} ", "enclu ",
RSPO = const size_of::<StateSaveArea>() - size_of::<GenPurposeRegs>() + 32,
EXTO = const size_of::<xsave::XSave>(),
CLEARX = sym clearx,
CLEARP = sym clearp,
RELOC = sym relocate,
ENTRY = sym main,
EEXIT = const sgx::enclu::EEXIT,
options(noreturn)
)
}
unsafe extern "C" fn main(
block: &mut [usize; BLOCK_SIZE / core::mem::size_of::<usize>()],
ssas: &mut [StateSaveArea; 3],
cssa: usize,
) {
ssas[cssa].extra[0] = 1;
let block_start = block.as_ptr() as usize;
let block_end = block_start + BLOCK_SIZE;
let shim_start = shim_address();
let shim_end = shim_start + ENCL_SIZE;
if (block_start >= shim_start && block_start < shim_end)
|| (block_end > shim_start && block_end <= shim_end)
{
panic!();
}
match cssa {
0 => entry::entry(&ENARX_EXEC_START as *const u8 as _),
1 => handler::Handler::handle(&mut ssas[0], block.as_mut_slice()),
n => handler::Handler::finish(&mut ssas[n - 1]),
}
ssas[cssa].extra[0] = 0;
}