Loaded a kernel
This commit is contained in:
16
Makefile
16
Makefile
@@ -37,6 +37,9 @@ LIBS = -lefi -lgnuefi
|
|||||||
TARGET = BOOTX64.EFI
|
TARGET = BOOTX64.EFI
|
||||||
TARGET_SO = bootx64.so
|
TARGET_SO = bootx64.so
|
||||||
OBJ = $(BUILD_DIR)/main.o
|
OBJ = $(BUILD_DIR)/main.o
|
||||||
|
KERNEL_TARGET = kernel.elf
|
||||||
|
KERNEL_OBJ = $(BUILD_DIR)/kernel.o
|
||||||
|
KERNEL_LD = kernel.ld
|
||||||
|
|
||||||
# QEMU settings
|
# QEMU settings
|
||||||
QEMU = qemu-system-x86_64
|
QEMU = qemu-system-x86_64
|
||||||
@@ -79,7 +82,7 @@ QEMU_FLAGS = -machine q35 \
|
|||||||
.PHONY: all clean run setup install-deps
|
.PHONY: all clean run setup install-deps
|
||||||
|
|
||||||
# Default target
|
# Default target
|
||||||
all: setup $(EFI_DIR)/$(TARGET)
|
all: setup $(EFI_DIR)/$(TARGET) $(BUILD_DIR)/$(KERNEL_TARGET)
|
||||||
|
|
||||||
# Create necessary directories
|
# Create necessary directories
|
||||||
setup:
|
setup:
|
||||||
@@ -92,6 +95,17 @@ $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
|
|||||||
@echo "Compiling $<..."
|
@echo "Compiling $<..."
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# Compile kernel source
|
||||||
|
$(KERNEL_OBJ): $(SRC_DIR)/kernel.c
|
||||||
|
@echo "Compiling kernel.c..."
|
||||||
|
$(CC) -ffreestanding -fno-stack-protector -fno-pic -fshort-wchar \
|
||||||
|
-mno-red-zone -Wall -Wextra $(EFI_INCLUDES) -c $< -o $@
|
||||||
|
|
||||||
|
# Link kernel ELF
|
||||||
|
$(BUILD_DIR)/$(KERNEL_TARGET): $(KERNEL_OBJ) $(KERNEL_LD)
|
||||||
|
@echo "Linking kernel ELF..."
|
||||||
|
$(LD) -nostdlib -T $(KERNEL_LD) $(KERNEL_OBJ) -o $@
|
||||||
|
|
||||||
# Link to create shared object
|
# Link to create shared object
|
||||||
$(BUILD_DIR)/$(TARGET_SO): $(OBJ)
|
$(BUILD_DIR)/$(TARGET_SO): $(OBJ)
|
||||||
@echo "Linking $@..."
|
@echo "Linking $@..."
|
||||||
|
|||||||
19
boot_info.h
Normal file
19
boot_info.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef BOOT_INFO_H
|
||||||
|
#define BOOT_INFO_H
|
||||||
|
|
||||||
|
#include <efi.h>
|
||||||
|
|
||||||
|
typedef UINTN (*KernelPrintFn)(const CHAR16 *Format, ...);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EFI_SYSTEM_TABLE *SystemTable;
|
||||||
|
KernelPrintFn print;
|
||||||
|
EFI_STATUS (*clear_screen)(void);
|
||||||
|
EFI_STATUS (*set_attribute)(UINTN Attribute);
|
||||||
|
EFI_STATUS (*read_key)(EFI_INPUT_KEY *Key);
|
||||||
|
void (*shutdown)(void);
|
||||||
|
} BootInfo;
|
||||||
|
|
||||||
|
typedef void (*KernelEntryFn)(BootInfo *Boot);
|
||||||
|
|
||||||
|
#endif
|
||||||
69
kernel.c
Normal file
69
kernel.c
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#include <efi.h>
|
||||||
|
|
||||||
|
#include "boot_info.h"
|
||||||
|
|
||||||
|
void kmain(BootInfo *Boot)
|
||||||
|
{
|
||||||
|
EFI_INPUT_KEY Key;
|
||||||
|
|
||||||
|
Boot->clear_screen();
|
||||||
|
Boot->set_attribute(EFI_TEXT_ATTR(EFI_LIGHTGREEN, EFI_BLACK));
|
||||||
|
|
||||||
|
Boot->print(L"================================================\n\r");
|
||||||
|
Boot->print(L" Welcome to Simple UEFI Operating System!\n\r");
|
||||||
|
Boot->print(L"================================================\n\r");
|
||||||
|
Boot->print(L"\n\r");
|
||||||
|
Boot->print(L"System Information:\n\r");
|
||||||
|
Boot->print(L" UEFI Firmware Vendor: %s\n\r", Boot->SystemTable->FirmwareVendor);
|
||||||
|
Boot->print(L" UEFI Firmware Revision: %d.%d\n\r",
|
||||||
|
Boot->SystemTable->FirmwareRevision >> 16,
|
||||||
|
Boot->SystemTable->FirmwareRevision & 0xFFFF);
|
||||||
|
Boot->print(L"\n\r");
|
||||||
|
|
||||||
|
Boot->print(L"Available Services:\n\r");
|
||||||
|
Boot->print(L" - Console Input/Output: Active\n\r");
|
||||||
|
Boot->print(L" - Runtime Services: Active\n\r");
|
||||||
|
Boot->print(L" - Boot Services: Active\n\r");
|
||||||
|
Boot->print(L"\n\r");
|
||||||
|
|
||||||
|
Boot->print(L"Commands:\n\r");
|
||||||
|
Boot->print(L" 'h' - Display help\n\r");
|
||||||
|
Boot->print(L" 'i' - Display system info\n\r");
|
||||||
|
Boot->print(L" 'c' - Clear screen\n\r");
|
||||||
|
Boot->print(L" 'q' - Shutdown\n\r");
|
||||||
|
Boot->print(L"\n\r");
|
||||||
|
Boot->print(L"Press a key to start...\n\r");
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
if (EFI_ERROR(Boot->read_key(&Key))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Key.UnicodeChar == L'q' || Key.UnicodeChar == L'Q') {
|
||||||
|
Boot->print(L"\n\rShutting down...\n\r");
|
||||||
|
Boot->shutdown();
|
||||||
|
} else if (Key.UnicodeChar == L'h' || Key.UnicodeChar == L'H') {
|
||||||
|
Boot->print(L"\n\r=== Help ===\n\r");
|
||||||
|
Boot->print(L"This is a minimal UEFI operating system.\n\r");
|
||||||
|
Boot->print(L"It demonstrates basic UEFI functionality.\n\r");
|
||||||
|
Boot->print(L"\n\r");
|
||||||
|
} else if (Key.UnicodeChar == L'i' || Key.UnicodeChar == L'I') {
|
||||||
|
Boot->print(L"\n\r=== System Info ===\n\r");
|
||||||
|
Boot->print(L"Firmware Vendor: %s\n\r", Boot->SystemTable->FirmwareVendor);
|
||||||
|
Boot->print(L"Firmware Revision: %d.%d\n\r",
|
||||||
|
Boot->SystemTable->FirmwareRevision >> 16,
|
||||||
|
Boot->SystemTable->FirmwareRevision & 0xFFFF);
|
||||||
|
Boot->print(L"UEFI Specification: %d.%d\n\r",
|
||||||
|
Boot->SystemTable->Hdr.Revision >> 16,
|
||||||
|
Boot->SystemTable->Hdr.Revision & 0xFFFF);
|
||||||
|
Boot->print(L"\n\r");
|
||||||
|
} else if (Key.UnicodeChar == L'c' || Key.UnicodeChar == L'C') {
|
||||||
|
Boot->clear_screen();
|
||||||
|
Boot->print(L"Screen cleared. Press 'h' for help.\n\r");
|
||||||
|
} else if (Key.UnicodeChar >= 32 && Key.UnicodeChar < 127) {
|
||||||
|
Boot->print(L"%c", Key.UnicodeChar);
|
||||||
|
} else if (Key.UnicodeChar == L'\r') {
|
||||||
|
Boot->print(L"\n\r> ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
kernel.ld
Normal file
27
kernel.ld
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
ENTRY(kmain)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x100000;
|
||||||
|
|
||||||
|
.text : ALIGN(0x1000)
|
||||||
|
{
|
||||||
|
*(.text*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata : ALIGN(0x1000)
|
||||||
|
{
|
||||||
|
*(.rodata*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data : ALIGN(0x1000)
|
||||||
|
{
|
||||||
|
*(.data*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : ALIGN(0x1000)
|
||||||
|
{
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss*)
|
||||||
|
}
|
||||||
|
}
|
||||||
303
main.c
303
main.c
@@ -1,93 +1,250 @@
|
|||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
#include <efilib.h>
|
#include <efilib.h>
|
||||||
|
|
||||||
|
#include "boot_info.h"
|
||||||
|
|
||||||
|
#define ELF_MAGIC 0x464c457f
|
||||||
|
#define PT_LOAD 1
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 e_magic;
|
||||||
|
UINT8 e_class;
|
||||||
|
UINT8 e_data;
|
||||||
|
UINT8 e_version;
|
||||||
|
UINT8 e_osabi;
|
||||||
|
UINT8 e_abiversion;
|
||||||
|
UINT8 e_pad[7];
|
||||||
|
UINT16 e_type;
|
||||||
|
UINT16 e_machine;
|
||||||
|
UINT32 e_version2;
|
||||||
|
UINT64 e_entry;
|
||||||
|
UINT64 e_phoff;
|
||||||
|
UINT64 e_shoff;
|
||||||
|
UINT32 e_flags;
|
||||||
|
UINT16 e_ehsize;
|
||||||
|
UINT16 e_phentsize;
|
||||||
|
UINT16 e_phnum;
|
||||||
|
UINT16 e_shentsize;
|
||||||
|
UINT16 e_shnum;
|
||||||
|
UINT16 e_shstrndx;
|
||||||
|
} Elf64_Ehdr;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 p_type;
|
||||||
|
UINT32 p_flags;
|
||||||
|
UINT64 p_offset;
|
||||||
|
UINT64 p_vaddr;
|
||||||
|
UINT64 p_paddr;
|
||||||
|
UINT64 p_filesz;
|
||||||
|
UINT64 p_memsz;
|
||||||
|
UINT64 p_align;
|
||||||
|
} Elf64_Phdr;
|
||||||
|
|
||||||
|
static EFI_STATUS open_root_volume(EFI_HANDLE ImageHandle, EFI_FILE_PROTOCOL **Root)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_LOADED_IMAGE *LoadedImage = NULL;
|
||||||
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem = NULL;
|
||||||
|
|
||||||
|
Status = uefi_call_wrapper(BS->HandleProtocol, 3, ImageHandle,
|
||||||
|
&gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = uefi_call_wrapper(BS->HandleProtocol, 3, LoadedImage->DeviceHandle,
|
||||||
|
&gEfiSimpleFileSystemProtocolGuid, (VOID **)&FileSystem);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return uefi_call_wrapper(FileSystem->OpenVolume, 2, FileSystem, Root);
|
||||||
|
}
|
||||||
|
|
||||||
|
static EFI_STATUS read_file_to_buffer(EFI_HANDLE ImageHandle, CHAR16 *Path,
|
||||||
|
VOID **Buffer, UINTN *Size)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_FILE_PROTOCOL *Root = NULL;
|
||||||
|
EFI_FILE_PROTOCOL *File = NULL;
|
||||||
|
EFI_FILE_INFO *Info = NULL;
|
||||||
|
UINTN InfoSize = 0;
|
||||||
|
UINTN FileSize = 0;
|
||||||
|
|
||||||
|
Status = open_root_volume(ImageHandle, &Root);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = uefi_call_wrapper(Root->Open, 5, Root, &File, Path,
|
||||||
|
EFI_FILE_MODE_READ, 0);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = uefi_call_wrapper(File->GetInfo, 4, File, &gEfiFileInfoGuid,
|
||||||
|
&InfoSize, NULL);
|
||||||
|
if (Status != EFI_BUFFER_TOO_SMALL) {
|
||||||
|
uefi_call_wrapper(File->Close, 1, File);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData,
|
||||||
|
InfoSize, (VOID **)&Info);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
uefi_call_wrapper(File->Close, 1, File);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = uefi_call_wrapper(File->GetInfo, 4, File, &gEfiFileInfoGuid,
|
||||||
|
&InfoSize, Info);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
uefi_call_wrapper(BS->FreePool, 1, Info);
|
||||||
|
uefi_call_wrapper(File->Close, 1, File);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileSize = (UINTN)Info->FileSize;
|
||||||
|
Status = uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData,
|
||||||
|
FileSize, Buffer);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
uefi_call_wrapper(BS->FreePool, 1, Info);
|
||||||
|
uefi_call_wrapper(File->Close, 1, File);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = uefi_call_wrapper(File->Read, 3, File, &FileSize, *Buffer);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
uefi_call_wrapper(BS->FreePool, 1, Info);
|
||||||
|
uefi_call_wrapper(File->Close, 1, File);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
uefi_call_wrapper(BS->FreePool, 1, Info);
|
||||||
|
uefi_call_wrapper(File->Close, 1, File);
|
||||||
|
|
||||||
|
*Size = FileSize;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EFI_STATUS load_elf_kernel(VOID *Image, UINTN Size, UINT64 *EntryOut)
|
||||||
|
{
|
||||||
|
Elf64_Ehdr *Ehdr = (Elf64_Ehdr *)Image;
|
||||||
|
Elf64_Phdr *Phdr = NULL;
|
||||||
|
UINT16 Index = 0;
|
||||||
|
|
||||||
|
if (Size < sizeof(Elf64_Ehdr)) {
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Ehdr->e_magic != ELF_MAGIC || Ehdr->e_class != 2 || Ehdr->e_data != 1) {
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Ehdr->e_phoff + (UINT64)Ehdr->e_phnum * Ehdr->e_phentsize) > Size) {
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Phdr = (Elf64_Phdr *)((UINT8 *)Image + Ehdr->e_phoff);
|
||||||
|
|
||||||
|
for (Index = 0; Index < Ehdr->e_phnum; Index++) {
|
||||||
|
Elf64_Phdr *Segment = (Elf64_Phdr *)((UINT8 *)Phdr + (Index * Ehdr->e_phentsize));
|
||||||
|
UINT64 SegmentStart = 0;
|
||||||
|
UINT64 SegmentEnd = 0;
|
||||||
|
UINT64 SegmentPages = 0;
|
||||||
|
EFI_PHYSICAL_ADDRESS Address = 0;
|
||||||
|
|
||||||
|
if (Segment->p_type != PT_LOAD || Segment->p_memsz == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Segment->p_offset + Segment->p_filesz) > Size) {
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
SegmentStart = Segment->p_vaddr & ~0xFFFULL;
|
||||||
|
SegmentEnd = (Segment->p_vaddr + Segment->p_memsz + 0xFFFULL) & ~0xFFFULL;
|
||||||
|
SegmentPages = (SegmentEnd - SegmentStart) >> 12;
|
||||||
|
|
||||||
|
Address = (EFI_PHYSICAL_ADDRESS)SegmentStart;
|
||||||
|
if (EFI_ERROR(uefi_call_wrapper(BS->AllocatePages, 4, AllocateAddress,
|
||||||
|
EfiLoaderData, SegmentPages, &Address))) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyMem((VOID *)(UINTN)Segment->p_vaddr,
|
||||||
|
(UINT8 *)Image + Segment->p_offset,
|
||||||
|
(UINTN)Segment->p_filesz);
|
||||||
|
if (Segment->p_memsz > Segment->p_filesz) {
|
||||||
|
SetMem((VOID *)(UINTN)(Segment->p_vaddr + Segment->p_filesz),
|
||||||
|
(UINTN)(Segment->p_memsz - Segment->p_filesz), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*EntryOut = Ehdr->e_entry;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EFI_STATUS loader_clear_screen(void)
|
||||||
|
{
|
||||||
|
return uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
static EFI_STATUS loader_set_attribute(UINTN Attribute)
|
||||||
|
{
|
||||||
|
return uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, Attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
static EFI_STATUS loader_read_key(EFI_INPUT_KEY *Key)
|
||||||
|
{
|
||||||
|
UINTN Index = 0;
|
||||||
|
uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &Index);
|
||||||
|
return uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loader_shutdown(void)
|
||||||
|
{
|
||||||
|
uefi_call_wrapper(RT->ResetSystem, 4, EfiResetShutdown, EFI_SUCCESS, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
|
efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
EFI_INPUT_KEY Key;
|
VOID *KernelImage = NULL;
|
||||||
|
UINTN KernelSize = 0;
|
||||||
|
UINT64 KernelEntry = 0;
|
||||||
|
BootInfo Boot;
|
||||||
|
KernelEntryFn EntryFn = NULL;
|
||||||
|
|
||||||
// Initialize the GNU-EFI library
|
// Initialize the GNU-EFI library
|
||||||
InitializeLib(ImageHandle, SystemTable);
|
InitializeLib(ImageHandle, SystemTable);
|
||||||
|
|
||||||
// Clear the screen
|
Print(L"Loading kernel...\n\r");
|
||||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
|
||||||
|
|
||||||
// Set text color to light green
|
|
||||||
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
|
|
||||||
EFI_TEXT_ATTR(EFI_LIGHTGREEN, EFI_BLACK));
|
|
||||||
|
|
||||||
// Print welcome messages
|
|
||||||
Print(L"================================================\n\r");
|
|
||||||
Print(L" Welcome to Simple UEFI Operating System!\n\r");
|
|
||||||
Print(L"================================================\n\r");
|
|
||||||
Print(L"\n\r");
|
|
||||||
Print(L"System Information:\n\r");
|
|
||||||
Print(L" UEFI Firmware Vendor: %s\n\r", ST->FirmwareVendor);
|
|
||||||
Print(L" UEFI Firmware Revision: %d.%d\n\r",
|
|
||||||
ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xFFFF);
|
|
||||||
Print(L"\n\r");
|
|
||||||
|
|
||||||
// Display some runtime services info
|
|
||||||
Print(L"Available Services:\n\r");
|
|
||||||
Print(L" - Console Input/Output: Active\n\r");
|
|
||||||
Print(L" - Runtime Services: Active\n\r");
|
|
||||||
Print(L" - Boot Services: Active\n\r");
|
|
||||||
Print(L"\n\r");
|
|
||||||
|
|
||||||
// Simple command loop
|
|
||||||
Print(L"Commands:\n\r");
|
|
||||||
Print(L" 'h' - Display help\n\r");
|
|
||||||
Print(L" 'i' - Display system info\n\r");
|
|
||||||
Print(L" 'c' - Clear screen\n\r");
|
|
||||||
Print(L" 'q' - Shutdown\n\r");
|
|
||||||
Print(L"\n\r");
|
|
||||||
Print(L"Press a key to start...\n\r");
|
|
||||||
|
|
||||||
while (TRUE) {
|
|
||||||
// Wait for key press
|
|
||||||
Status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2,
|
|
||||||
ST->ConIn, &Key);
|
|
||||||
|
|
||||||
|
Status = read_file_to_buffer(ImageHandle, L"\\kernel.elf", &KernelImage, &KernelSize);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
continue;
|
Print(L"Failed to read kernel.elf: %r\n\r", Status);
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle commands
|
Status = load_elf_kernel(KernelImage, KernelSize, &KernelEntry);
|
||||||
if (Key.UnicodeChar == L'q' || Key.UnicodeChar == L'Q') {
|
if (EFI_ERROR(Status)) {
|
||||||
Print(L"\n\rShutting down...\n\r");
|
Print(L"Failed to load kernel.elf: %r\n\r", Status);
|
||||||
// Reset the system
|
return Status;
|
||||||
uefi_call_wrapper(RT->ResetSystem, 4, EfiResetShutdown,
|
|
||||||
EFI_SUCCESS, 0, NULL);
|
|
||||||
}
|
|
||||||
else if (Key.UnicodeChar == L'h' || Key.UnicodeChar == L'H') {
|
|
||||||
Print(L"\n\r=== Help ===\n\r");
|
|
||||||
Print(L"This is a minimal UEFI operating system.\n\r");
|
|
||||||
Print(L"It demonstrates basic UEFI functionality.\n\r");
|
|
||||||
Print(L"\n\r");
|
|
||||||
}
|
|
||||||
else if (Key.UnicodeChar == L'i' || Key.UnicodeChar == L'I') {
|
|
||||||
Print(L"\n\r=== System Info ===\n\r");
|
|
||||||
Print(L"Firmware Vendor: %s\n\r", ST->FirmwareVendor);
|
|
||||||
Print(L"Firmware Revision: %d.%d\n\r",
|
|
||||||
ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xFFFF);
|
|
||||||
Print(L"UEFI Specification: %d.%d\n\r",
|
|
||||||
ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xFFFF);
|
|
||||||
Print(L"\n\r");
|
|
||||||
}
|
|
||||||
else if (Key.UnicodeChar == L'c' || Key.UnicodeChar == L'C') {
|
|
||||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
|
||||||
Print(L"Screen cleared. Press 'h' for help.\n\r");
|
|
||||||
}
|
|
||||||
else if (Key.UnicodeChar >= 32 && Key.UnicodeChar < 127) {
|
|
||||||
// Echo printable characters
|
|
||||||
Print(L"%c", Key.UnicodeChar);
|
|
||||||
}
|
|
||||||
else if (Key.UnicodeChar == L'\r') {
|
|
||||||
Print(L"\n\r> ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Boot.SystemTable = ST;
|
||||||
|
Boot.print = Print;
|
||||||
|
Boot.clear_screen = loader_clear_screen;
|
||||||
|
Boot.set_attribute = loader_set_attribute;
|
||||||
|
Boot.read_key = loader_read_key;
|
||||||
|
Boot.shutdown = loader_shutdown;
|
||||||
|
|
||||||
|
EntryFn = (KernelEntryFn)(UINTN)KernelEntry;
|
||||||
|
EntryFn(&Boot);
|
||||||
|
|
||||||
|
Print(L"Kernel returned. Halting.\n\r");
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user