Initial commit
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
.zig-cache
|
||||||
|
zig-cache
|
||||||
|
zig-out
|
||||||
|
|
||||||
|
*.efi
|
||||||
|
*.pdb
|
||||||
|
*.img
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
IMG_FILE := bootable.img
|
||||||
|
IMG_SIZE_MB := 100
|
||||||
|
EFI_FILE := bootx64.efi
|
||||||
|
MNT_DIR := esp_mnt
|
||||||
|
USB_DEV ?= /dev/sdX
|
||||||
|
|
||||||
|
.PHONY: all clean flash
|
||||||
|
|
||||||
|
# The default target, which is to build the image file.
|
||||||
|
all: $(EFI_FILE)
|
||||||
|
@echo "--- Creating blank disk image: $(IMG_FILE) ($(IMG_SIZE_MB)MB)..."
|
||||||
|
dd if=/dev/zero of=$(IMG_FILE) bs=1M count=$(IMG_SIZE_MB) status=none
|
||||||
|
|
||||||
|
sudo -v
|
||||||
|
|
||||||
|
@echo "--- Creating GPT and EFI System Partition..."
|
||||||
|
# Use sgdisk for non-interactive partitioning.
|
||||||
|
# --new=1:0:0 creates partition 1, starting at the first available sector and filling the disk.
|
||||||
|
# --typecode=1:ef00 sets the partition type to 'EFI System'.
|
||||||
|
sudo sgdisk --new=1:0:0 --typecode=1:ef00 $(IMG_FILE)
|
||||||
|
|
||||||
|
@# This block handles setting up, using, and cleaning up a loop device and mount point.
|
||||||
|
@# 'set -e' ensures the script will exit immediately if a command fails.
|
||||||
|
@# The trap command guarantees that we unmount the partition and detach the loop device on exit,
|
||||||
|
@# even if an error occurs.
|
||||||
|
set -e; \
|
||||||
|
LOOP_DEV=$$(sudo losetup --partscan --show --find $(IMG_FILE)); \
|
||||||
|
trap 'echo "--- Cleaning up mount point and loop device..."; sudo umount $(MNT_DIR) 2>/dev/null || true; sudo losetup -d $$LOOP_DEV 2>/dev/null || true; rm -rf $(MNT_DIR);' EXIT; \
|
||||||
|
\
|
||||||
|
echo "--- Using loop device: $$LOOP_DEV"; \
|
||||||
|
echo "--- Formatting EFI partition (FAT32)..."; \
|
||||||
|
sudo mkfs.vfat -F32 $${LOOP_DEV}p1; \
|
||||||
|
\
|
||||||
|
echo "--- Mounting partition..."; \
|
||||||
|
mkdir -p $(MNT_DIR); \
|
||||||
|
sudo mount $${LOOP_DEV}p1 $(MNT_DIR); \
|
||||||
|
\
|
||||||
|
echo "--- Copying EFI executable to EFI/BOOT/BOOTX64.EFI..."; \
|
||||||
|
sudo mkdir -p $(MNT_DIR)/EFI/BOOT; \
|
||||||
|
sudo cp $(EFI_FILE) $(MNT_DIR)/EFI/BOOT/BOOTX64.EFI; \
|
||||||
|
\
|
||||||
|
echo "--- Syncing filesystem..."; \
|
||||||
|
sync;
|
||||||
|
|
||||||
|
@echo "\nSuccess! Bootable image created: $(IMG_FILE)"
|
||||||
|
|
||||||
|
$(EFI_FILE):
|
||||||
|
zig build-exe -OReleaseFast -target x86_64-uefi-msvc --name bootx64 main.zig
|
||||||
|
|
||||||
|
# Rule to flash the image to a USB device.
|
||||||
|
flash: $(IMG_FILE)
|
||||||
|
@if [ "$(USB_DEV)" = "/dev/sdX" ]; then \
|
||||||
|
echo "\nERROR: USB_DEV is not set."; \
|
||||||
|
echo "Please specify the target device, e.g., 'make flash USB_DEV=/dev/sdb'"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
@echo "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||||
|
@echo "!! WARNING: This will ERASE ALL DATA on $(USB_DEV) !!"
|
||||||
|
@echo "!! Verify that this is the correct device before proceeding. !!"
|
||||||
|
@echo "!! Press Ctrl+C to cancel, or Enter to continue. !!"
|
||||||
|
@echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||||
|
@read
|
||||||
|
sudo dd if=$(IMG_FILE) of=$(USB_DEV) bs=4M status=progress conv=fsync
|
||||||
|
|
||||||
|
# Rule to clean up all generated files and temporary directories.
|
||||||
|
clean:
|
||||||
|
@echo "--- Cleaning up..."
|
||||||
|
@-sudo umount $(MNT_DIR) >/dev/null 2>&1 || true
|
||||||
|
@-rm -rf $(MNT_DIR)
|
||||||
|
@-if losetup -j $(IMG_FILE) > /dev/null 2>&1; then \
|
||||||
|
LOOP_DEV=$$(losetup -j $(IMG_FILE) | cut -d: -f1); \
|
||||||
|
echo "Detaching loop device $$LOOP_DEV..."; \
|
||||||
|
sudo losetup -d $$LOOP_DEV; \
|
||||||
|
fi
|
||||||
|
@-rm -f $(IMG_FILE)
|
||||||
|
@echo "Cleanup complete."
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# This script creates a bootable EFI image file
|
||||||
|
# It replicates the logic from the 'all' target of the Makefile
|
||||||
|
|
||||||
|
IMG_FILE="bootable.img"
|
||||||
|
IMG_SIZE_MB=100
|
||||||
|
EFI_FILE="bootx64.efi"
|
||||||
|
MNT_DIR="esp_mnt"
|
||||||
|
|
||||||
|
# Make sure we have sudo privileges
|
||||||
|
sudo -v
|
||||||
|
|
||||||
|
echo ">>> Checking for source file: ${EFI_FILE}..."
|
||||||
|
if [ ! -f "${EFI_FILE}" ]; then
|
||||||
|
echo "Error: Source file '${EFI_FILE}' not found."
|
||||||
|
echo "Please place your EFI executable in this directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ">>> Creating blank disk image: ${IMG_FILE} (${IMG_SIZE_MB}MB)..."
|
||||||
|
dd if=/dev/zero of="${IMG_FILE}" bs=1M count=${IMG_SIZE_MB} status=none
|
||||||
|
|
||||||
|
echo ">>> Creating GPT and EFI System Partition..."
|
||||||
|
sudo sgdisk --new=1:0:0 --typecode=1:ef00 "${IMG_FILE}"
|
||||||
|
|
||||||
|
# Set up a trap to ensure cleanup happens even if the script fails
|
||||||
|
cleanup() {
|
||||||
|
echo ">>> Cleaning up..."
|
||||||
|
# The '|| true' prevents the script from exiting if umount fails (e.g., not mounted)
|
||||||
|
sudo umount "${MNT_DIR}" 2>/dev/null || true
|
||||||
|
if [ -n "${LOOP_DEV}" ]; then
|
||||||
|
sudo losetup -d "${LOOP_DEV}" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
rm -rf "${MNT_DIR}"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
echo ">>> Setting up loop device..."
|
||||||
|
LOOP_DEV=$(sudo losetup --partscan --show --find "${IMG_FILE}")
|
||||||
|
echo ">>> Using loop device: ${LOOP_DEV}"
|
||||||
|
|
||||||
|
echo ">>> Formatting EFI partition (FAT32)..."
|
||||||
|
sudo mkfs.vfat -F32 "${LOOP_DEV}p1"
|
||||||
|
|
||||||
|
echo ">>> Mounting partition..."
|
||||||
|
mkdir -p "${MNT_DIR}"
|
||||||
|
sudo mount "${LOOP_DEV}p1" "${MNT_DIR}"
|
||||||
|
|
||||||
|
echo ">>> Copying EFI executable to EFI/BOOT/BOOTX64.EFI..."
|
||||||
|
sudo mkdir -p "${MNT_DIR}/EFI/BOOT"
|
||||||
|
sudo cp "${EFI_FILE}" "${MNT_DIR}/EFI/BOOT/BOOTX64.EFI"
|
||||||
|
|
||||||
|
echo ">>> Syncing filesystem..."
|
||||||
|
sync
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
const uefi_target = b.resolveTargetQuery(.{
|
||||||
|
.cpu_arch = .x86_64,
|
||||||
|
.os_tag = .uefi,
|
||||||
|
.abi = .msvc,
|
||||||
|
});
|
||||||
|
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
|
.name = "bootx64.efi",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.root_source_file = b.path("main.zig"),
|
||||||
|
.optimize = .ReleaseFast,
|
||||||
|
.target = uefi_target,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
b.default_step.dependOn(&exe.step);
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env just --justfile
|
||||||
|
|
||||||
|
IMG_FILE := 'small.img'
|
||||||
|
IMG_SIZE_MB := '36'
|
||||||
|
EFI_NAME := 'bootx64'
|
||||||
|
EFI_FILE := 'bootx64.efi'
|
||||||
|
MNT_DIR := 'esp_mnt'
|
||||||
|
|
||||||
|
default: image
|
||||||
|
|
||||||
|
build:
|
||||||
|
@echo ">>> Building UEFI executable ({{EFI_FILE}})..."
|
||||||
|
zig build-exe -OReleaseFast -target x86_64-uefi-msvc --name {{EFI_NAME}} main.zig
|
||||||
|
|
||||||
|
_image-init:
|
||||||
|
echo ">>> Creating blank disk image: {{IMG_FILE}} ({{IMG_SIZE_MB}}MB)..."
|
||||||
|
#dd if=/dev/zero of={{IMG_FILE}} bs=1M count={{IMG_SIZE_MB}}
|
||||||
|
fallocate -l {{IMG_SIZE_MB}}M {{IMG_FILE}}
|
||||||
|
|
||||||
|
sudo -v
|
||||||
|
|
||||||
|
echo ">>> Creating GPT and EFI System Partition..."
|
||||||
|
sudo sgdisk --new=1:0:0 --typecode=1:ef00 {{IMG_FILE}}
|
||||||
|
|
||||||
|
image: build _image-init
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
LOOP_DEV=$(sudo losetup --partscan --show --find {{IMG_FILE}})
|
||||||
|
trap 'sudo umount {{MNT_DIR}} 2>/dev/null || true; sudo losetup -d "$LOOP_DEV" 2>/dev/null || true; rm -rf {{MNT_DIR}};' EXIT
|
||||||
|
|
||||||
|
echo ">>> Using loop device: $LOOP_DEV"
|
||||||
|
echo ">>> Formatting EFI partition (FAT32)..."
|
||||||
|
sudo mkfs.vfat -F32 "${LOOP_DEV}p1"
|
||||||
|
|
||||||
|
echo ">>> Mounting partition..."
|
||||||
|
mkdir -p {{MNT_DIR}}
|
||||||
|
sudo mount "${LOOP_DEV}p1" {{MNT_DIR}}
|
||||||
|
|
||||||
|
echo ">>> Copying EFI executable to EFI/BOOT/BOOTX64.EFI..."
|
||||||
|
sudo mkdir -p {{MNT_DIR}}/EFI/BOOT
|
||||||
|
sudo cp {{EFI_FILE}} {{MNT_DIR}}/EFI/BOOT/BOOTX64.EFI
|
||||||
|
|
||||||
|
echo ">>> Syncing filesystem..."
|
||||||
|
sync
|
||||||
|
|
||||||
|
echo "Success! Bootable image created: {{IMG_FILE}}"
|
||||||
|
|
||||||
|
run: image
|
||||||
|
qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -drive format=raw,file={{IMG_FILE}}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo ">>> Cleaning up..."
|
||||||
|
-rm -vrf zig-cache zig-out
|
||||||
|
-rm -vf *.img bootx64*
|
||||||
|
@echo ">>> Cleanup complete."
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const uefi = std.os.uefi;
|
||||||
|
|
||||||
|
const W = std.unicode.utf8ToUtf16LeStringLiteral;
|
||||||
|
|
||||||
|
pub fn main() void {
|
||||||
|
const con_out = uefi.system_table.con_out.?;
|
||||||
|
con_out.reset(false) catch unreachable;
|
||||||
|
_ = con_out.outputString(W("Hi :D\r\n")) catch unreachable;
|
||||||
|
|
||||||
|
const boot_services = uefi.system_table.boot_services.?;
|
||||||
|
boot_services.stall(5 * 1000 * 1000) catch unreachable;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user