Add prototype for kaem-minimal.
This commit is contained in:
parent
c5889ecef0
commit
6f90a6cd2e
|
@ -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)
|
||||
|
|
|
@ -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)();
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -114,8 +114,8 @@ not_comment:
|
|||
goto next_byte;
|
||||
|
||||
terminate:
|
||||
/* rootdir->close(fin);
|
||||
rootdir->close(fout); */
|
||||
rootdir->close(fin);
|
||||
rootdir->close(fout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
BOOTX64 hex0_AMD64_POSIX.hex0 hex0
|
||||
BOOTX64
|
||||
|
|
Loading…
Reference in New Issue