commit ce3cd36e7551a8c4e64f6fc5998cba297c5782e4 Author: lifning <> Date: Sat May 4 20:37:03 2024 -0700 initial import diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..6207835 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[build] +target = "aarch64-unknown-uefi" + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6d1fc4d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,324 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + +[[package]] +name = "efigife" +version = "0.1.0" +dependencies = [ + "embedded-graphics", + "tinygif", + "uefi", + "uefi-graphics2", +] + +[[package]] +name = "embedded-graphics" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0649998afacf6d575d126d83e68b78c0ab0e00ca2ac7e9b3db11b4cbe8274ef0" +dependencies = [ + "az", + "byteorder", + "embedded-graphics-core", + "float-cmp", + "micromath", +] + +[[package]] +name = "embedded-graphics-core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba9ecd261f991856250d2207f6d8376946cd9f412a2165d3b75bc87a0bc7a044" +dependencies = [ + "az", + "byteorder", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "micromath" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "ptr_meta" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcada80daa06c42ed5f48c9a043865edea5dc44cbf9ac009fda3b89526e28607" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca9224df2e20e7c5548aeb5f110a0f3b77ef05f8585139b7148b59056168ed2" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tinygif" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f1406b710986188de8d393c810213d4bbf940e327d90d52cff9930d007a248" +dependencies = [ + "embedded-graphics", + "heapless", +] + +[[package]] +name = "ucs2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79298e11f316400c57ec268f3c2c29ac3c4d4777687955cd3d4f3a35ce7eba" +dependencies = [ + "bit_field", +] + +[[package]] +name = "uefi" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c0a56dc9fed2589aad6ddca11c2584968fc21f227b5d7083bb8961d26a69fa" +dependencies = [ + "bitflags", + "cfg-if", + "log", + "ptr_meta", + "ucs2", + "uefi-macros", + "uefi-raw", + "uguid", +] + +[[package]] +name = "uefi-graphics2" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7ecab5c247c3b9224708a31551021d4ae847f32454064e2d75029840cadcf77" +dependencies = [ + "embedded-graphics", + "uefi", +] + +[[package]] +name = "uefi-macros" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26a7b1c2c808c3db854a54d5215e3f7e7aaf5dcfbce095598cba6af29895695d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "uefi-raw" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa8716f52e8cab8bcedfd5052388a0f263b69fe5cc2561548dc6a530678333c" +dependencies = [ + "bitflags", + "ptr_meta", + "uguid", +] + +[[package]] +name = "uguid" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab14ea9660d240e7865ce9d54ecdbd1cd9fa5802ae6f4512f093c7907e921533" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..2a47c06 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "efigife" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +embedded-graphics = "0.8.1" +tinygif = { version = "0.0.4", features = ["8k"] } +uefi = { version = "0.28.0", features = ["global_allocator", "panic_handler", "alloc"] } +uefi-graphics2 = "0.1.3" diff --git a/src/bad-apple.gif b/src/bad-apple.gif new file mode 100644 index 0000000..955acc0 Binary files /dev/null and b/src/bad-apple.gif differ diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..3a5dcd4 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,114 @@ +#![no_main] +#![no_std] + +use core::time::Duration; + +use uefi::prelude::*; +use uefi::proto::console::gop::GraphicsOutput; +use uefi::proto::loaded_image::LoadedImage; +use uefi::proto::media::block::{BlockIO, Lba}; +use uefi::proto::misc::Timestamp; +use uefi::table::boot::{OpenProtocolAttributes, OpenProtocolParams}; + +use uefi_graphics2::embedded_graphics::{pixelcolor::Rgb888, prelude::*}; +use uefi_graphics2::UefiDisplay; + +const GIF_SIZE: usize = include_bytes!("bad-apple.gif").len(); + +#[entry] +fn main(_image_handle: Handle, mut boot_system_table: SystemTable) -> Status { + uefi::helpers::init(&mut boot_system_table).unwrap(); + + // Disable the watchdog timer + boot_system_table + .boot_services() + .set_watchdog_timer(0, 0x10000, None) + .unwrap(); + + let boot_services = boot_system_table.boot_services(); + + let img_handle = boot_services.image_handle(); + let loaded_image = boot_services + .open_protocol_exclusive::(img_handle) + .unwrap(); + + let device_handle = loaded_image.device().unwrap(); + + let block_io = unsafe { + boot_services.open_protocol::( + OpenProtocolParams { + handle: device_handle, + agent: img_handle, + controller: None, + }, + OpenProtocolAttributes::GetProtocol, + ) + } + .unwrap(); + + let mut gif_buf = [0u8; GIF_SIZE]; + block_io + .read_blocks(block_io.media().media_id(), Lba::from(0u64), &mut gif_buf) + .unwrap(); + + let gif = tinygif::Gif::::from_slice(&gif_buf).unwrap(); + + // Get gop + let gop_handle = boot_services + .get_handle_for_protocol::() + .unwrap(); + let mut gop = boot_services + .open_protocol_exclusive::(gop_handle) + .unwrap(); + + // Create UefiDisplay + let mode = gop.current_mode_info(); + let (res_w, res_h) = mode.resolution(); + let mut display = UefiDisplay::new(gop.frame_buffer(), mode); + + // Tint the entire screen cyan + display.fill_entire(Rgb888::BLACK).unwrap(); + + let timer_handle = boot_services + .get_handle_for_protocol::() + .unwrap(); + let timer = boot_services + .open_protocol_exclusive::(timer_handle) + .unwrap(); + + let timer_hz = timer.get_properties().unwrap().frequency as f64; + + let start_timestamp = timer.get_timestamp(); + let mut gif_elapsed = Duration::new(0, 0); + + let get_real_elapsed = + || Duration::from_secs_f64((timer.get_timestamp() - start_timestamp) as f64 / timer_hz); + + let mut skipped_flushes = 0; + let translation = Point::new( + (res_w as i32 - gif.width() as i32) / 2, + (res_h as i32 / gif.height() as i32) / 2, + ); + for frame in gif.frames() { + frame.draw(&mut display.translated(translation)).unwrap(); + gif_elapsed += Duration::from_millis(frame.delay_centis as u64 * 10); + + // skip flush to catch up + if gif_elapsed > get_real_elapsed() { + display.flush(); + if let Some(time_diff) = get_real_elapsed().checked_sub(gif_elapsed) { + boot_services.stall(time_diff.as_micros() as usize); + } + } else { + skipped_flushes += 1; + if skipped_flushes == 5 { + // don't skip more than 5 frames at a time + // so you can actually still see anything + skipped_flushes = 0; + display.flush(); + } + } + } + + Status::SUCCESS +}