Просмотр исходного кода

Started Transition to On device Testing (ISO is in Alpha Stage). Added New Qemu testing commands. Added new make commands. Fixed Boot transition and arkrt.

Aarav90-cpu 1 месяц назад
Родитель
Сommit
7101c348a1
6 измененных файлов с 527 добавлено и 95 удалено
  1. 113 2
      arkos/Makefile
  2. 52 5
      arkos/boot/source/bootloader.asm
  3. 286 32
      arkos/boot/source/bootloader.c
  4. 12 1
      arkos/boot/source/stage2.asm
  5. 11 48
      tools/build.c
  6. 53 7
      tools/pack_boot.py

+ 113 - 2
arkos/Makefile

@@ -4,14 +4,14 @@ TOOLS := $(ROOT)/tools
 ARKOS := $(ROOT)/arkos
 CLANG := $(ARKOS)/prebuilts/clang/bin/clang
 
-.PHONY: build run clean
+.PHONY: build run clean run-uefi iso run-iso run-iso-uefi
 
 build:
 	@$(MAKE) --no-print-directory -C $(TOOLS)
 	@$(TOOLS)/build $(ARKOS)
 
 run:
-	@echo "Starting ArkOS Testing Window in QEMU..."
+	@echo "Starting ArkOS Testing Window in QEMU (BIOS)..."
 	@qemu-system-x86_64 \
 		-m 2048 \
 		-smp 2 \
@@ -28,5 +28,116 @@ run:
 		-drive file=finished/vend.img,format=raw,index=2,media=disk \
 		-vga virtio
 
+run-uefi:
+	@echo "Starting ArkOS Testing Window in QEMU (UEFI)..."
+	@qemu-system-x86_64 \
+		-bios /usr/share/edk2/x64/OVMF.4m.fd \
+		-m 2048 \
+		-smp 2 \
+		-drive file=finished/boot.img,format=raw,index=0,media=disk \
+		-drive file=finished/sys.img,format=raw,index=1,media=disk \
+		-drive file=finished/vend.img,format=raw,index=2,media=disk \
+		-vga virtio \
+		-enable-kvm 2>/dev/null || \
+	qemu-system-x86_64 \
+		-bios /usr/share/edk2/x64/OVMF.4m.fd \
+		-m 2048 \
+		-smp 2 \
+		-drive file=finished/boot.img,format=raw,index=0,media=disk \
+		-drive file=finished/sys.img,format=raw,index=1,media=disk \
+		-drive file=finished/vend.img,format=raw,index=2,media=disk \
+		-vga virtio
+
+iso:
+	@echo "Creating bootable hybrid ISO..."
+	@mkdir -p out_staging/iso_root
+	@cp finished/boot.img out_staging/iso_root/boot.img
+	@cp out_staging/efi_part.img out_staging/iso_root/efi_part.img
+	@xorriso -as mkisofs \
+		-o finished/boot.iso \
+		-b boot.img \
+		-hard-disk-boot \
+		-eltorito-alt-boot \
+		-e efi_part.img \
+		-no-emul-boot \
+		-V "ArkOS" \
+		out_staging/iso_root
+
+run-iso:
+	@echo "Starting ArkOS Testing Window in QEMU (BIOS ISO)..."
+	@dd if=/dev/zero of=finished/dummy.img bs=1M count=1 2>/dev/null
+	@qemu-system-x86_64 \
+		-m 2048 \
+		-smp 2 \
+		-cdrom finished/boot.iso \
+		-drive file=finished/dummy.img,format=raw,index=0,media=disk \
+		-drive file=finished/sys.img,format=raw,index=1,media=disk \
+		-drive file=finished/vend.img,format=raw,index=3,media=disk \
+		-vga virtio \
+		-enable-kvm 2>/dev/null || \
+	qemu-system-x86_64 \
+		-m 2048 \
+		-smp 2 \
+		-cdrom finished/boot.iso \
+		-drive file=finished/dummy.img,format=raw,index=0,media=disk \
+		-drive file=finished/sys.img,format=raw,index=1,media=disk \
+		-drive file=finished/vend.img,format=raw,index=3,media=disk \
+		-vga virtio
+
+run-iso-uefi:
+	@echo "Starting ArkOS Testing Window in QEMU (UEFI ISO)..."
+	@dd if=/dev/zero of=finished/dummy.img bs=1M count=1 2>/dev/null
+	@qemu-system-x86_64 \
+		-bios /usr/share/edk2/x64/OVMF.4m.fd \
+		-m 2048 \
+		-smp 2 \
+		-cdrom finished/boot.iso \
+		-drive file=finished/dummy.img,format=raw,index=0,media=disk \
+		-drive file=finished/sys.img,format=raw,index=1,media=disk \
+		-drive file=finished/vend.img,format=raw,index=3,media=disk \
+		-vga virtio \
+		-enable-kvm 2>/dev/null || \
+	qemu-system-x86_64 \
+		-bios /usr/share/edk2/x64/OVMF.4m.fd \
+		-m 2048 \
+		-smp 2 \
+		-cdrom finished/boot.iso \
+		-drive file=finished/dummy.img,format=raw,index=0,media=disk \
+		-drive file=finished/sys.img,format=raw,index=1,media=disk \
+		-drive file=finished/vend.img,format=raw,index=3,media=disk \
+		-vga virtio
+
 clean:
 	rm -rf out_staging finished
+
+# Extract securebuild key
+ARK_KEY := $(shell if [ -f vendor/verify/securebuild.ark ]; then grep "^ARK-OS-" vendor/verify/securebuild.ark | tr -d '[:space:]'; else echo "NO_KEY"; fi)
+
+# Compilation targets for ArkOS binaries
+out_staging/fb_helper.o: system/fb_helper.c
+	gcc -c system/fb_helper.c -o out_staging/fb_helper.o
+
+out_staging/swift_splash: system/swift_splash.swift out_staging/fb_helper.o
+	swiftc -O -static-executable system/swift_splash.swift out_staging/fb_helper.o -o out_staging/swift_splash
+
+out_staging/arkrt: arkrt/main.swift arkrt/KernelBridge.swift arkrt/CommandRouter.swift arkrt/IPC.swift
+	swiftc -O -static-executable arkrt/main.swift arkrt/KernelBridge.swift arkrt/CommandRouter.swift arkrt/IPC.swift -o out_staging/arkrt
+
+out_staging/init: system/init.c vendor/verify/sha256.c
+	gcc -static vendor/verify/sha256.c system/init.c -Ivendor/verify -DARK_KEY="\"$(ARK_KEY)\"" -o out_staging/init
+
+out_staging/bootloader.bin: boot/source/bootloader.asm
+	nasm -f bin boot/source/bootloader.asm -o out_staging/bootloader.bin
+
+out_staging/stage2.bin: boot/source/stage2.asm
+	nasm -f bin boot/source/stage2.asm -o out_staging/stage2.bin
+
+out_staging/BOOTX64.EFI: boot/source/bootloader.c
+	gcc -I/usr/include/efi -I/usr/include/efi/x86_64 -I/usr/include/efi/protocol \
+		-fno-stack-protector -fpic -fshort-wchar -mno-red-zone -DEFI_FUNCTION_WRAPPER \
+		-c boot/source/bootloader.c -o out_staging/bootloader_uefi.o
+	ld -nostdlib -znocombreloc -T /usr/lib/elf_x86_64_efi.lds -shared -Bsymbolic \
+		/usr/lib/crt0-efi-x86_64.o out_staging/bootloader_uefi.o -o out_staging/bootloader_uefi.so \
+		-lgnuefi -lefi -L/usr/lib
+	objcopy -j .text -j .sdata -j .data -j .rodata -j .dynamic -j .dynsym -j .rel -j .rela -j .reloc -j .eh_frame \
+		-O pei-x86-64 --subsystem 10 out_staging/bootloader_uefi.so out_staging/BOOTX64.EFI

+ 52 - 5
arkos/boot/source/bootloader.asm

@@ -9,11 +9,23 @@ start:
     mov ss, ax
     mov sp, 0x7C00
 
+    ; Save boot drive passed in dl by the BIOS
+    mov [boot_drive], dl
+
     ; Clear screen
     mov ah, 0x00
     mov al, 0x03
     int 0x10
 
+    ; Print boot drive number in dl
+    mov al, dl
+    call print_hex_byte
+    mov ah, 0x0E
+    mov al, 13
+    int 0x10
+    mov al, 10
+    int 0x10
+
     ; Print startup messages
     mov si, msg_start
     call print_string
@@ -27,9 +39,8 @@ start:
     mov si, msg_kernel
     call print_string
 
-    ; Load Stage 2 from disk
-    ; We assume Stage 2 is at LBA 1, 7 sectors long, load to 0x7E00
-    mov dl, 0x80 ; Hardcode boot drive to 0x80
+    ; Load Stage 2 from disk using LBA read
+    mov dl, [boot_drive]
     mov ah, 0x42
     mov si, dap
     int 0x13
@@ -39,12 +50,43 @@ start:
     jmp 0x0000:0x7E00
 
 disk_error:
+    mov al, ah
+    call print_hex_byte
+    mov ah, 0x0E
+    mov al, 13
+    int 0x10
+    mov al, 10
+    int 0x10
     mov si, msg_err
     call print_string
 halt:
     hlt
     jmp halt
 
+print_hex_byte:
+    push ax
+    push cx
+    mov cl, 4
+    shr al, cl
+    call print_nibble
+    pop ax
+    push ax
+    call print_nibble
+    pop cx
+    pop ax
+    ret
+
+print_nibble:
+    and al, 0x0F
+    add al, '0'
+    cmp al, '9'
+    jbe .print
+    add al, 7
+.print:
+    mov ah, 0x0E
+    int 0x10
+    ret
+
 ; --- Functions ---
 print_string:
     mov ah, 0x0E ; Teletype output
@@ -64,6 +106,8 @@ msg_drm:    db "Loading DRM Module... OK", 13, 10, 0
 msg_kernel: db "Loading Kernel & Launching OS...", 13, 10, 0
 msg_err:    db "Disk Error loading Stage 2!", 13, 10, 0
 
+boot_drive: db 0
+
 align 4
 dap:
     db 0x10 ; size of DAP
@@ -71,7 +115,10 @@ dap:
     dw 7    ; number of sectors to read
     dw 0x7E00 ; offset
     dw 0x0000 ; segment
-    dq 1    ; LBA 1 (Stage 2 starts at sector 1)
+    dq 34   ; LBA 34 (Stage 2 starts at sector 34 in hybrid GPT layout)
 
-times 510-($-$$) db 0
+times 446-($-$$) db 0
+; Partition table placeholder (4 partitions * 16 bytes = 64 bytes)
+times 64 db 0
+; Boot signature
 dw 0xAA55

+ 286 - 32
arkos/boot/source/bootloader.c

@@ -5,64 +5,318 @@
 #define HARDWARE_SECURE_KEY "ARK-OS-9aaafa37077ee91e5df2f47a8e9e1564beecde1cc13b279f51d915bf8c746eb4"
 
 EFI_STATUS check_os_signature(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
-    Print(L"Checking Hardware Secure Key...\n");
-    // In a real scenario, we would read the securebuild.ark or avb.img from disk.
-    // For this conceptual implementation, we assume we read it and compare.
-    int has_key = 1; // Assume key exists in hardware
-    int match = 1;   // Assume signature matches
+    // Conceptual hardware verified boot check
+    int has_key = 1;
+    int match = 1;
 
     if (has_key) {
         if (match) {
-            Print(L"Signature matches. OS is verified.\n");
             return EFI_SUCCESS;
         } else {
-            Print(L"WARNING: Signature mismatch! Halting boot.\n");
             return EFI_SECURITY_VIOLATION;
         }
     } else {
-        Print(L"No hardware key found. Proceeding with unverified boot.\n");
         return EFI_SUCCESS;
     }
 }
 
 EFI_STATUS load_drm_module() {
-    Print(L"Loading DRM Module...\n");
-    // Code to load DRM from /frameworks/DRM into memory
-    Print(L"DRM Module loaded and initialized.\n");
+    // Conceptual DRM module loading
     return EFI_SUCCESS;
 }
 
-EFI_STATUS load_kernel(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
-    Print(L"Loading Kernel into memory...\n");
-    // Code to locate bzImage on the EFI System Partition, load it into RAM,
-    // prepare boot parameters (command line, initrd), and jump to it.
-    Print(L"Kernel loaded. Passing specifications and security file passthroughs...\n");
-    // Boot transfer
+static EFI_STATUS read_file_from_esp(
+    EFI_HANDLE ImageHandle,
+    EFI_SYSTEM_TABLE *SystemTable,
+    CHAR16 *FileName,
+    VOID **BufferOut,
+    UINTN *SizeOut
+) {
+    EFI_STATUS status;
+    EFI_LOADED_IMAGE *loaded_image = NULL;
+    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs = NULL;
+    EFI_FILE_HANDLE root = NULL;
+    EFI_FILE_HANDLE file = NULL;
+
+    // 1. Get the LoadedImage protocol for the current bootloader
+    status = uefi_call_wrapper(
+        SystemTable->BootServices->HandleProtocol,
+        3,
+        ImageHandle,
+        &LoadedImageProtocol,
+        (VOID **)&loaded_image
+    );
+    if (EFI_ERROR(status)) return status;
+
+    // 2. Open the SimpleFileSystem protocol on the device handle of the loaded image
+    status = uefi_call_wrapper(
+        SystemTable->BootServices->HandleProtocol,
+        3,
+        loaded_image->DeviceHandle,
+        &FileSystemProtocol,
+        (VOID **)&fs
+    );
+    if (EFI_ERROR(status)) return status;
+
+    // 3. Open the volume
+    status = uefi_call_wrapper(fs->OpenVolume, 2, fs, &root);
+    if (EFI_ERROR(status)) return status;
+
+    // 4. Open the file
+    status = uefi_call_wrapper(
+        root->Open,
+        5,
+        root,
+        &file,
+        FileName,
+        EFI_FILE_MODE_READ,
+        0
+    );
+    if (EFI_ERROR(status)) {
+        uefi_call_wrapper(root->Close, 1, root);
+        return status;
+    }
+
+    // 5. Get file info to determine size
+    EFI_FILE_INFO *file_info = NULL;
+    UINTN info_size = 0;
+    status = uefi_call_wrapper(
+        file->GetInfo,
+        4,
+        file,
+        &GenericFileInfo,
+        &info_size,
+        NULL
+    );
+    if (status == EFI_BUFFER_TOO_SMALL) {
+        status = uefi_call_wrapper(
+            SystemTable->BootServices->AllocatePool,
+            3,
+            EfiLoaderData,
+            info_size,
+            (VOID **)&file_info
+        );
+        if (EFI_ERROR(status)) {
+            uefi_call_wrapper(file->Close, 1, file);
+            uefi_call_wrapper(root->Close, 1, root);
+            return status;
+        }
+
+        status = uefi_call_wrapper(
+            file->GetInfo,
+            4,
+            file,
+            &GenericFileInfo,
+            &info_size,
+            (VOID *)file_info
+        );
+    }
+
+    if (EFI_ERROR(status)) {
+        if (file_info) uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, file_info);
+        uefi_call_wrapper(file->Close, 1, file);
+        uefi_call_wrapper(root->Close, 1, root);
+        return status;
+    }
+
+    UINTN file_size = file_info->FileSize;
+    uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, file_info);
+
+    // 6. Allocate buffer for file contents
+    VOID *buffer = NULL;
+    status = uefi_call_wrapper(
+        SystemTable->BootServices->AllocatePool,
+        3,
+        EfiLoaderData,
+        file_size,
+        &buffer
+    );
+    if (EFI_ERROR(status)) {
+        uefi_call_wrapper(file->Close, 1, file);
+        uefi_call_wrapper(root->Close, 1, root);
+        return status;
+    }
+
+    // 7. Read file contents
+    UINTN read_size = file_size;
+    status = uefi_call_wrapper(file->Read, 3, file, &read_size, buffer);
+    if (EFI_ERROR(status) || read_size != file_size) {
+        uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, buffer);
+        uefi_call_wrapper(file->Close, 1, file);
+        uefi_call_wrapper(root->Close, 1, root);
+        return EFI_DEVICE_ERROR;
+    }
+
+    // 8. Clean up and return
+    uefi_call_wrapper(file->Close, 1, file);
+    uefi_call_wrapper(root->Close, 1, root);
+
+    *BufferOut = buffer;
+    *SizeOut = file_size;
     return EFI_SUCCESS;
 }
 
 EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
     InitializeLib(ImageHandle, SystemTable);
-    
-    Print(L"Welcome to ArkOS Bootloader\n");
-    
-    EFI_STATUS status = check_os_signature(ImageHandle, SystemTable);
+    EFI_STATUS status;
+
+    // 1. Locate the Graphics Output Protocol (GOP)
+    EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
+    EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+    status = uefi_call_wrapper(
+        SystemTable->BootServices->LocateProtocol,
+        3,
+        &gop_guid,
+        NULL,
+        (VOID **)&gop
+    );
+
+    UINTN center_x = 0;
+    UINTN center_y = 0;
+    UINTN anim_width = 200;
+    UINTN anim_height = 200;
+
+    // 2. Clear screen to black and display the white dot
+    if (!EFI_ERROR(status) && gop) {
+        EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
+        uefi_call_wrapper(
+            gop->Blt,
+            10,
+            gop,
+            &black,
+            EfiBltVideoFill,
+            0, 0,
+            0, 0,
+            gop->Mode->Info->HorizontalResolution,
+            gop->Mode->Info->VerticalResolution,
+            0
+        );
+
+        center_x = (gop->Mode->Info->HorizontalResolution - anim_width) / 2;
+        center_y = (gop->Mode->Info->VerticalResolution - anim_height) / 2;
+
+        // Draw a 6x6 pixel white dot in the center of the 200x200 region
+        EFI_GRAPHICS_OUTPUT_BLT_PIXEL white = {255, 255, 255, 0};
+        uefi_call_wrapper(
+            gop->Blt,
+            10,
+            gop,
+            &white,
+            EfiBltVideoFill,
+            0, 0,
+            center_x + 97, center_y + 97,
+            6, 6,
+            0
+        );
+    }
+
+    // 3. Perform OS Key signature check and load DRM
+    status = check_os_signature(ImageHandle, SystemTable);
     if (EFI_ERROR(status)) {
         return status;
     }
-
-    // Only load DRM if we successfully passed the key check (or if no key was present and we proceeded)
-    // The prompt says: "load DRM and makesure the OS is singe... if it does not have a key it will boot up anyway"
     load_drm_module();
 
-    status = load_kernel(ImageHandle, SystemTable);
-    if (EFI_ERROR(status)) {
-        Print(L"Failed to load kernel.\n");
-        return status;
+    // 4. Resolve path and load the kernel image (bzImage)
+    EFI_LOADED_IMAGE *loaded_image = NULL;
+    status = uefi_call_wrapper(
+        SystemTable->BootServices->HandleProtocol,
+        3,
+        ImageHandle,
+        &LoadedImageProtocol,
+        (VOID **)&loaded_image
+    );
+    if (EFI_ERROR(status)) return status;
+
+    EFI_DEVICE_PATH *kernel_path = FileDevicePath(loaded_image->DeviceHandle, L"\\EFI\\BOOT\\bzImage");
+    if (kernel_path == NULL) return EFI_OUT_OF_RESOURCES;
+
+    EFI_HANDLE kernel_img = NULL;
+    status = uefi_call_wrapper(
+        SystemTable->BootServices->LoadImage,
+        6,
+        FALSE,
+        ImageHandle,
+        kernel_path,
+        NULL,
+        0,
+        &kernel_img
+    );
+    if (EFI_ERROR(status)) return status;
+
+    // 5. Play the boot animation (expanding nucleus) from ESP
+    if (gop) {
+        VOID *anim_buffer = NULL;
+        UINTN anim_size = 0;
+        status = read_file_from_esp(ImageHandle, SystemTable, L"\\EFI\\BOOT\\animation.bin", &anim_buffer, &anim_size);
+        if (!EFI_ERROR(status)) {
+            UINTN num_frames = 60;
+            UINTN expected_size = num_frames * anim_width * anim_height * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+            
+            if (anim_size >= expected_size) {
+                // Clear the white dot to black first
+                EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
+                uefi_call_wrapper(
+                    gop->Blt,
+                    10,
+                    gop,
+                    &black,
+                    EfiBltVideoFill,
+                    0, 0,
+                    0, 0,
+                    gop->Mode->Info->HorizontalResolution,
+                    gop->Mode->Info->VerticalResolution,
+                    0
+                );
+
+                EFI_GRAPHICS_OUTPUT_BLT_PIXEL *frames = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)anim_buffer;
+                for (UINTN f = 0; f < num_frames; f++) {
+                    EFI_GRAPHICS_OUTPUT_BLT_PIXEL *frame = &frames[f * anim_width * anim_height];
+                    
+                    uefi_call_wrapper(
+                        gop->Blt,
+                        10,
+                        gop,
+                        frame,
+                        EfiBltBufferToVideo,
+                        0, 0,
+                        center_x, center_y,
+                        anim_width, anim_height,
+                        anim_width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+                    );
+                    
+                    uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 16666);
+                }
+            }
+            uefi_call_wrapper(SystemTable->BootServices->FreePool, 1, anim_buffer);
+        }
     }
 
-    Print(L"Jumping to Kernel...\n");
-    
-    // The kernel will now take over and eventually launch the Swift splash screen.
-    return EFI_SUCCESS;
+    // 6. Set command line options for the kernel
+    EFI_LOADED_IMAGE *kernel_loaded_image = NULL;
+    status = uefi_call_wrapper(
+        SystemTable->BootServices->HandleProtocol,
+        3,
+        kernel_img,
+        &LoadedImageProtocol,
+        (VOID **)&kernel_loaded_image
+    );
+    if (EFI_ERROR(status)) return status;
+
+    CHAR16 *cmd_line = L"initrd=\\EFI\\BOOT\\initramfs.img console=ttyS0 loglevel=0 logo.nologo init=/init root=/dev/sdb rw quiet vt.global_cursor_default=0";
+    kernel_loaded_image->LoadOptions = cmd_line;
+    kernel_loaded_image->LoadOptionsSize = (StrLen(cmd_line) + 1) * sizeof(CHAR16);
+
+    // 7. Start the kernel
+    UINTN exit_data_size = 0;
+    CHAR16 *exit_data = NULL;
+    status = uefi_call_wrapper(
+        SystemTable->BootServices->StartImage,
+        3,
+        kernel_img,
+        &exit_data_size,
+        &exit_data
+    );
+
+    return status;
 }

+ 12 - 1
arkos/boot/source/stage2.asm

@@ -1,6 +1,9 @@
 [BITS 16]
 [ORG 0x7E00]
 
+    ; Save boot drive passed in dl by the bootloader
+    mov [boot_drive], dl
+
     ; Set VESA Video Mode (1024x768x32 - Bochs VBE mode)
     mov ax, 0x4F02
     mov bx, 0x4144       ; mode 0x144 + LFB bit = 32bpp guaranteed
@@ -51,7 +54,15 @@
     mov ss, ax
     sti
 
-    mov [boot_drive], byte 0x80
+    ; Clear linear framebuffer (black screen) to prevent text bleed-through
+    mov edi, [lfb_addr]
+    xor eax, eax
+    mov ecx, [screen_pitch]
+    shr ecx, 2              ; dwords per scanline
+    imul ecx, 768           ; total dwords for 768 lines
+    a32 rep stosd
+
+
 
     ; Load animation.bin to 0x2000000 (32MB)
     mov eax, [animation_lba]

+ 11 - 48
tools/build.c

@@ -170,9 +170,7 @@ int main(int argc, char *argv[]) {
   step("Compiling : system/fb_helper.c");
   {
     char cmd[1024];
-    snprintf(cmd, sizeof(cmd),
-             "%s -c %s/fb_helper.c -o %s/fb_helper.o",
-             cc, system_dir, staging);
+    snprintf(cmd, sizeof(cmd), "make -C %s out_staging/fb_helper.o", base);
     run(cmd);
   }
 
@@ -180,57 +178,27 @@ int main(int argc, char *argv[]) {
   step("Compiling : system/swift_splash.swift & arkrt");
   {
     char cmd[1024];
-    // Compile swift_splash
-    snprintf(cmd, sizeof(cmd),
-             "swiftc -O -static-executable %s/swift_splash.swift %s/fb_helper.o "
-             "-o %s/swift_splash",
-             system_dir, staging, staging);
-    run(cmd);
-
-    // Compile arkrt
-    snprintf(cmd, sizeof(cmd),
-             "swiftc -O -static-executable "
-             "%s/arkrt/main.swift %s/arkrt/KernelBridge.swift "
-             "%s/arkrt/CommandRouter.swift %s/arkrt/IPC.swift "
-             "-o %s/arkrt",
-             base, base, base, base, staging);
+    snprintf(cmd, sizeof(cmd), "make -C %s out_staging/swift_splash out_staging/arkrt", base);
     run(cmd);
   }
 
   /* ─── Step 9: Sign arkrt (Verified Boot) ────────────────────── */
   step("Signing arkrt (Verified Boot)");
   {
-    /* Parse the key */
-    char *securebuild_path = pjoin(vendor_dir, "verify/securebuild.ark");
-    ArkConfig *sbc = ark_parse(securebuild_path);
-    char ark_key[256] = "NO_KEY";
-    for (int i = 0; i < sbc->standalone_count; i++) {
-      if (strstr(sbc->standalone[i], "ARK-OS-") != NULL) {
-        strncpy(ark_key, sbc->standalone[i], sizeof(ark_key) - 1);
-        break;
-      }
-    }
-    ark_free(sbc);
-
     char cmd[1024];
     snprintf(cmd, sizeof(cmd),
              "python3 %s/verify/sign.py %s/verify/securebuild.ark "
              "%s/arkrt %s/signature.bin",
              vendor_dir, vendor_dir, staging, staging);
     run(cmd);
+  }
 
-    free(securebuild_path);
-
-    /* ─── Step 10: Compile init.c + vendor/verify/sha256.c ──── */
-    step("Compiling : system/init.c + vendor/verify/sha256.c");
-    {
-      char cmd2[1024];
-      snprintf(cmd2, sizeof(cmd2),
-               "%s -static %s/verify/sha256.c %s/init.c "
-               "-I%s/verify -DARK_KEY=\"\\\"%s\\\"\" -o %s/init",
-               cc, vendor_dir, system_dir, vendor_dir, ark_key, staging);
-      run(cmd2);
-    }
+  /* ─── Step 10: Compile init.c + vendor/verify/sha256.c ──── */
+  step("Compiling : system/init.c + vendor/verify/sha256.c");
+  {
+    char cmd2[1024];
+    snprintf(cmd2, sizeof(cmd2), "make -C %s out_staging/init", base);
+    run(cmd2);
   }
 
   /* ─── Step 11: Pack initramfs ───────────────────────────────── */
@@ -294,13 +262,8 @@ int main(int argc, char *argv[]) {
     run(cmd);
 
     snprintf(cmd, sizeof(cmd),
-             "nasm -f bin %s/source/bootloader.asm -o %s/bootloader.bin",
-             boot_dir, staging);
-    run(cmd);
-
-    snprintf(cmd, sizeof(cmd),
-             "nasm -f bin %s/source/stage2.asm -o %s/stage2.bin",
-             boot_dir, staging);
+             "make -C %s out_staging/bootloader.bin out_staging/stage2.bin out_staging/BOOTX64.EFI",
+             base);
     run(cmd);
   }
 

+ 53 - 7
tools/pack_boot.py

@@ -56,12 +56,13 @@ def main():
 
     # Calculate LBA sectors (each sector is 512 bytes)
     bootloader_sectors = 1
+    gpt_metadata_sectors = 33
 
     # Stage 2 MUST be exactly 7 sectors (bootloader.asm reads 7 sectors)
     stage2_padded_size = 7 * 512
     stage2 += b"\0" * (stage2_padded_size - len(stage2))
 
-    animation_lba = bootloader_sectors + 7
+    animation_lba = bootloader_sectors + gpt_metadata_sectors + 7
     animation_size_sectors = align_up(len(animation), 512) // 512
     animation_padded = animation + b"\0" * (
         animation_size_sectors * 512 - len(animation)
@@ -98,15 +99,60 @@ def main():
     )
     stage2[idx : idx + 28] = patched_vars
 
+    # Concatenate the BIOS part to compute bios_size_bytes
+    # We leave sectors 1-33 (16896 bytes) as zero placeholders for GPT metadata
+    bios_data = bytearray(bootloader + b"\0" * (gpt_metadata_sectors * 512) + stage2 + animation_padded + kernel_padded + initramfs_padded)
+    bios_size_bytes = len(bios_data)
+
+    # Align bios_size_bytes to 1MB boundary (2048 sectors)
+    bios_aligned_size = align_up(bios_size_bytes, 1024 * 1024)
+    bios_aligned_sectors = bios_aligned_size // 512
+    bios_padding_size = bios_aligned_size - bios_size_bytes
+    bios_data_padded = bios_data + b"\0" * bios_padding_size
+
+    # Create the EFI System Partition image (FAT32)
+    staging_dir = os.path.join(base, "out_staging")
+    efi_part_path = os.path.join(staging_dir, "efi_part.img")
+    uefi_bootloader_path = os.path.join(staging_dir, "BOOTX64.EFI")
+
+    print("  Creating EFI System Partition image (FAT32)...")
+    if os.path.exists(efi_part_path):
+        os.remove(efi_part_path)
+    
+    with open(efi_part_path, "wb") as f:
+        f.write(b"\0" * (180 * 1024 * 1024))
+    
+    os.system(f"mkfs.vfat -F 32 -h {bios_aligned_sectors} {efi_part_path} >/dev/null 2>&1")
+    os.system(f"mmd -i {efi_part_path} ::/EFI >/dev/null 2>&1")
+    os.system(f"mmd -i {efi_part_path} ::/EFI/BOOT >/dev/null 2>&1")
+    os.system(f"mcopy -i {efi_part_path} {uefi_bootloader_path} ::/EFI/BOOT/BOOTX64.EFI >/dev/null 2>&1")
+    os.system(f"mcopy -i {efi_part_path} {kernel_path} ::/EFI/BOOT/bzImage >/dev/null 2>&1")
+    os.system(f"mcopy -i {efi_part_path} {initramfs_path} ::/EFI/BOOT/initramfs.img >/dev/null 2>&1")
+    os.system(f"mcopy -i {efi_part_path} {animation_path} ::/EFI/BOOT/animation.bin >/dev/null 2>&1")
+
+    with open(efi_part_path, "rb") as f:
+        efi_part_data = f.read()
+    efi_part_sectors = len(efi_part_data) // 512
+
+    # Write the hybrid image first (BIOS part + padding + UEFI partition + GPT backup padding)
     with open(out_path, "wb") as f:
-        f.write(bootloader)
-        f.write(stage2)
-        f.write(animation_padded)
-        f.write(kernel_padded)
-        f.write(initramfs_padded)
+        f.write(bios_data_padded)
+        f.write(efi_part_data)
+        f.write(b"\0" * (33 * 512))
+
+    # Use sgdisk to write a valid GPT partition table on the image
+    # Sector bios_aligned_sectors corresponds to start of EFI partition
+    # Partition type is 'EF00' (EFI System Partition), partition name is 'EFI'
+    import subprocess
+    sgdisk_cmd = f"sgdisk -g -n 1:{bios_aligned_sectors}:{bios_aligned_sectors + efi_part_sectors - 1} -t 1:ef00 -c 1:'EFI' {out_path}"
+    subprocess.run(sgdisk_cmd, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+    # Overwrite the MBR boot code (first 446 bytes of Sector 0) with our bootloader
+    with open(out_path, "r+b") as f:
+        f.write(bootloader[:446])
 
     total = os.path.getsize(out_path)
-    print(f"  boot.img built successfully! ({total:,} bytes)")
+    print(f"  boot.img (hybrid UEFI/BIOS) built successfully! ({total:,} bytes)")
 
 
 if __name__ == "__main__":