[package]
name = "bootable_graphics"
version = "0.1.0"
edition = "2021"
[dependencies]
uefi = "0.31"
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
opt-level = "s"
lto = true
#![no_std]
#![no_main]
use uefi::prelude::*;
use uefi::proto::console::gop::{BltPixel, GraphicsOutput};
use uefi::table::boot::{OpenProtocolAttributes, OpenProtocolParams};
use uefi::table::runtime::ResetType;
use core::fmt::Write;
#[panic_handler]
fn panic_handler(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
#[entry]
fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
// ---- 将图形操作放在独立块中,结束后 gop 被释放 ----
let (width, height) = {
let gop_handle = system_table
.boot_services()
.get_handle_for_protocol::<GraphicsOutput>()
.expect("此固件不支持图形输出协议 (GOP)");
let mut gop = unsafe {
system_table
.boot_services()
.open_protocol::<GraphicsOutput>(
OpenProtocolParams {
handle: gop_handle,
agent: image_handle,
controller: None,
},
OpenProtocolAttributes::GetProtocol,
)
.expect("无法打开图形输出协议")
};
let mode = gop.current_mode_info();
let (w, h) = mode.resolution();
let stride = mode.stride();
let mut fb = gop.frame_buffer();
// 蓝色背景
let blue = BltPixel::new(0, 0, 255);
unsafe {
for y in 0..h {
for x in 0..w {
let offset = y * stride + x * 4;
if offset + 4 <= fb.size() {
fb.write_value(offset, &blue);
}
}
}
}
// 中央红色矩形
let rect_x = w / 4;
let rect_y = h / 4;
let rect_w = w / 2;
let rect_h = h / 2;
let red = BltPixel::new(255, 0, 0);
unsafe {
for y in rect_y..(rect_y + rect_h).min(h) {
for x in rect_x..(rect_x + rect_w).min(w) {
let offset = y * stride + x * 4;
if offset + 4 <= fb.size() {
fb.write_value(offset, &red);
}
}
}
}
// gop 在这里离开作用域,对 system_table 的借用结束
(w, h)
};
// ---- 文本输出(此时 system_table 已无借用) ----
let stdout = system_table.stdout();
stdout.reset(false).unwrap();
stdout.clear().unwrap();
write!(stdout, "=== Bare Metal Graphics ===\n").unwrap();
write!(stdout, "Resolution: {}x{}\n", width, height).unwrap();
write!(stdout, "Press any key to reboot...\n").unwrap();
// ---- 等待按键 ----
let stdin = system_table.stdin();
while stdin.read_key().is_err() {}
// ---- 冷重启 ----
system_table.runtime_services().reset(
ResetType::COLD,
Status::SUCCESS,
None,
);
}