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
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
targets = hex0
|
targets = kaem-minimal hex0
|
||||||
ESP_SIZE = 50 # MiB
|
ESP_SIZE_MIB = 50
|
||||||
QEMU = qemu-system-x86_64
|
QEMU = qemu-system-x86_64
|
||||||
OVMF_IMG = /usr/share/edk2-ovmf/OVMF_CODE.fd
|
OVMF_IMG = /usr/share/edk2-ovmf/OVMF_CODE.fd
|
||||||
|
|
||||||
ESP_SIZE_SECTORS = $$(($(ESP_SIZE) * 2048))
|
ESP_SIZE_SECTORS = $$(($(ESP_SIZE_MIB) * 2048))
|
||||||
DISK_SIZE_SECTORS=$$(($(ESP_SIZE_SECTORS) + 2048 + 33))
|
DISK_SIZE_SECTORS = $$(($(ESP_SIZE_SECTORS) + 2048 + 33))
|
||||||
|
|
||||||
cc = clang
|
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
|
ld = lld-link
|
||||||
lflags = -subsystem:efi_application -nodefaultlib -dll
|
lflags = -subsystem:efi_application -nodefaultlib -dll
|
||||||
build_dir = build
|
build_dir = build
|
||||||
|
@ -50,7 +50,8 @@ $(build_dir)/esp.img: rootfs
|
||||||
rootfs: $(targets2)
|
rootfs: $(targets2)
|
||||||
cp -R rootfs $(build_dir)
|
cp -R rootfs $(build_dir)
|
||||||
mkdir -p $(rootfs_dir)/EFI/BOOT/
|
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:
|
clean:
|
||||||
rm -rf $(build_dir)
|
rm -rf $(build_dir)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#ifndef __EFI_BOOT_TABLE_H__
|
#ifndef __EFI_BOOT_TABLE_H__
|
||||||
#define __EFI_BOOT_TABLE_H__
|
#define __EFI_BOOT_TABLE_H__
|
||||||
|
|
||||||
|
#include "device_path_protocol.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
static const uint32_t EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL = 0x00000001;
|
static const uint32_t EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL = 0x00000001;
|
||||||
|
@ -52,14 +53,13 @@ struct efi_boot_table
|
||||||
void (*unused20)();
|
void (*unused20)();
|
||||||
|
|
||||||
// Image Services
|
// Image Services
|
||||||
void (*unused21)();
|
efi_status_t (*load_image)(uint8_t, efi_handle_t, struct efi_device_path_protocol*, void *, efi_uint_t, efi_handle_t);
|
||||||
void (*unused22)();
|
efi_status_t (*start_image)(efi_handle_t, efi_uint_t *, uint16_t);
|
||||||
void (*unused23)();
|
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);
|
efi_status_t (*exit_boot_services)(efi_handle_t, efi_uint_t);
|
||||||
|
|
||||||
// Miscellaneius Services
|
// Miscellaneous Services
|
||||||
void (*unused26)();
|
void (*unused26)();
|
||||||
void (*unused27)();
|
void (*unused27)();
|
||||||
void (*unused28)();
|
void (*unused28)();
|
||||||
|
@ -94,7 +94,7 @@ struct efi_boot_table
|
||||||
// 32-bit CRC Services
|
// 32-bit CRC Services
|
||||||
void (*unused39)();
|
void (*unused39)();
|
||||||
|
|
||||||
// Miscellaneius Services (cont)
|
// Miscellaneous Services (cont)
|
||||||
void (*unused40)();
|
void (*unused40)();
|
||||||
void (*unused41)();
|
void (*unused41)();
|
||||||
void (*unused42)();
|
void (*unused42)();
|
||||||
|
|
|
@ -9,6 +9,9 @@ struct efi_device_path_protocol {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t subtype;
|
uint8_t subtype;
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
|
uint32_t memory_type;
|
||||||
|
uint64_t start_address;
|
||||||
|
uint64_t end_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __EFI_DEVICE_PATH_PROTOCOL_H__
|
#endif // __EFI_DEVICE_PATH_PROTOCOL_H__
|
||||||
|
|
|
@ -114,8 +114,8 @@ not_comment:
|
||||||
goto next_byte;
|
goto next_byte;
|
||||||
|
|
||||||
terminate:
|
terminate:
|
||||||
/* rootdir->close(fin);
|
rootdir->close(fin);
|
||||||
rootdir->close(fout); */
|
rootdir->close(fout);
|
||||||
|
|
||||||
return 0;
|
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
|
# SPDX-License-Identifier: Unlicense
|
||||||
|
|
||||||
BOOTX64 hex0_AMD64_POSIX.hex0 hex0
|
BOOTX64
|
||||||
|
|
Loading…
Reference in New Issue