vi and busybox

This commit is contained in:
wcjbr
2026-07-29 10:56:30 +08:00
commit 86dbf7482f
47 changed files with 9647 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
[package]
name = "zeroos-loader"
version = "0.1.0"
edition = "2024"
[dependencies]
+352
View File
@@ -0,0 +1,352 @@
#![no_std]
#![no_main]
use core::mem::size_of;
use core::panic::PanicInfo;
use core::ptr::{copy_nonoverlapping, null_mut};
type EfiHandle = *mut core::ffi::c_void;
type EfiStatus = usize;
const EFI_SUCCESS: EfiStatus = 0;
const EFI_LOAD_ERROR: EfiStatus = 1;
const EFI_BUFFER_TOO_SMALL: EfiStatus = 5;
const EFI_LOADED_IMAGE_PROTOCOL_GUID: EfiGuid = EfiGuid::new(
0x5b1b31a1,
0x9562,
0x11d2,
[0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b],
);
const EFI_DEVICE_PATH_PROTOCOL_GUID: EfiGuid = EfiGuid::new(
0x09576e91,
0x6d3f,
0x11d2,
[0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b],
);
const MEDIA_DEVICE_PATH: u8 = 0x04;
const MEDIA_FILEPATH_DP: u8 = 0x04;
const END_DEVICE_PATH_TYPE: u8 = 0x7f;
const END_ENTIRE_DEVICE_PATH_SUBTYPE: u8 = 0xff;
static ZEROOS_PATH: [u16; 23] = [
'\\' as u16,
'E' as u16,
'F' as u16,
'I' as u16,
'\\' as u16,
'Z' as u16,
'e' as u16,
'r' as u16,
'o' as u16,
'O' as u16,
'S' as u16,
'\\' as u16,
'Z' as u16,
'e' as u16,
'r' as u16,
'o' as u16,
'O' as u16,
'S' as u16,
'.' as u16,
'E' as u16,
'F' as u16,
'I' as u16,
0,
];
static LOADING: [u16; 22] = [
'L' as u16,
'o' as u16,
'a' as u16,
'd' as u16,
'i' as u16,
'n' as u16,
'g' as u16,
' ' as u16,
'Z' as u16,
'e' as u16,
'r' as u16,
'o' as u16,
'O' as u16,
'S' as u16,
'.' as u16,
'.' as u16,
'.' as u16,
'\r' as u16,
'\n' as u16,
0,
0,
0,
];
#[repr(C)]
#[derive(Clone, Copy)]
struct EfiGuid {
data1: u32,
data2: u16,
data3: u16,
data4: [u8; 8],
}
impl EfiGuid {
const fn new(data1: u32, data2: u16, data3: u16, data4: [u8; 8]) -> Self {
Self {
data1,
data2,
data3,
data4,
}
}
}
#[repr(C)]
struct EfiTableHeader {
signature: u64,
revision: u32,
header_size: u32,
crc32: u32,
reserved: u32,
}
#[repr(C)]
struct EfiSystemTable {
hdr: EfiTableHeader,
firmware_vendor: *mut u16,
firmware_revision: u32,
console_in_handle: EfiHandle,
con_in: *mut core::ffi::c_void,
console_out_handle: EfiHandle,
con_out: *mut EfiSimpleTextOutputProtocol,
standard_error_handle: EfiHandle,
std_err: *mut EfiSimpleTextOutputProtocol,
runtime_services: *mut core::ffi::c_void,
boot_services: *mut EfiBootServices,
number_of_table_entries: usize,
configuration_table: *mut core::ffi::c_void,
}
#[repr(C)]
struct EfiSimpleTextOutputProtocol {
reset: usize,
output_string:
extern "efiapi" fn(this: *mut EfiSimpleTextOutputProtocol, string: *const u16) -> EfiStatus,
}
#[repr(C)]
struct EfiBootServices {
hdr: EfiTableHeader,
raise_tpl: usize,
restore_tpl: usize,
allocate_pages: usize,
free_pages: usize,
get_memory_map: usize,
allocate_pool: usize,
free_pool: usize,
create_event: usize,
set_timer: usize,
wait_for_event: usize,
signal_event: usize,
close_event: usize,
check_event: usize,
install_protocol_interface: usize,
reinstall_protocol_interface: usize,
uninstall_protocol_interface: usize,
handle_protocol: extern "efiapi" fn(
handle: EfiHandle,
protocol: *const EfiGuid,
interface: *mut *mut core::ffi::c_void,
) -> EfiStatus,
reserved: usize,
register_protocol_notify: usize,
locate_handle: usize,
locate_device_path: usize,
install_configuration_table: usize,
load_image: extern "efiapi" fn(
boot_policy: u8,
parent_image_handle: EfiHandle,
device_path: *const EfiDevicePathProtocol,
source_buffer: *mut core::ffi::c_void,
source_size: usize,
image_handle: *mut EfiHandle,
) -> EfiStatus,
start_image: extern "efiapi" fn(
image_handle: EfiHandle,
exit_data_size: *mut usize,
exit_data: *mut *mut u16,
) -> EfiStatus,
}
#[repr(C)]
struct EfiLoadedImageProtocol {
revision: u32,
parent_handle: EfiHandle,
system_table: *mut EfiSystemTable,
device_handle: EfiHandle,
file_path: *mut EfiDevicePathProtocol,
reserved: *mut core::ffi::c_void,
load_options_size: u32,
load_options: *mut core::ffi::c_void,
image_base: *mut core::ffi::c_void,
image_size: u64,
image_code_type: u32,
image_data_type: u32,
unload: usize,
}
#[repr(C, packed)]
struct EfiDevicePathProtocol {
ty: u8,
sub_type: u8,
length: [u8; 2],
}
#[unsafe(no_mangle)]
extern "efiapi" fn efi_main(
image_handle: EfiHandle,
system_table: *mut EfiSystemTable,
) -> EfiStatus {
unsafe {
if system_table.is_null() || (*system_table).boot_services.is_null() {
return EFI_LOAD_ERROR;
}
write(system_table, LOADING.as_ptr());
let boot_services = (*system_table).boot_services;
let mut loaded_image = null_mut();
let status = ((*boot_services).handle_protocol)(
image_handle,
&EFI_LOADED_IMAGE_PROTOCOL_GUID,
&mut loaded_image,
);
if status != EFI_SUCCESS {
return status;
}
let loaded_image = loaded_image as *mut EfiLoadedImageProtocol;
let mut partition_device_path = null_mut();
let status = ((*boot_services).handle_protocol)(
(*loaded_image).device_handle,
&EFI_DEVICE_PATH_PROTOCOL_GUID,
&mut partition_device_path,
);
if status != EFI_SUCCESS {
return status;
}
let mut device_path_buffer = [0u8; 1024];
let device_path = match build_zeroos_device_path(
partition_device_path as *const EfiDevicePathProtocol,
&mut device_path_buffer,
) {
Ok(path) => path,
Err(status) => return status,
};
let mut zeroos_image = null_mut();
let status = ((*boot_services).load_image)(
0,
image_handle,
device_path,
null_mut(),
0,
&mut zeroos_image,
);
if status != EFI_SUCCESS {
return status;
}
((*boot_services).start_image)(zeroos_image, null_mut(), null_mut())
}
}
unsafe fn build_zeroos_device_path<'a>(
partition_path: *const EfiDevicePathProtocol,
buffer: &'a mut [u8],
) -> Result<*const EfiDevicePathProtocol, EfiStatus> {
if partition_path.is_null() {
return Err(EFI_LOAD_ERROR);
}
let partition_len = unsafe { device_path_len_without_end(partition_path)? };
let file_path_node_len = 4 + ZEROOS_PATH.len() * size_of::<u16>();
let total_len = partition_len + file_path_node_len + 4;
if total_len > buffer.len() || file_path_node_len > u16::MAX as usize {
return Err(EFI_BUFFER_TOO_SMALL);
}
unsafe {
copy_nonoverlapping(
partition_path as *const u8,
buffer.as_mut_ptr(),
partition_len,
);
}
let file_node = &mut buffer[partition_len..partition_len + file_path_node_len];
file_node[0] = MEDIA_DEVICE_PATH;
file_node[1] = MEDIA_FILEPATH_DP;
file_node[2] = (file_path_node_len & 0xff) as u8;
file_node[3] = (file_path_node_len >> 8) as u8;
unsafe {
copy_nonoverlapping(
ZEROOS_PATH.as_ptr() as *const u8,
file_node[4..].as_mut_ptr(),
ZEROOS_PATH.len() * size_of::<u16>(),
);
}
let end_node = &mut buffer[partition_len + file_path_node_len..total_len];
end_node[0] = END_DEVICE_PATH_TYPE;
end_node[1] = END_ENTIRE_DEVICE_PATH_SUBTYPE;
end_node[2] = 4;
end_node[3] = 0;
Ok(buffer.as_ptr() as *const EfiDevicePathProtocol)
}
unsafe fn device_path_len_without_end(
mut node: *const EfiDevicePathProtocol,
) -> Result<usize, EfiStatus> {
let mut len = 0;
for _ in 0..256 {
let node_len = unsafe { device_path_node_len(node) };
if node_len < 4 {
return Err(EFI_LOAD_ERROR);
}
if unsafe {
(*node).ty == END_DEVICE_PATH_TYPE && (*node).sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE
} {
return Ok(len);
}
len += node_len;
node = unsafe { (node as *const u8).add(node_len) as *const EfiDevicePathProtocol };
}
Err(EFI_LOAD_ERROR)
}
unsafe fn device_path_node_len(node: *const EfiDevicePathProtocol) -> usize {
unsafe { ((*node).length[0] as usize) | ((*node).length[1] as usize) << 8 }
}
unsafe fn write(system_table: *mut EfiSystemTable, text: *const u16) {
unsafe {
if !system_table.is_null() && !(*system_table).con_out.is_null() {
((*(*system_table).con_out).output_string)((*system_table).con_out, text);
}
}
}
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}