在uefi-rs中获取文件大小:如何将u8缓冲区转为FileInfo结构体
解决UEFI应用中u8缓冲区转FileInfo的问题
核心问题原因
你遇到的薄指针转胖指针失败的问题,本质是因为FileInfo在uefi-rs中是trait对象,它的引用是包含数据指针和vtable指针的胖指针;而你手里的u8缓冲区是单纯的薄指针(仅指向字节数据),直接通过transmute转换会丢失vtable信息,导致类型不兼容。
正确解决方案
uefi-rs的get_info方法本身就会返回FileInfo的合法引用,无需手动转换缓冲区。当你传入足够大的缓冲区后,该方法会自动填充数据并返回可用的&FileInfo引用,直接使用即可。
修改后的完整代码
#![no_main] #![no_std] #![feature(abi_efiapi)] #![allow(stable_features)] #[macro_use] extern crate alloc; use elf_rs::{Elf, ElfFile}; use log::info; use uefi::{ prelude::{entry, BootServices, cstr16}, Handle, table::{SystemTable, Boot}, Status, proto::{ loaded_image::LoadedImage, media::{ file::{File, FileHandle, FileMode, FileAttribute, FileInfo}, fs::SimpleFileSystem, }, }, CStr16, }; fn load_file(path: &CStr16, boot_services: &BootServices) -> FileHandle { let loaded_image = boot_services .open_protocol_exclusive::<LoadedImage>(boot_services.image_handle()) .unwrap(); let mut file_system = boot_services .open_protocol_exclusive::<SimpleFileSystem>(loaded_image.device()) .unwrap(); let mut directory = file_system.open_volume().unwrap(); directory .open(path, FileMode::Read, FileAttribute::READ_ONLY) .unwrap() } #[entry] fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status { uefi_services::init(&mut system_table).unwrap(); info!("Loading kernel..."); let mut kernel = load_file( cstr16!("kernel.elf"), system_table.boot_services(), ) .into_regular_file() .unwrap(); // 获取所需缓冲区大小 let mut small_buffer = vec![0u8; 0]; let size = kernel .get_info::<FileInfo>(&mut small_buffer) .err() .unwrap() .data() .unwrap(); // 分配足够大的缓冲区并获取FileInfo引用 let mut file_info_buffer = vec![0u8; size]; let info = kernel .get_info::<FileInfo>(&mut file_info_buffer) .unwrap(); // 读取ELF文件内容到缓冲区 let mut elf_buffer = vec![0u8; info.file_size().try_into().unwrap()]; kernel.read(&mut elf_buffer).unwrap(); let elf = Elf::from_bytes(&elf_buffer).expect("Kernel loading failed!"); info!("{:?} header: {:?}", elf, elf.elf_header()); for p in elf.program_header_iter() { info!("{:x?}", p); } for s in elf.section_header_iter() { info!("{:x?}", s); } let s = elf.lookup_section(b".text"); info!("s {:?}", s); system_table.boot_services().stall(100_000_000); Status::SUCCESS }
关键修改点
- 直接接收
get_info的返回值,获取合法的&FileInfo引用,跳过手动转换缓冲区的步骤 - 补充了
kernel.read(&mut elf_buffer).unwrap(),原代码仅创建空缓冲区但未读取文件内容,会导致后续ELF解析失败 - 移除了无效的手动指针转换逻辑,避免类型不匹配问题
内容的提问来源于stack exchange,提问作者Olle
相关产品推荐
相关产品推荐

