Compare commits

..

No commits in common. "7d12f92a2276d2736d62dfdd26c7d19b9c172123" and "5b9f765be086cdfab36b50b089650e34725acab8" have entirely different histories.

7 changed files with 51 additions and 191 deletions

45
Cargo.lock generated
View file

@ -26,18 +26,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "arbitrary-int"
version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c84fc003e338a6f69fbd4f7fe9f92b535ff13e9af8997f3b14b6ddff8b1df46d"
[[package]]
name = "arrayref"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
[[package]] [[package]]
name = "atomic-polyfill" name = "atomic-polyfill"
version = "1.0.3" version = "1.0.3"
@ -135,7 +123,6 @@ name = "efigife"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"embedded-graphics", "embedded-graphics",
"log",
"tinygif", "tinygif",
"uefi", "uefi",
"uefi-graphics2", "uefi-graphics2",
@ -297,17 +284,6 @@ version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "mbrs"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d080a720bb58430e0039347784859f9be41bf8578307b8156be4e02ca3b316e"
dependencies = [
"arbitrary-int",
"arrayref",
"thiserror",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.2" version = "2.7.2"
@ -469,26 +445,6 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "thiserror"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]] [[package]]
name = "tinygif" name = "tinygif"
version = "0.0.4" version = "0.0.4"
@ -740,5 +696,4 @@ name = "xtask"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fatfs", "fatfs",
"mbrs",
] ]

View file

@ -12,8 +12,6 @@ resolver = "2"
[workspace.dependencies] [workspace.dependencies]
fatfs = { path = "rust-fatfs", default-features = false, features = ["alloc", "chrono"] } fatfs = { path = "rust-fatfs", default-features = false, features = ["alloc", "chrono"] }
embedded-graphics = "0.8.1" embedded-graphics = "0.8.1"
log = "0.4.21"
mbrs = "0.3.1"
tinygif = { version = "0.0.4", features = ["8k"] } tinygif = { version = "0.0.4", features = ["8k"] }
uefi = { version = "0.28.0", features = ["global_allocator", "panic_handler", "alloc"] } uefi = { version = "0.28.0", features = ["global_allocator", "panic_handler", "alloc"] }
uefi-graphics2 = "0.1.3" uefi-graphics2 = "0.1.3"

View file

@ -7,7 +7,6 @@ edition = "2021"
[dependencies] [dependencies]
embedded-graphics.workspace = true embedded-graphics.workspace = true
log.workspace = true
tinygif.workspace = true tinygif.workspace = true
uefi.workspace = true uefi.workspace = true
uefi-graphics2.workspace = true uefi-graphics2.workspace = true

View file

@ -1,8 +1,6 @@
#![no_main] #![no_main]
#![no_std] #![no_std]
extern crate alloc;
use core::time::Duration; use core::time::Duration;
use uefi::prelude::*; use uefi::prelude::*;
@ -19,26 +17,22 @@ const GIF_SIZE: usize = include_bytes!("bad-apple.gif").len();
#[entry] #[entry]
fn main(_image_handle: Handle, mut boot_system_table: SystemTable<Boot>) -> Status { fn main(_image_handle: Handle, mut boot_system_table: SystemTable<Boot>) -> Status {
uefi::helpers::init(&mut boot_system_table).expect("helper init"); uefi::helpers::init(&mut boot_system_table).unwrap();
log::info!("hello!");
// Disable the watchdog timer // Disable the watchdog timer
boot_system_table boot_system_table
.boot_services() .boot_services()
.set_watchdog_timer(0, 0x10000, None) .set_watchdog_timer(0, 0x10000, None)
.expect("disable watchdog timer"); .unwrap();
let boot_services = boot_system_table.boot_services(); let boot_services = boot_system_table.boot_services();
boot_services.stall(1_000_000);
let img_handle = boot_services.image_handle(); let img_handle = boot_services.image_handle();
let loaded_image = boot_services let loaded_image = boot_services
.open_protocol_exclusive::<LoadedImage>(img_handle) .open_protocol_exclusive::<LoadedImage>(img_handle)
.expect("loaded image"); .unwrap();
let device_handle = loaded_image.device().expect("device handle"); let device_handle = loaded_image.device().unwrap();
let block_io = unsafe { let block_io = unsafe {
boot_services.open_protocol::<BlockIO>( boot_services.open_protocol::<BlockIO>(
@ -50,56 +44,39 @@ fn main(_image_handle: Handle, mut boot_system_table: SystemTable<Boot>) -> Stat
OpenProtocolAttributes::GetProtocol, OpenProtocolAttributes::GetProtocol,
) )
} }
.expect("block io"); .unwrap();
let mut gif_buf = [0u8; GIF_SIZE]; let mut gif_buf = [0u8; GIF_SIZE];
block_io block_io
.read_blocks(block_io.media().media_id(), Lba::from(0u64), &mut gif_buf) .read_blocks(block_io.media().media_id(), Lba::from(0u64), &mut gif_buf)
.expect("read blocks"); .unwrap();
let gif = tinygif::Gif::<Rgb888>::from_slice(&gif_buf).expect("gif from slice"); let gif = tinygif::Gif::<Rgb888>::from_slice(&gif_buf).unwrap();
// Get gop // Get gop
let gop_handle = boot_services let gop_handle = boot_services
.get_handle_for_protocol::<GraphicsOutput>() .get_handle_for_protocol::<GraphicsOutput>()
.expect("graphics output handle"); .unwrap();
let mut gop = boot_services let mut gop = boot_services
.open_protocol_exclusive::<GraphicsOutput>(gop_handle) .open_protocol_exclusive::<GraphicsOutput>(gop_handle)
.expect("graphics output open"); .unwrap();
use alloc::vec::Vec;
// Create UefiDisplay // Create UefiDisplay
for mode in gop.modes(&boot_services).collect::<Vec<_>>() {
let (w, h) = mode.info().resolution();
if w >= gif.width() as usize && h >= gif.height() as usize {
match mode.info().pixel_format() {
uefi::proto::console::gop::PixelFormat::Rgb
| uefi::proto::console::gop::PixelFormat::Bgr => {
if gop.set_mode(&mode).is_ok() {
break;
}
}
uefi::proto::console::gop::PixelFormat::Bitmask
| uefi::proto::console::gop::PixelFormat::BltOnly => {}
}
}
}
let mode = gop.current_mode_info(); let mode = gop.current_mode_info();
let (res_w, res_h) = mode.resolution(); let (res_w, res_h) = mode.resolution();
let mut display = UefiDisplay::new(gop.frame_buffer(), mode); let mut display = UefiDisplay::new(gop.frame_buffer(), mode);
// Tint the entire screen cyan // Tint the entire screen cyan
display.fill_entire(Rgb888::BLACK).expect("fill black"); display.fill_entire(Rgb888::BLACK).unwrap();
let timer_handle = boot_services let timer_handle = boot_services
.get_handle_for_protocol::<Timestamp>() .get_handle_for_protocol::<Timestamp>()
.expect("timestamp handle"); .unwrap();
let timer = boot_services let timer = boot_services
.open_protocol_exclusive::<Timestamp>(timer_handle) .open_protocol_exclusive::<Timestamp>(timer_handle)
.expect("timestamp open"); .unwrap();
let timer_hz = timer.get_properties().expect("timer props").frequency as f64; let timer_hz = timer.get_properties().unwrap().frequency as f64;
let start_timestamp = timer.get_timestamp(); let start_timestamp = timer.get_timestamp();
let mut gif_elapsed = Duration::new(0, 0); let mut gif_elapsed = Duration::new(0, 0);
@ -113,9 +90,7 @@ fn main(_image_handle: Handle, mut boot_system_table: SystemTable<Boot>) -> Stat
(res_h as i32 / gif.height() as i32) / 2, (res_h as i32 / gif.height() as i32) / 2,
); );
for frame in gif.frames() { for frame in gif.frames() {
frame frame.draw(&mut display.translated(translation)).unwrap();
.draw(&mut display.translated(translation))
.expect("frame draw");
gif_elapsed += Duration::from_millis(frame.delay_centis as u64 * 10); gif_elapsed += Duration::from_millis(frame.delay_centis as u64 * 10);
// skip flush to catch up // skip flush to catch up

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -7,4 +7,3 @@ edition = "2021"
[dependencies] [dependencies]
fatfs.workspace = true fatfs.workspace = true
mbrs.workspace = true

View file

@ -9,43 +9,16 @@ use fatfs::{
FileSystem, FormatVolumeOptions, FsOptions, IoBase, IoError, Read as FatRead, Seek as FatSeek, FileSystem, FormatVolumeOptions, FsOptions, IoBase, IoError, Read as FatRead, Seek as FatSeek,
Write as FatWrite, Write as FatWrite,
}; };
use mbrs::{Mbr, PartInfo, PartType};
#[derive(Copy, Clone)]
enum Cpu {
X86_64,
AArch64,
}
impl std::fmt::Display for Cpu {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Cpu::X86_64 => "x86_64",
Cpu::AArch64 => "aarch64",
})
}
}
fn main() { fn main() {
let mut args: VecDeque<_> = std::env::args().skip(1).collect(); let mut args: VecDeque<_> = std::env::args().skip(1).collect();
match args.pop_front() { match args.pop_front() {
Some(cmd) => { Some(cmd) => match cmd.as_str() {
let cpu = match args "build" => do_build(args),
.pop_front() "run" => do_run(args),
.unwrap_or(std::env::consts::ARCH.to_string())
.as_str()
{
"aarch64" | "arm64" => Cpu::AArch64,
"x86_64" | "x64" => Cpu::X86_64,
x => unimplemented!("target cpu {:?}", x),
};
match cmd.as_str() {
"build" => do_build(cpu, args),
"run" => do_run(cpu, args),
x => eprintln!("unknown command {:?}", x), x => eprintln!("unknown command {:?}", x),
} },
}
None => eprintln!("usage: cargo xtask [build|run] [x86_64|aarch64]"), None => eprintln!("usage: cargo xtask [build|run] [x86_64|aarch64]"),
} }
} }
@ -100,15 +73,14 @@ impl<T: Read + Write + Seek> FatWrite for MyStdIoWrapper<T> {
} }
} }
fn do_build(cpu: Cpu, _args: VecDeque<String>) { fn do_build(args: VecDeque<String>) {
let build = "debug"; let build_success = Command::new("cargo")
let build_success = Command::new(env!("CARGO"))
.arg("build") .arg("build")
.arg("--bin") .arg("--bin")
.arg("efigife") .arg("efigife")
//.arg("--release") .arg("--release")
.arg("--target") .arg("--target")
.arg(format!("{}-unknown-uefi", cpu)) .arg("aarch64-unknown-uefi") // TODO: target according to arg
.stdin(Stdio::inherit()) .stdin(Stdio::inherit())
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
@ -118,12 +90,11 @@ fn do_build(cpu: Cpu, _args: VecDeque<String>) {
.success(); .success();
assert!(build_success); assert!(build_success);
let efi_bin_path = format!( let efi_bin_path = concat!(
"{}/../target/{}-unknown-uefi/{}/efigife.efi",
env!("CARGO_MANIFEST_DIR"), env!("CARGO_MANIFEST_DIR"),
cpu, "/../target/aarch64-unknown-uefi/release/efigife.efi"
build
); );
eprintln!("{}", efi_bin_path);
let mut efi_bin_buf = Vec::new(); let mut efi_bin_buf = Vec::new();
let mut efi_bin_file = File::open(efi_bin_path).unwrap(); let mut efi_bin_file = File::open(efi_bin_path).unwrap();
let efi_bin_size = efi_bin_file.read_to_end(&mut efi_bin_buf); let efi_bin_size = efi_bin_file.read_to_end(&mut efi_bin_buf);
@ -139,11 +110,7 @@ fn do_build(cpu: Cpu, _args: VecDeque<String>) {
) )
.unwrap(); .unwrap();
let fat_fs = FileSystem::new(fat_disk, FsOptions::new()).unwrap(); let fat_fs = FileSystem::new(fat_disk, FsOptions::new()).unwrap();
let boot_efi_name = match cpu { let boot_efi_name = "BOOTAA64.EFI"; // TODO: parameterize on arg
Cpu::AArch64 => "BOOTAA64.EFI",
Cpu::X86_64 => "BOOTX64.EFI",
};
let mut boot_efi = fat_fs let mut boot_efi = fat_fs
.root_dir() .root_dir()
.create_dir("EFI") .create_dir("EFI")
@ -163,82 +130,49 @@ fn do_build(cpu: Cpu, _args: VecDeque<String>) {
let mut buf = Vec::new(); let mut buf = Vec::new();
let src_gif_size = src_gif_file.read_to_end(&mut buf).unwrap(); let src_gif_size = src_gif_file.read_to_end(&mut buf).unwrap();
drop(src_gif_file); drop(src_gif_file);
let fat_start_sector = (src_gif_size + 511) / 512; let fat_start_sector = (src_gif_size + 511) / 512;
let fat_sector_count = (fat_disk_buf.len() + 511) / 512;
buf.extend(std::iter::repeat(0).take(fat_start_sector * 512 - buf.len())); buf.extend(std::iter::repeat(0).take(fat_start_sector * 512 - buf.len()));
buf.extend(fat_disk_buf); buf.extend(fat_disk_buf);
let mut mbr = Mbr::default();
mbr.partition_table.entries[0] = Some(
PartInfo::try_from_lba(
true,
fat_start_sector as u32,
fat_sector_count as u32,
PartType::Efi,
)
.unwrap(),
);
let fake_mbr_buf = <[u8; 512]>::try_from(&mbr).unwrap();
buf[0x1be..0x200].copy_from_slice(&fake_mbr_buf[0x1be..0x200]);
let out_img_path = format!( let out_img_path = format!(
"{}/../target/bad-apple.{}-efi.raw.gif", "{}/../target/bad-apple.{}-efi.raw.gif",
env!("CARGO_MANIFEST_DIR"), env!("CARGO_MANIFEST_DIR"),
cpu "aarch64"
); );
let mut out_img_file = File::create(out_img_path).unwrap(); let mut out_img_file = File::create(out_img_path).unwrap();
out_img_file.write_all(&buf).unwrap(); out_img_file.write_all(&buf).unwrap();
} }
fn do_run(cpu: Cpu, args: VecDeque<String>) { fn do_run(args: VecDeque<String>) {
do_build(cpu, args.clone()); do_build(args.clone());
let mut cmd = Command::new(format!("qemu-system-{}", cpu)); let mut cmd = match args[0].as_str() {
let kvm = cpu.to_string() == std::env::consts::ARCH; "aarch64" | "arm64" => {
match cpu { let mut cmd = Command::new("qemu-system-aarch64");
Cpu::AArch64 => { cmd.arg("-drive")
if kvm { .arg("if=none,id=code,format=raw,file=/usr/share/qemu/edk2-aarch64-code.fd,readonly=on")
cmd.arg("-M") .arg("-M")
.arg("virt,pflash0=code,accel=kvm,gic-version=3") .arg("virt,pflash0=code,accel=kvm,gic-version=3")
.arg("-cpu") .arg("-cpu")
.arg("host"); .arg("host")
} else { .arg("-m")
cmd.arg("-M").arg("virt,pflash0=code,gic-version=3");
}
cmd.arg("-drive").arg(
"if=none,id=code,format=raw,file=/usr/share/qemu/edk2-aarch64-code.fd,readonly=on",
);
}
Cpu::X86_64 => {
if kvm {
cmd.arg("-M")
.arg("q35,smm=on,accel=kvm")
.arg("-cpu")
.arg("host");
} else {
cmd.arg("-M").arg("q35,smm=on");
}
cmd.arg("-global")
.arg("ICH9-LPC.disable_s3=1")
.arg("-drive")
.arg(
"if=pflash,format=raw,unit=0,file=/usr/share/edk2-ovmf/OVMF_CODE.fd,readonly=on",
);
}
}
cmd.arg("-m")
.arg("512") .arg("512")
.arg("-device") .arg("-device")
.arg("virtio-gpu-pci") .arg("virtio-gpu-pci");
.args(&args); cmd
}
"x86_64" | "x64" => {
//let mut cmd = Command::new("qemu-system-x86_64");
todo!();
}
x => unimplemented!("target cpu {:?}", x),
};
let out_img_path = format!( let out_img_path = format!(
"{}/../target/bad-apple.{}-efi.raw.gif", "{}/../target/bad-apple.{}-efi.raw.gif",
env!("CARGO_MANIFEST_DIR"), env!("CARGO_MANIFEST_DIR"),
cpu "aarch64"
); );
cmd.arg("-drive") cmd.arg(out_img_path)
.arg(format!("format=raw,file={}", out_img_path))
.stdin(Stdio::inherit()) .stdin(Stdio::inherit())
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())