mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 09:53:24 +00:00
Introduce the boot trojan
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
ddca4fb2fc
commit
953ff66fcc
@ -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"
|
@ -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()
|
||||
)
|
||||
}
|
@ -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.*)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)+)?))
|
||||
}
|
||||
}
|
@ -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:
|
@ -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
|
||||
}
|
@ -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 {}
|
||||
}
|
@ -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"
|
||||
}
|
Reference in New Issue
Block a user