diff --git a/Development/Makefile b/Development/Makefile index a260fab..846d657 100644 --- a/Development/Makefile +++ b/Development/Makefile @@ -2,16 +2,16 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -targets = hex0 -ESP_SIZE = 50 # MiB +targets = kaem-minimal hex0 +ESP_SIZE_MIB = 50 QEMU = qemu-system-x86_64 OVMF_IMG = /usr/share/edk2-ovmf/OVMF_CODE.fd -ESP_SIZE_SECTORS = $$(($(ESP_SIZE) * 2048)) -DISK_SIZE_SECTORS=$$(($(ESP_SIZE_SECTORS) + 2048 + 33)) +ESP_SIZE_SECTORS = $$(($(ESP_SIZE_MIB) * 2048)) +DISK_SIZE_SECTORS = $$(($(ESP_SIZE_SECTORS) + 2048 + 33)) cc = clang -cflags = -ffreestanding -MMD -mno-red-zone -std=c11 -target x86_64-unknown-windows -Wall -Werror -pedantic +cflags = -ffreestanding -MMD -mno-red-zone -std=c11 -target x86_64-unknown-windows ld = lld-link lflags = -subsystem:efi_application -nodefaultlib -dll build_dir = build @@ -50,7 +50,8 @@ $(build_dir)/esp.img: rootfs rootfs: $(targets2) cp -R rootfs $(build_dir) mkdir -p $(rootfs_dir)/EFI/BOOT/ - cp $(build_dir)/hex0.efi $(rootfs_dir)/EFI/BOOT/BOOTX64.EFI + cp $^ $(rootfs_dir)/EFI/BOOT/ + mv $(rootfs_dir)//EFI/BOOT/kaem-minimal.efi $(rootfs_dir)/EFI/BOOT/BOOTX64.EFI clean: rm -rf $(build_dir) diff --git a/Development/efi/boot_table.h b/Development/efi/boot_table.h index ee5518d..52d538e 100644 --- a/Development/efi/boot_table.h +++ b/Development/efi/boot_table.h @@ -3,6 +3,7 @@ #ifndef __EFI_BOOT_TABLE_H__ #define __EFI_BOOT_TABLE_H__ +#include "device_path_protocol.h" #include "types.h" static const uint32_t EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL = 0x00000001; @@ -52,14 +53,13 @@ struct efi_boot_table void (*unused20)(); // Image Services - void (*unused21)(); - void (*unused22)(); + efi_status_t (*load_image)(uint8_t, efi_handle_t, struct efi_device_path_protocol*, void *, efi_uint_t, efi_handle_t); + efi_status_t (*start_image)(efi_handle_t, efi_uint_t *, uint16_t); void (*unused23)(); - void (*unused24)(); - + efi_status_t (*exit)(efi_handle_t, efi_status_t, uint16_t); efi_status_t (*exit_boot_services)(efi_handle_t, efi_uint_t); - // Miscellaneius Services + // Miscellaneous Services void (*unused26)(); void (*unused27)(); void (*unused28)(); @@ -94,7 +94,7 @@ struct efi_boot_table // 32-bit CRC Services void (*unused39)(); - // Miscellaneius Services (cont) + // Miscellaneous Services (cont) void (*unused40)(); void (*unused41)(); void (*unused42)(); diff --git a/Development/efi/device_path_protocol.h b/Development/efi/device_path_protocol.h index a703697..36f8768 100644 --- a/Development/efi/device_path_protocol.h +++ b/Development/efi/device_path_protocol.h @@ -9,6 +9,9 @@ struct efi_device_path_protocol { uint8_t type; uint8_t subtype; uint16_t length; + uint32_t memory_type; + uint64_t start_address; + uint64_t end_address; }; #endif // __EFI_DEVICE_PATH_PROTOCOL_H__ diff --git a/Development/hex0.c b/Development/hex0.c index 991cf52..d414411 100644 --- a/Development/hex0.c +++ b/Development/hex0.c @@ -114,8 +114,8 @@ not_comment: goto next_byte; terminate: - /* rootdir->close(fin); - rootdir->close(fout); */ + rootdir->close(fin); + rootdir->close(fout); return 0; } diff --git a/Development/kaem-minimal.c b/Development/kaem-minimal.c new file mode 100644 index 0000000..62d4912 --- /dev/null +++ b/Development/kaem-minimal.c @@ -0,0 +1,162 @@ +/* SPDX-FileCopyrightText: 2022 Andrius Štikonas + * + * SPDX-License-Identifier: GPL-3.0-or-later */ + +/* Written in a low level C that is close to assembly. + * We skip error checking since this is a prototype for hex0 code */ + +#include "efi/efi.h" + +#define max_string 512 + +#define HARDWARE_DEVICE_PATH 1 +#define END_HARDWARE_DEVICE_PATH 0x7F +#define END_ENTIRE_DEVICE_PATH 0xFF +#define MEMORY_MAPPED 3 + +efi_status_t efi_main(efi_handle_t image_handle, struct efi_system_table *system) +{ + struct efi_loaded_image_protocol *image, *child_image; + struct efi_simple_file_system_protocol *rootfs; + struct efi_file_protocol *rootdir; + struct efi_guid guid1 = EFI_LOADED_IMAGE_PROTOCOL_GUID; + struct efi_guid guid2 = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; + struct efi_guid guid3 = EFI_FILE_INFO_GUID; + + /* Open Loaded Image protocol */ + system->boot->open_protocol(image_handle, &guid1, (void **) &image, image_handle, 0, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); + + /* Command line args */ + uint16_t *options = image->load_options; + uint16_t default_file[] = L"kaem.amd64"; + uint16_t *script_file; + do { + ++options; + } while (*options != ' ' && *options != 0); /* Skip app name */ + + if (! *options) { + script_file = default_file; + } + else { + script_file = ++options; + } + + /* Get root device */ + efi_handle_t root_device = image->device; + system->boot->open_protocol(root_device, &guid2, (void **) &rootfs, image_handle, 0, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); + /* Get root fs */ + rootfs->open_volume(rootfs, &rootdir); + + /* Open file for reading */ + struct efi_file_protocol *fin; + efi_status_t status = rootdir->open(rootdir, &fin, script_file, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY); + if(status != EFI_SUCCESS) { + return status; + } + + uint16_t *command; + system->boot->allocate_pool(EFI_LOADER_DATA, 2 * max_string, (void **) &command); + + unsigned int command_length = 0; /* length of command without arguments */ + unsigned int i; + uint8_t c; + efi_uint_t size = 1; + efi_uint_t return_code; + void *executable; + efi_handle_t child_ih; + + do + { + i = 0; + command_length = 0; + do + { + fin->read(fin, &size, &c); + if (size == 0) { + rootdir->close(fin); + system->boot->free_pool(command); + return EFI_SUCCESS; + } + else if(c == '\n') { + break; + } + else if (c == ' ' && command_length == 0) { + command_length = i; + } + else if (c == '#') { + /* Line comments */ + do { + fin->read(fin, &size, &c); + } while (c != '\n'); + break; + } + command[i] = c; + i++; + } while(true); + + if (command_length == 0 ) { + continue; + } + + command[i] = 0; + + system->out->output_string(system->out, L" +> "); + system->out->output_string(system->out, command); + system->out->output_string(system->out, L"\r\n"); + + command[command_length] = 0; + + /* Open executable file for reading and load it into memory */ + struct efi_file_protocol *fcmd; + efi_status_t status = rootdir->open(rootdir, &fcmd, command, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY); + if(status != EFI_SUCCESS) { + system->boot->free_pool(command); + rootdir->close(fin); + return status; + } + + struct efi_file_info *file_info; + size = sizeof(struct efi_file_info); + system->boot->allocate_pool(EFI_LOADER_DATA, size, (void **) &file_info); + fcmd->get_info(fcmd, &guid3, &size, file_info); + size = file_info->file_size; + system->boot->free_pool(file_info); + + system->boot->allocate_pool(EFI_LOADER_CODE, size, (void **) &executable); + fcmd->read(fcmd, &size, executable); + + struct efi_device_path_protocol *device_path; + system->boot->allocate_pool(EFI_LOADER_DATA, 4 + sizeof(struct efi_device_path_protocol), (void **) &device_path); + device_path->type = HARDWARE_DEVICE_PATH; + device_path->subtype = MEMORY_MAPPED; + device_path->length = sizeof(struct efi_device_path_protocol); + device_path->memory_type = EFI_LOADER_CODE; + device_path->start_address = (uint64_t) executable; + device_path->end_address = (uint64_t) executable + size; + device_path[1].type = END_HARDWARE_DEVICE_PATH; + device_path[1].subtype = END_ENTIRE_DEVICE_PATH; + device_path[1].length = 4; + + system->boot->load_image(0, image_handle, device_path, executable, size, &child_ih); + system->boot->free_pool(device_path); + system->boot->free_pool(executable); + + /* Deal with command line arguments */ + command[command_length] = ' '; + system->boot->open_protocol(child_ih, &guid1, (void **) &child_image, child_ih, 0, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); + child_image->load_options = command; + child_image->device = image->device; + + /* Run command */ + return_code = system->boot->start_image(child_ih, 0, 0); + + if(return_code != 0) { + system->boot->free_pool(command); + system->out->output_string(system->out, L"Subprocess error.\r\n"); + return return_code; + } + } while(true); +} diff --git a/Development/rootfs/startup.nsh b/Development/rootfs/startup.nsh index 8a0d4cb..04b0d68 100644 --- a/Development/rootfs/startup.nsh +++ b/Development/rootfs/startup.nsh @@ -1,3 +1,3 @@ # SPDX-License-Identifier: Unlicense -BOOTX64 hex0_AMD64_POSIX.hex0 hex0 +BOOTX64