first commit
This commit is contained in:
6
.cargo/config.toml
Executable file
6
.cargo/config.toml
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
[unstable]
|
||||||
|
build-std = ["core", "compiler_builtins", "alloc"]
|
||||||
|
build-std-features = ["compiler-builtins-mem"]
|
||||||
|
|
||||||
|
[build]
|
||||||
|
target = "x86_64-unknown-uefi"
|
||||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
BIN
BOOT/EFI/BOOT/BOOTX64.EFI
Executable file
BIN
BOOT/EFI/BOOT/BOOTX64.EFI
Executable file
Binary file not shown.
191
Cargo.lock
generated
Executable file
191
Cargo.lock
generated
Executable file
@@ -0,0 +1,191 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit_field"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "goblin"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"plain",
|
||||||
|
"scroll",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plain"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.51"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||||
|
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",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rlibc"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scroll"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da"
|
||||||
|
dependencies = [
|
||||||
|
"scroll_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scroll_derive"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bdbda6ac5cd1321e724fa9cee216f3a61885889b896f073b8f82322789c5250e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stubby"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"goblin",
|
||||||
|
"log",
|
||||||
|
"rlibc",
|
||||||
|
"uefi",
|
||||||
|
"uefi-macros",
|
||||||
|
"uefi-services",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "ucs2"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bad643914094137d475641b6bab89462505316ec2ce70907ad20102d28a79ab8"
|
||||||
|
dependencies = [
|
||||||
|
"bit_field",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uefi"
|
||||||
|
version = "0.19.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f5607fef843201070ed442fa257c7a944fae963fac7d4620612123192eb4d844"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"log",
|
||||||
|
"ptr_meta",
|
||||||
|
"ucs2",
|
||||||
|
"uefi-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uefi-macros"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8099684193f2d99f7f130951f4054a1591ff7da370e2b33d7a71f0434920499"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uefi-services"
|
||||||
|
version = "0.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f75daa44f951cc1d9dc68d98cabc06ddbccc221d7bd21222271be5d7ac526a9d"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"log",
|
||||||
|
"uefi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||||
16
Cargo.toml
Normal file
16
Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "stubby"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rlibc = "1.0.0"
|
||||||
|
|
||||||
|
uefi = { version = "0.19.1", features = ['logger', 'alloc', ] }
|
||||||
|
uefi-services = "0.16.0"
|
||||||
|
uefi-macros = "0.10.0"
|
||||||
|
log = { version = "0.4.17", default-features = false }
|
||||||
|
goblin = { version = "0.6.1", default-features = false, features = ['elf32', 'elf64', 'alloc', 'endian_fd'] }
|
||||||
|
arrayvec = { version = "0.7.2", default-features = false }
|
||||||
46
Makefile
Executable file
46
Makefile
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
ARCH ?= x86_64
|
||||||
|
TARGET ?= $(ARCH)-unknown-uefi
|
||||||
|
PROJECT ?= stubby
|
||||||
|
OVMF_FW := OVMF_CODE.fd
|
||||||
|
OVMF_VARS = OVMF_VARS.fd
|
||||||
|
BOOT_DIR := BOOT
|
||||||
|
|
||||||
|
qemu_args := -nodefaults -vga std -monitor vc:1440x900 -serial stdio -machine q35,accel=kvm:hvf -no-shutdown -no-reboot -m 256M
|
||||||
|
qemu_efi := -drive if=pflash,format=raw,readonly=on,file=$(OVMF_FW)
|
||||||
|
qemu_efi_vars := -drive if=pflash,format=raw,file=$(OVMF_VARS)
|
||||||
|
qemu_drive := -drive format=raw,file=fat:rw:$(BOOT_DIR)
|
||||||
|
|
||||||
|
target_debug := target/$(TARGET)/debug/$(PROJECT).efi
|
||||||
|
target_release := target/$(TARGET)/release/$(PROJECT).efi
|
||||||
|
|
||||||
|
.PHONY: all release debug clean run-debug run
|
||||||
|
|
||||||
|
all: $(target_debug) $(target_release)
|
||||||
|
debug: $(target_debug)
|
||||||
|
release: $(target_release)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rv $(BOOT_DIR)
|
||||||
|
@RUST_TARGET_PATH=$(shell pwd) cargo clean --target $(TARGET)
|
||||||
|
|
||||||
|
run-debug: $(target_debug)
|
||||||
|
@RUST_TARGET_PATH=$(shell pwd) cargo +nightly build -Z build-std --target $(TARGET) --verbose
|
||||||
|
mkdir -p $(BOOT_DIR)/EFI/BOOT/
|
||||||
|
cp -v $(target_debug) $(BOOT_DIR)/EFI/BOOT/BOOTX64.EFI
|
||||||
|
@qemu-system-$(ARCH) $(qemu_args) $(qemu_efi) $(qemu_efi_vars) $(qemu_drive)
|
||||||
|
|
||||||
|
run: $(target_release)
|
||||||
|
@RUST_TARGET_PATH=$(shell pwd) cargo +nightly build -Z build-std --target $(TARGET) --release
|
||||||
|
mkdir -p $(BOOT_DIR)/EFI/BOOT/
|
||||||
|
cp -v $(target_release) $(BOOT_DIR)/EFI/BOOT/BOOTX64.EFI
|
||||||
|
@qemu-system-$(ARCH) $(qemu_args) $(qemu_efi) $(qemu_efi_vars) $(qemu_drive)
|
||||||
|
|
||||||
|
$(target_debug):
|
||||||
|
@RUST_TARGET_PATH=$(shell pwd) cargo +nightly build -Z build-std --target $(TARGET) --verbose
|
||||||
|
mkdir -p $(BOOT_DIR)/EFI/BOOT/
|
||||||
|
cp -v $(target_debug) $(BOOT_DIR)/EFI/BOOT/BOOTX64.EFI
|
||||||
|
|
||||||
|
$(target_release):
|
||||||
|
@RUST_TARGET_PATH=$(shell pwd) cargo +nightly build -Z build-std --target $(TARGET) --release
|
||||||
|
mkdir -p $(BOOT_DIR)/EFI/BOOT/
|
||||||
|
cp -v $(target_release) $(BOOT_DIR)/EFI/BOOT/BOOTX64.EFI
|
||||||
BIN
OVMF_CODE.fd
Normal file
BIN
OVMF_CODE.fd
Normal file
Binary file not shown.
BIN
OVMF_VARS.fd
Normal file
BIN
OVMF_VARS.fd
Normal file
Binary file not shown.
173
src/main.rs
Normal file
173
src/main.rs
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
// Keep this line to ensure the `mem*` functions are linked in.
|
||||||
|
extern crate rlibc;
|
||||||
|
|
||||||
|
extern crate goblin;
|
||||||
|
|
||||||
|
extern crate uefi;
|
||||||
|
extern crate uefi_services;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate uefi_macros;
|
||||||
|
|
||||||
|
use core::ffi::c_void;
|
||||||
|
use core::ptr;
|
||||||
|
use uefi::Handle;
|
||||||
|
use uefi::{prelude::*, Identify};
|
||||||
|
use uefi::{
|
||||||
|
proto::console::gop::{BltOp, BltPixel, FrameBuffer, GraphicsOutput, PixelFormat},
|
||||||
|
table::boot::{
|
||||||
|
AllocateType, BootServices, MemoryType, OpenProtocolAttributes, OpenProtocolParams,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[uefi_macros::entry]
|
||||||
|
pub fn efi_main(_image: Handle, mut st: SystemTable<Boot>) -> Status {
|
||||||
|
// Initialize logging, memory allocation and uefi services
|
||||||
|
let mut bt = match uefi_services::init(&mut st) {
|
||||||
|
Ok(_) => {
|
||||||
|
|
||||||
|
st.stdout().clear();
|
||||||
|
st.stdout().set_color(
|
||||||
|
uefi::proto::console::text::Color::LightMagenta,
|
||||||
|
uefi::proto::console::text::Color::Black,
|
||||||
|
);
|
||||||
|
|
||||||
|
// output firmware-vendor (CStr16 to Rust string)
|
||||||
|
// max size of 32 characters
|
||||||
|
let mut buf = arrayvec::ArrayString::<32>::new();
|
||||||
|
st.firmware_vendor().as_str_in_buf(&mut buf).unwrap();
|
||||||
|
info!("Firmware Vendor: {}", buf.as_str());
|
||||||
|
|
||||||
|
let rev = st.uefi_revision();
|
||||||
|
let (major, minor) = (rev.major(), rev.minor());
|
||||||
|
let buf = format!("UEFI {}.{}", major, minor / 10);
|
||||||
|
info!("{}", buf);
|
||||||
|
|
||||||
|
assert!(major >= 2, "Running on an old, unsupported version of UEFI");
|
||||||
|
assert!(
|
||||||
|
minor >= 30,
|
||||||
|
"Old version of UEFI 2, some features might not be available."
|
||||||
|
);
|
||||||
|
|
||||||
|
st.boot_services()
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let handle = bt.get_handle_for_protocol::<GraphicsOutput>()
|
||||||
|
.expect("missing GraphicsOutput protocol");
|
||||||
|
|
||||||
|
|
||||||
|
let mut gop = unsafe {
|
||||||
|
let mut gop_proto = st.boot_services().open_protocol::<GraphicsOutput>(
|
||||||
|
OpenProtocolParams {
|
||||||
|
handle,
|
||||||
|
agent: st.boot_services().image_handle(),
|
||||||
|
controller: None,
|
||||||
|
},
|
||||||
|
// For this test, don't open in exclusive mode. That
|
||||||
|
// would break the connection between stdout and the
|
||||||
|
// video console.
|
||||||
|
OpenProtocolAttributes::GetProtocol,
|
||||||
|
)
|
||||||
|
.expect("failed to open Graphics Output Protocol");
|
||||||
|
|
||||||
|
gop_proto
|
||||||
|
};
|
||||||
|
|
||||||
|
set_graphics_mode(&mut gop);
|
||||||
|
fill_color(&mut gop);
|
||||||
|
draw_fb(&mut gop);
|
||||||
|
info!("GOP Framebuffer test complete");
|
||||||
|
|
||||||
|
// Return success status
|
||||||
|
Status::SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a larger graphics mode.
|
||||||
|
fn set_graphics_mode(gop: &mut GraphicsOutput) {
|
||||||
|
// We know for sure QEMU has a 1024x768 mode.
|
||||||
|
let mode = gop
|
||||||
|
.modes()
|
||||||
|
.find(|mode| {
|
||||||
|
let info = mode.info();
|
||||||
|
info.resolution() == (1024, 768)
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
gop.set_mode(&mode).expect("Failed to set graphics mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the screen with color.
|
||||||
|
fn fill_color(gop: &mut GraphicsOutput) {
|
||||||
|
let op = BltOp::VideoFill {
|
||||||
|
// Cornflower blue.
|
||||||
|
color: BltPixel::new(100, 149, 237),
|
||||||
|
dest: (0, 0),
|
||||||
|
dims: (1024, 768),
|
||||||
|
};
|
||||||
|
|
||||||
|
gop.blt(op).expect("Failed to fill screen with color");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw directly to the frame buffer.
|
||||||
|
fn draw_fb(gop: &mut GraphicsOutput) {
|
||||||
|
// The `virtio-gpu-pci` graphics device we use on aarch64 doesn't
|
||||||
|
// support `PixelFormat::BltOnly`.
|
||||||
|
if cfg!(target_arch = "aarch64") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mi = gop.current_mode_info();
|
||||||
|
let stride = mi.stride();
|
||||||
|
let (width, height) = mi.resolution();
|
||||||
|
|
||||||
|
let mut fb = gop.frame_buffer();
|
||||||
|
|
||||||
|
type PixelWriter = unsafe fn(&mut FrameBuffer, usize, [u8; 3]);
|
||||||
|
unsafe fn write_pixel_rgb(fb: &mut FrameBuffer, pixel_base: usize, rgb: [u8; 3]) {
|
||||||
|
fb.write_value(pixel_base, rgb);
|
||||||
|
}
|
||||||
|
unsafe fn write_pixel_bgr(fb: &mut FrameBuffer, pixel_base: usize, rgb: [u8; 3]) {
|
||||||
|
fb.write_value(pixel_base, [rgb[2], rgb[1], rgb[0]]);
|
||||||
|
}
|
||||||
|
let write_pixel: PixelWriter = match mi.pixel_format() {
|
||||||
|
PixelFormat::Rgb => write_pixel_rgb,
|
||||||
|
PixelFormat::Bgr => write_pixel_bgr,
|
||||||
|
_ => {
|
||||||
|
info!("This pixel format is not supported by the drawing demo");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut fill_rectangle = |(x1, y1), (x2, y2), color| {
|
||||||
|
assert!((x1 < width) && (x2 < width), "Bad X coordinate");
|
||||||
|
assert!((y1 < height) && (y2 < height), "Bad Y coordinate");
|
||||||
|
for row in y1..y2 {
|
||||||
|
for column in x1..x2 {
|
||||||
|
unsafe {
|
||||||
|
let pixel_index = (row * stride) + column;
|
||||||
|
let pixel_base = 4 * pixel_index;
|
||||||
|
write_pixel(&mut fb, pixel_base, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fill_rectangle((50, 30), (150, 600), [250, 128, 64]);
|
||||||
|
fill_rectangle((400, 120), (750, 450), [16, 128, 255]);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user