Rust UEFI开发宏库uefi-macros的使用,简化UEFI固件开发的宏工具集

uefi-macros

这个crate提供了过程宏,由uefi-rs项目使用,以简化UEFI应用程序的开发并减少样板代码。

元数据

pkg:cargo/uefi-macros@0.18.1

4个月前

v1.81.0

MIT OR Apache-2.0

12.2 KiB

安装

运行以下Cargo命令在您的项目目录中:

cargo add uefi-macros

或者将以下行添加到您的Cargo.toml中:

uefi-macros = “0.18.1”

文档

docs.rs/uefi-macros/0.18.1

仓库

github.com/rust-osdev/uefi-rs

所有者

Nicholas Bishop Gabriel Majeri Philipp Schuster

类别

API bindings Embedded development No standard library

报告crate

基于以上内容,以下是一个完整的示例demo:

// 在Cargo.toml中添加依赖
// uefi-macros = "0.18.1"

use uefi::prelude::*;
use uefi_macros::entry; // 使用uefi-macros提供的entry宏

// 使用entry宏定义UEFI入口点
#[entry]
fn main(_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
    // 初始化UEFI服务
    uefi_services::init(&mut system_table).unwrap();
    
    // 获取标准输出
    let stdout = system_table.stdout();
    
    // 输出欢迎信息
    stdout.output_string("Hello from Rust UEFI application!\n").unwrap();
    
    // 保持应用程序运行
    loop {}
    
    Status::SUCCESS
}

此示例展示了如何使用uefi-macros库中的entry宏来简化UEFI应用程序的入口点定义。entry宏会自动处理UEFI应用程序的初始化和清理工作,让开发者可以专注于应用程序逻辑。

完整示例代码:

// 在Cargo.toml中添加依赖
// uefi-macros = "0.18.1"
// uefi = "0.18.1"
// uefi-services = "0.18.1"

use uefi::prelude::*;
use uefi_macros::entry; // 使用uefi-macros提供的entry宏

// 使用entry宏定义UEFI入口点
#[entry]
fn main(_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
    // 初始化UEFI服务
    uefi_services::init(&mut system_table).unwrap();
    
    // 获取标准输出
    let stdout = system_table.stdout();
    
    // 输出欢迎信息
    stdout.output_string("Hello from Rust UEFI application!\n").unwrap();
    
    // 保持应用程序运行
    loop {}
    
    Status::SUCCESS
}

1 回复

Rust UEFI开发宏库uefi-macros使用指南

概述

uefi-macros是一个专为Rust UEFI开发设计的宏工具集,旨在简化UEFI应用程序和驱动程序的开发过程。该库提供了一系列过程宏,帮助开发者快速定义UEFI入口点、协议实现和其他UEFI相关结构。

主要特性

  • 自动生成UEFI入口点函数
  • 简化协议实现和使用的宏
  • 类型安全的UEFI句柄包装
  • 减少样板代码,提高开发效率

安装方法

在Cargo.toml中添加依赖:

[dependencies]
uefi = "0.14"
uefi-macros = "0.5"
uefi-services = "0.11"

核心宏使用示例

1. 定义UEFI入口点

use uefi::prelude::*;
use uefi_macros::entry;

#[entry]
fn main(_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
    uefi_services::init(&mut system_table).unwrap();
    
    // 你的UEFI应用程序逻辑
    system_table.stdout().clear().unwrap();
    system_table.stdout().output_string("Hello UEFI World!\r\n").unwrap();
    
    Status::SUCCESS
}

2. 协议实现宏

use uefi::proto::Protocol;
use uefi_macros::protocol;

#[protocol("7c2c87c1-5e5d-4a42-87d7-c18c3a2ab5b9")]
pub trait MyCustomProtocol: Protocol {
    fn do_something(&self, value: u64) -> uefi::Result<()>;
    fn get_status(&self) -> uefi::Result<bool>;
}

// 自动生成GUID和协议实现

3. 事件处理宏

use uefi_macros::event_handler;

#[event_handler]
fn timer_event(context: &mut MyContext) -> uefi::Result<()> {
    println!("Timer triggered!");
    context.counter += 1;
    Ok(())
}

4. 协议定位宏

use uefi_macros::locate_protocol;

fn use_graphics_output(system_table: &SystemTable<Boot>) -> uefi::Result<()> {
    let gop = locate_protocol!(system_table, GraphicsOutput)?;
    
    // 使用图形输出协议
    let mode = gop.current_mode_info();
    println!("Current resolution: {}x{}", mode.resolution().0, mode.resolution().1);
    
    Ok(())
}

完整示例:简单的UEFI应用

#![no_std]
#![no_main]

use uefi::prelude::*;
use uefi_macros::entry;
use uefi::proto::console::text::Output;
use uefi::table::boot::BootServices;

#[entry]
fn main(handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
    uefi_services::init(&mut system_table).unwrap();
    
    let boot_services = system_table.boot_services();
    
    // 清屏
    system_table.stdout().clear().unwrap();
    
    // 输出欢迎信息
    system_table.stdout()
        .output_string("Welcome to UEFI Rust Development!\r\n")
        .unwrap();
    
    // 演示协议使用
    if let Ok(runtime_services) = boot_services.locate_protocol::<uefi::proto::runtime::Runtime>() {
        println!("Runtime services protocol found");
    }
    
    Status::SUCCESS
}

完整示例demo

#![no_std]
#![no_main]
#![feature(abi_efiapi)]

use uefi::prelude::*;
use uefi_macros::entry;
use uefi::proto::console::text::Output;
use uefi::table::boot::BootServices;
use uefi::proto::Protocol;
use uefi::Result;

// 自定义协议定义
#[protocol("7c2c87c1-5e5d-4a42-87d7-c18c3a2ab5b9")]
pub trait MyCustomProtocol: Protocol {
    fn do_something(&self, value: u64) -> Result<()>;
    fn get_status(&self) -> Result<bool>;
}

// 自定义上下文结构
struct AppContext {
    counter: u32,
    system_table: SystemTable<Boot>,
}

#[entry]
fn main(handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
    // 初始化UEFI服务
    uefi_services::init(&mut system_table).unwrap();
    
    let boot_services = system_table.boot_services();
    
    // 清屏操作
    system_table.stdout().clear().unwrap();
    
    // 输出欢迎信息
    system_table.stdout()
        .output_string("=== UEFI Rust应用程序示例 ===\r\n")
        .unwrap();
    
    // 创建应用上下文
    let mut context = AppContext {
        counter: 0,
        system_table: system_table.unsafe_clone(),
    };
    
    // 演示协议定位和使用
    match boot_services.locate_protocol::<uefi::proto::runtime::Runtime>() {
        Ok(runtime_protocol) => {
            system_table.stdout()
                .output_string("✓ Runtime服务协议已找到\r\n")
                .unwrap();
        }
        Err(_) => {
            system_table.stdout()
                .output_string("✗ Runtime服务协议未找到\r\n")
                .unwrap();
        }
    }
    
    // 演示图形输出协议(如果可用)
    if let Ok(gop) = boot_services.locate_protocol::<uefi::proto::console::gop::GraphicsOutput>() {
        let mode = gop.current_mode_info();
        let (width, height) = mode.resolution();
        
        let mut output = String::new();
        ufmt::uwrite!(&mut output, "当前分辨率: {}x{}\r\n", width, height).unwrap();
        system_table.stdout().output_string(&output).unwrap();
    }
    
    // 计数器演示
    context.counter += 1;
    let mut counter_msg = String::new();
    ufmt::uwrite!(&mut counter_msg, "程序运行计数: {}\r\n", context.counter).unwrap();
    system_table.stdout().output_string(&counter_msg).unwrap();
    
    // 输出完成信息
    system_table.stdout()
        .output_string("=== 应用程序执行完成 ===\r\n")
        .unwrap();
    
    Status::SUCCESS
}

// 简单的事件处理函数示例
#[event_handler]
fn simple_timer_event(context: &mut AppContext) -> Result<()> {
    context.counter += 1;
    
    let mut message = String::new();
    ufmt::uwrite!(&mut message, "定时器触发! 计数: {}\r\n", context.counter).unwrap();
    context.system_table.stdout().output_string(&message).unwrap();
    
    Ok(())
}

最佳实践

  1. 始终使用#[entry]宏定义UEFI入口点
  2. 利用协议宏确保类型安全的协议实现
  3. 使用提供的错误处理宏简化Result处理
  4. 在开发时启用相应的Cargo features进行调试

注意事项

  • 需要配合uefiuefi-servicescrate使用
  • 确保目标平台设置为UEFI环境
  • 编译时需要#![no_std]#![no_main]属性
  • 建议使用cargo-xbuild或类似工具进行交叉编译

这个宏库显著简化了Rust UEFI开发的复杂性,让开发者能够更专注于业务逻辑而不是底层细节。

回到顶部