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”
文档
仓库
所有者
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(())
}
最佳实践
- 始终使用
#[entry]
宏定义UEFI入口点 - 利用协议宏确保类型安全的协议实现
- 使用提供的错误处理宏简化Result处理
- 在开发时启用相应的Cargo features进行调试
注意事项
- 需要配合
uefi
和uefi-services
crate使用 - 确保目标平台设置为UEFI环境
- 编译时需要
#![no_std]
和#![no_main]
属性 - 建议使用cargo-xbuild或类似工具进行交叉编译
这个宏库显著简化了Rust UEFI开发的复杂性,让开发者能够更专注于业务逻辑而不是底层细节。