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
+179
View File
@@ -0,0 +1,179 @@
use core::ffi::c_void;
use crate::efi::{
EFI_LOADED_IMAGE_PROTOCOL_GUID, EFI_NOT_FOUND, EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
EFI_SUCCESS, EfiBootServices, EfiGuid, EfiHandle, EfiLoadedImageProtocol, EfiStatus,
};
use crate::memory::{PAGE_SIZE, PhysicalMemoryManager};
pub const BASH_PATH: &[u16] = &[
'\\' as u16,
'b' as u16,
'i' as u16,
'n' as u16,
'\\' as u16,
'b' as u16,
'a' as u16,
's' as u16,
'h' as u16,
0,
];
pub const SH_PATH: &[u16] = &[
'\\' as u16,
'b' as u16,
'i' as u16,
'n' as u16,
'\\' as u16,
's' as u16,
'h' as u16,
0,
];
const EFI_FILE_MODE_READ: u64 = 1;
const EFI_FILE_INFO_GUID: EfiGuid = EfiGuid::new(
0x09576e92,
0x6d3f,
0x11d2,
[0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b],
);
pub struct LoadedFile {
pub ptr: *const u8,
pub len: usize,
}
#[repr(C)]
struct EfiSimpleFileSystemProtocol {
revision: u64,
open_volume: extern "efiapi" fn(
this: *mut EfiSimpleFileSystemProtocol,
root: *mut *mut EfiFileProtocol,
) -> EfiStatus,
}
#[repr(C)]
struct EfiFileProtocol {
revision: u64,
open: extern "efiapi" fn(
this: *mut EfiFileProtocol,
new_handle: *mut *mut EfiFileProtocol,
file_name: *const u16,
open_mode: u64,
attributes: u64,
) -> EfiStatus,
close: extern "efiapi" fn(this: *mut EfiFileProtocol) -> EfiStatus,
delete: usize,
read: extern "efiapi" fn(
this: *mut EfiFileProtocol,
buffer_size: *mut usize,
buffer: *mut c_void,
) -> EfiStatus,
write: usize,
get_position: usize,
set_position: usize,
get_info: extern "efiapi" fn(
this: *mut EfiFileProtocol,
information_type: *const EfiGuid,
buffer_size: *mut usize,
buffer: *mut c_void,
) -> EfiStatus,
}
#[repr(C)]
struct EfiFileInfoPrefix {
size: u64,
file_size: u64,
physical_size: u64,
}
pub unsafe fn load_file(
image_handle: EfiHandle,
boot_services: *mut EfiBootServices,
memory: &mut PhysicalMemoryManager,
path: &[u16],
) -> Option<LoadedFile> {
let mut loaded_image = core::ptr::null_mut();
let status = unsafe {
((*boot_services).handle_protocol)(
image_handle,
&EFI_LOADED_IMAGE_PROTOCOL_GUID,
&mut loaded_image,
)
};
if status != EFI_SUCCESS || loaded_image.is_null() {
return None;
}
let loaded_image = loaded_image as *mut EfiLoadedImageProtocol;
let mut fs = core::ptr::null_mut();
let status = unsafe {
((*boot_services).handle_protocol)(
(*loaded_image).device_handle,
&EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
&mut fs,
)
};
if status != EFI_SUCCESS || fs.is_null() {
return None;
}
let fs = fs as *mut EfiSimpleFileSystemProtocol;
let mut root = core::ptr::null_mut();
let status = unsafe { ((*fs).open_volume)(fs, &mut root) };
if status != EFI_SUCCESS || root.is_null() {
return None;
}
let mut file = core::ptr::null_mut();
let status = unsafe { ((*root).open)(root, &mut file, path.as_ptr(), EFI_FILE_MODE_READ, 0) };
unsafe {
((*root).close)(root);
}
if status == EFI_NOT_FOUND || status != EFI_SUCCESS || file.is_null() {
return None;
}
let size = unsafe { file_size(file)? };
let pages = size.div_ceil(PAGE_SIZE).max(1);
let buffer = memory.alloc_pages(pages)?;
let mut read_len = size;
let status = unsafe { ((*file).read)(file, &mut read_len, buffer.cast::<c_void>()) };
unsafe {
((*file).close)(file);
}
if status != EFI_SUCCESS || read_len == 0 {
unsafe {
memory.free_pages(buffer, pages);
}
return None;
}
Some(LoadedFile {
ptr: buffer as *const u8,
len: read_len,
})
}
unsafe fn file_size(file: *mut EfiFileProtocol) -> Option<usize> {
let mut info_buffer = [0u8; 1024];
let mut info_size = info_buffer.len();
let status = unsafe {
((*file).get_info)(
file,
&EFI_FILE_INFO_GUID,
&mut info_size,
info_buffer.as_mut_ptr().cast::<c_void>(),
)
};
if status != EFI_SUCCESS {
return None;
}
if info_size < core::mem::size_of::<EfiFileInfoPrefix>() {
return None;
}
let info = unsafe { &*(info_buffer.as_ptr() as *const EfiFileInfoPrefix) };
usize::try_from(info.file_size).ok()
}