Introduce the boot trojan

This commit is contained in:
Zhang Junyang
2023-11-12 15:49:35 +08:00
committed by Tate, Hongliang Tian
parent ddca4fb2fc
commit 953ff66fcc
22 changed files with 767 additions and 209 deletions

View File

@ -1,10 +0,0 @@
[package]
name = "aster-frame-x86-boot-linux-setup"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
uart_16550 = "0.3.0"
xmas-elf = "0.8.0"

View File

@ -1,9 +0,0 @@
use std::path::PathBuf;
fn main() {
let source_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
println!(
"cargo:rustc-link-arg-bins=--script={}",
source_dir.join("linker.ld").display()
)
}

View File

@ -1,32 +0,0 @@
ENTRY(start_of_setup32)
OUTPUT_ARCH(i386:x86)
OUTPUT_FORMAT(elf32-i386)
SETUP32_LMA = 0x100000;
SECTIONS
{
. = SETUP32_LMA - 0x1000;
.header : { KEEP(*(.header)) }
. = SETUP32_LMA;
.header.text : { KEEP(*(.header)) }
.stack : { KEEP(*(.stack)) }
.text : { *(.text .text.*) }
.rodata : { *(.rodata .rodata.*) }
.data : { *(.data .data.*) }
.bss : {
__bss = .;
*(.bss .bss.*) *(COMMON)
__bss_end = .;
}
.eh_frame : {
*(.eh_frame .eh_frame.*)
}
.eh_frame_hdr : {
*(.eh_frame_hdr .eh_frame_hdr.*)
}
}

View File

@ -1,12 +0,0 @@
const FIELD_PAYLOAD_OFFSET: u32 = 0x248;
const FIELD_PAYLOAD_LENGTH: u32 = 0x24c;
/// Safty: user must ensure that the boot_params_ptr is valid
pub unsafe fn get_payload_offset(boot_params_ptr: u32) -> u32 {
*((boot_params_ptr + FIELD_PAYLOAD_OFFSET) as *const u32)
}
/// Safty: user must ensure that the boot_params_ptr is valid
pub unsafe fn get_payload_length(boot_params_ptr: u32) -> u32 {
*((boot_params_ptr + FIELD_PAYLOAD_LENGTH) as *const u32)
}

View File

@ -1,53 +0,0 @@
use core::fmt::{self, Write};
use uart_16550::SerialPort;
struct Stdout {
serial_port: SerialPort,
}
static mut STDOUT: Stdout = Stdout {
serial_port: unsafe { SerialPort::new(0x0) },
};
/// safety: this function must only be called once
pub unsafe fn init() {
STDOUT = Stdout::init();
}
impl Stdout {
/// safety: this function must only be called once
pub unsafe fn init() -> Self {
let mut serial_port = unsafe { SerialPort::new(0x3F8) };
serial_port.init();
Self { serial_port }
}
}
impl Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.serial_port.write_str(s).unwrap();
Ok(())
}
}
pub fn print(args: fmt::Arguments) {
// safety: init() must be called before print() and there is no race condition
unsafe {
STDOUT.write_fmt(args).unwrap();
}
}
#[macro_export]
macro_rules! print {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!($fmt $(, $($arg)+)?))
}
}
#[macro_export]
macro_rules! println {
($fmt: literal $(, $($arg: tt)+)?) => {
$crate::console::print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?))
}
}

View File

@ -1,92 +0,0 @@
// The compatibility file for the Linux x86 Boot Protocol.
// See https://www.kernel.org/doc/html/v5.6/x86/boot.html for
// more information on the Linux x86 Boot Protocol.
.section ".header", "a"
// The Linux x86 Boot Protocol header.
//
// Some of the fields filled with a 0xab* values should be filled
// by the runner, which is the only tool after building and can
// access the info of the payload.
// Asterinas will use only a few of these fields, and some of them
// are filled by the loader and will be read by Asterinas.
CODE32_START = 0x100000
.code16
.org 0x01f1
hdr_start:
setup_sects: .byte 7 # so that the legacy setup could occupy a page
root_flags: .word 1
syssize: .long 0
ram_size: .word 0
vid_mode: .word 0xfffd
root_dev: .word 0
boot_flag: .word 0xAA55
jump: .byte 0xeb
jump_addr: .byte hdr_end-jump_addr
magic: .ascii "HdrS"
.word 0x020f
realmode_swtch: .word 0, 0
start_sys_seg: .word 0
.word 0
type_of_loader: .byte 0
loadflags: .byte (1 << 0)
setup_move_size: .word 0
code32_start: .long CODE32_START
ramdisk_image: .long 0
ramdisk_size: .long 0
bootsect_kludge: .long 0
heap_end_ptr: .word 65535
ext_loader_ver: .byte 0
ext_loader_type: .byte 0
cmd_line_ptr: .long 0
initrd_addr_max: .long 0x7fffffff
kernel_alignment: .long 0x1000000
relocatable_kernel: .byte 0
min_alignment: .byte 0x10
xloadflags: .word 0 # none of the flags supported
cmdline_size: .long 4096-1
hardware_subarch: .long 0
hardware_subarch_data: .quad 0
payload_offset: .long 0xabababab # at 0x248/4, to be filled by the runner
payload_length: .long 0xabababab # at 0x24c/4, to be filled by the runner
setup_data: .quad 0
pref_address: .quad 0
init_size: .long 0xabababab # at 0x260/4, to be filled by the runner
handover_offset: .long 0
kernel_info_offset: .long 0
hdr_end:
// End of header.
// 32-bit setup code starts here, and will be loaded at CODE32_START.
.section ".header.text", "ax"
.code32
.global start_of_setup32
start_of_setup32:
mov eax, offset stack_bottom
mov esp, eax
mov eax, offset halt
push eax # the return address
mov ebp, esp
add ebp, -4
push ebp
mov ebp, esp
.extern _rust_setup_entry
push esi # the boot_params pointer
call _rust_setup_entry
// Unreachable here.
halt:
hlt
jmp halt
// A small stack for the setup code.
.section ".stack", "aw"
SETUP_STACK_SIZE = 0x1000
.align 16
stack_top:
.skip SETUP_STACK_SIZE
stack_bottom:

View File

@ -1,29 +0,0 @@
use xmas_elf::program::{ProgramHeader, SegmentData};
pub fn load_elf(file: &[u8]) -> u32 {
let elf = xmas_elf::ElfFile::new(file).unwrap();
for ph in elf.program_iter() {
let ProgramHeader::Ph64(program) = ph else {
panic!("[setup] Unexpected program header type!");
};
if program.get_type().unwrap() == xmas_elf::program::Type::Load {
let SegmentData::Undefined(header_data) = program.get_data(&elf).unwrap() else {
panic!("[setup] Unexpected segment data type!");
};
// Safety: the physical address from the ELF file is valid
let dst_slice = unsafe {
core::slice::from_raw_parts_mut(
program.physical_addr as *mut u8,
program.mem_size as usize,
)
};
dst_slice[..program.file_size as usize].copy_from_slice(header_data);
let zero_slice = &mut dst_slice[program.file_size as usize..];
zero_slice.fill(0);
}
}
// Return the Linux 32-bit Boot Protocol entry point defined by Asterinas.
0x8001000
}

View File

@ -1,44 +0,0 @@
#![no_std]
#![no_main]
mod boot_params;
mod console;
mod loader;
use core::arch::{asm, global_asm};
global_asm!(include_str!("header.S"));
unsafe fn call_aster_entrypoint(entrypoint: u32, boot_params_ptr: u32) -> ! {
asm!("mov esi, {}", in(reg) boot_params_ptr);
asm!("mov eax, {}", in(reg) entrypoint);
asm!("jmp eax");
unreachable!();
}
#[no_mangle]
pub extern "cdecl" fn _rust_setup_entry(boot_params_ptr: u32) -> ! {
// Safety: this init function is only called once.
unsafe { console::init() };
println!("[setup] boot_params_ptr: {:#x}", boot_params_ptr);
let payload_offset = unsafe { boot_params::get_payload_offset(boot_params_ptr) };
let payload_length = unsafe { boot_params::get_payload_length(boot_params_ptr) };
let payload = unsafe {
core::slice::from_raw_parts_mut(payload_offset as *mut u8, payload_length as usize)
};
println!("[setup] loading ELF payload...");
let entrypoint = loader::load_elf(payload);
println!("[setup] entrypoint: {:#x}", entrypoint);
// Safety: the entrypoint and the ptr is valid.
unsafe { call_aster_entrypoint(entrypoint, boot_params_ptr) };
}
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
println!("panic: {:?}", info);
loop {}
}

View File

@ -1,20 +0,0 @@
{
"llvm-target": "i386-unknown-none",
"data-layout": "e-m:e-i32:32-f80:128-n8:16:32-S128-p:32:32",
"cpu": "i386",
"arch": "x86",
"dynamic-linking": false,
"executables": true,
"linker-flavor": "ld.lld",
"linker": "rust-lld",
"max-atomic-width": 64,
"position-independent-executables": false,
"disable-redzone": true,
"target-c-int-width": "32",
"target-pointer-width": "32",
"target-endian": "little",
"panic-strategy": "abort",
"os": "none",
"relocation-model": "static",
"features": "+soft-float,-sse,-mmx"
}