You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 12:50:22