Add prototype for kaem-minimal.

This commit is contained in:
Andrius Štikonas 2022-07-08 18:49:15 +01:00
parent c5889ecef0
commit 6f90a6cd2e
6 changed files with 181 additions and 15 deletions

View File

@ -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)

View File

@ -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)();

View File

@ -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__

View File

@ -114,8 +114,8 @@ not_comment:
goto next_byte;
terminate:
/* rootdir->close(fin);
rootdir->close(fout); */
rootdir->close(fin);
rootdir->close(fout);
return 0;
}

162
Development/kaem-minimal.c Normal file
View File

@ -0,0 +1,162 @@
/* SPDX-FileCopyrightText: 2022 Andrius Štikonas <andrius@stikonas.eu>
*
* 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);
}

View File

@ -1,3 +1,3 @@
# SPDX-License-Identifier: Unlicense
BOOTX64 hex0_AMD64_POSIX.hex0 hex0
BOOTX64