stage0-uefi/Development/hex0.c

122 lines
3.0 KiB
C

/* 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"
efi_status_t efi_main(efi_handle_t image_handle, struct efi_system_table *system)
{
struct efi_loaded_image_protocol *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;
/* 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 *in;
uint16_t *out;
do {
++options;
} while (*options != ' '); /* Skip app name */
in = ++options;
do {
++options;
} while (*options != ' ');
*options = 0;
out = ++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;
rootdir->open(rootdir, &fin, in, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY);
/* Open file for writing */
struct efi_file_protocol *fout;
rootdir->open(rootdir, &fout, out, EFI_FILE_MODE_CREATE| EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);
uint8_t c;
uint64_t size;
uint8_t toggle = 0;
uint8_t hold;
next_byte:
size = 1;
fin->read(fin, &size, &c);
/* If the file ended (0 bytes read) terminate */
if (size == 0) {
goto terminate;
}
/* Check if it's a comment */
if (c == '#' || c == ';') {
goto loop;
}
goto not_comment;
loop:
fin->read(fin, &size, &c);
/* If the file ended (0 bytes read) terminate */
if (size == 0) {
goto terminate;
}
/* Check if read byte is the end of the comment (i.e. a newline character),
* in that case we continue processing */
if (c == '\n' || c == '\r') {
goto next_byte;
}
goto loop;
not_comment:
/* Check if it's a hex character:
* in the case it's not, ignores and reads next byte */
if (c >= '0' && c <= '9') {
c -= 48;
}
else if (c >= 'A' && c <= 'F') {
c -= 55;
}
else if (c >= 'a' && c <= 'f') {
c -= 87;
}
else {
goto next_byte;
}
if (!toggle) {
hold = c;
toggle = 1;
}
else {
c = (hold << 4) + c;
fout->write(fout, &size, &c);
hold = 0;
toggle = 0;
}
goto next_byte;
terminate:
/* rootdir->close(fin);
rootdir->close(fout); */
return 0;
}