Add hex2.c prototype.
This commit is contained in:
parent
f5a38323ef
commit
20b0450c8f
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
targets = kaem-minimal hex0
|
||||
targets = kaem-minimal hex0 hex2
|
||||
ESP_SIZE_MIB = 50
|
||||
QEMU = qemu-system-x86_64
|
||||
|
||||
|
|
|
@ -0,0 +1,404 @@
|
|||
/* SPDX-FileCopyrightText: 2022 Andrius Štikonas <andrius@stikonas.eu>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "efi/efi.h"
|
||||
|
||||
#define EOF -4
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define max_string 4096
|
||||
|
||||
typedef struct efi_file_protocol FILE;
|
||||
|
||||
struct entry
|
||||
{
|
||||
struct entry* next;
|
||||
unsigned target;
|
||||
char* name;
|
||||
};
|
||||
|
||||
/* Globals */
|
||||
FILE* output;
|
||||
struct entry* jump_table;
|
||||
int Base_Address;
|
||||
int ip;
|
||||
char* scratch;
|
||||
struct efi_boot_table *boot;
|
||||
struct efi_simple_text_output_protocol *stdout;
|
||||
char c;
|
||||
|
||||
char fgetc(FILE* fin)
|
||||
{
|
||||
uint64_t size = 1;
|
||||
fin->read(fin, &size, &c);
|
||||
if (size == 0) {
|
||||
c = EOF;
|
||||
}
|
||||
uint16_t temp;
|
||||
temp = c;
|
||||
return c;
|
||||
}
|
||||
|
||||
void* memset(void* ptr, int value, int num)
|
||||
{
|
||||
char* s;
|
||||
for(s = ptr; 0 < num; num = num - 1)
|
||||
{
|
||||
s[0] = value;
|
||||
s = s + 1;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* malloc(unsigned size)
|
||||
{
|
||||
uint16_t *pool;
|
||||
boot->allocate_pool(EFI_LOADER_DATA, size, (void **) &pool);
|
||||
return pool;
|
||||
}
|
||||
|
||||
|
||||
void* calloc(int count, int size)
|
||||
{
|
||||
void* ret = malloc(count * size);
|
||||
if(NULL == ret) return NULL;
|
||||
memset(ret, 0, (count * size));
|
||||
return ret;
|
||||
}
|
||||
|
||||
char fputc(char c, FILE* fout)
|
||||
{
|
||||
uint64_t size = 1;
|
||||
fout->write(fout, &size, &c);
|
||||
return c;
|
||||
}
|
||||
|
||||
int match(char* a, char* b)
|
||||
{
|
||||
if((NULL == a) && (NULL == b)) return TRUE;
|
||||
if(NULL == a) return FALSE;
|
||||
if(NULL == b) return FALSE;
|
||||
|
||||
int i = -1;
|
||||
do
|
||||
{
|
||||
i = i + 1;
|
||||
if(a[i] != b[i])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
} while((0 != a[i]) && (0 !=b[i]));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int in_set(int c, char* s)
|
||||
{
|
||||
/* NULL set is always false */
|
||||
if(NULL == s) return FALSE;
|
||||
|
||||
while(0 != s[0])
|
||||
{
|
||||
if(c == s[0]) return TRUE;
|
||||
s = s + 1;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
int consume_token(FILE* source_file)
|
||||
{
|
||||
int i = 0;
|
||||
int c = fgetc(source_file);
|
||||
while(!in_set(c, " \t\n>"))
|
||||
{
|
||||
scratch[i] = c;
|
||||
i = i + 1;
|
||||
c = fgetc(source_file);
|
||||
if(EOF == c) break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int Throwaway_token(FILE* source_file)
|
||||
{
|
||||
int c;
|
||||
do
|
||||
{
|
||||
c = fgetc(source_file);
|
||||
if(EOF == c) break;
|
||||
} while(!in_set(c, " \t\n>"));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int length(char* s)
|
||||
{
|
||||
int i = 0;
|
||||
while(0 != s[i]) i = i + 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
void Clear_Scratch(char* s)
|
||||
{
|
||||
do
|
||||
{
|
||||
s[0] = 0;
|
||||
s = s + 1;
|
||||
} while(0 != s[0]);
|
||||
}
|
||||
|
||||
void Copy_String(char* a, char* b)
|
||||
{
|
||||
while(0 != a[0])
|
||||
{
|
||||
b[0] = a[0];
|
||||
a = a + 1;
|
||||
b = b + 1;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned GetTarget(char* c)
|
||||
{
|
||||
struct entry* i;
|
||||
for(i = jump_table; NULL != i; i = i->next)
|
||||
{
|
||||
if(match(c, i->name))
|
||||
{
|
||||
return i->target;
|
||||
}
|
||||
}
|
||||
// fputs("Target label ", stderr);
|
||||
// fputs(c, stderr);
|
||||
// fputs(" is not valid\n", stderr);
|
||||
// exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int storeLabel(FILE* source_file, int ip)
|
||||
{
|
||||
struct entry* entry = calloc(1, sizeof(struct entry));
|
||||
|
||||
/* Ensure we have target address */
|
||||
entry->target = ip;
|
||||
|
||||
/* Prepend to list */
|
||||
entry->next = jump_table;
|
||||
jump_table = entry;
|
||||
|
||||
/* Store string */
|
||||
int c = consume_token(source_file);
|
||||
entry->name = calloc(length(scratch) + 1, sizeof(char));
|
||||
Copy_String(scratch, entry->name);
|
||||
Clear_Scratch(scratch);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void outputPointer(int displacement, int number_of_bytes)
|
||||
{
|
||||
unsigned value = displacement;
|
||||
|
||||
while(number_of_bytes > 0)
|
||||
{
|
||||
unsigned byte = value % 256;
|
||||
value = value / 256;
|
||||
fputc(byte, output);
|
||||
number_of_bytes = number_of_bytes - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Update_Pointer(char ch)
|
||||
{
|
||||
/* Calculate pointer size*/
|
||||
if(in_set(ch, "%&")) ip = ip + 4; /* Deal with % and & */
|
||||
else if(in_set(ch, "@$")) ip = ip + 2; /* Deal with @ and $ */
|
||||
else if('!' == ch) ip = ip + 1; /* Deal with ! */
|
||||
// else exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void storePointer(char ch, FILE* source_file)
|
||||
{
|
||||
/* Get string of pointer */
|
||||
Clear_Scratch(scratch);
|
||||
Update_Pointer(ch);
|
||||
int base_sep_p = consume_token(source_file);
|
||||
|
||||
/* Lookup token */
|
||||
int target = GetTarget(scratch);
|
||||
int displacement;
|
||||
|
||||
int base = ip;
|
||||
|
||||
/* Change relative base address to :<base> */
|
||||
if ('>' == base_sep_p)
|
||||
{
|
||||
Clear_Scratch(scratch);
|
||||
consume_token (source_file);
|
||||
base = GetTarget (scratch);
|
||||
|
||||
/* Force universality of behavior */
|
||||
displacement = (target - base);
|
||||
}
|
||||
else
|
||||
{
|
||||
displacement = target - base;
|
||||
}
|
||||
|
||||
/* output calculated difference */
|
||||
if('!' == ch) outputPointer(displacement, 1); /* Deal with ! */
|
||||
else if('$' == ch) outputPointer(target, 2); /* Deal with $ */
|
||||
else if('@' == ch) outputPointer(displacement, 2); /* Deal with @ */
|
||||
else if('&' == ch) outputPointer(target, 4); /* Deal with & */
|
||||
else if('%' == ch) outputPointer(displacement, 4); /* Deal with % */
|
||||
// else exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void line_Comment(FILE* source_file)
|
||||
{
|
||||
int c = fgetc(source_file);
|
||||
while(!in_set(c, "\n\r"))
|
||||
{
|
||||
if(EOF == c) break;
|
||||
c = fgetc(source_file);
|
||||
}
|
||||
}
|
||||
|
||||
int hex(int c, FILE* source_file)
|
||||
{
|
||||
if (in_set(c, "0123456789")) return (c - 48);
|
||||
else if (in_set(c, "abcdef")) return (c - 87);
|
||||
else if (in_set(c, "ABCDEF")) return (c - 55);
|
||||
else if (in_set(c, "#;")) line_Comment(source_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int hold;
|
||||
int toggle;
|
||||
void process_byte(char c, FILE* source_file, int write)
|
||||
{
|
||||
if(0 <= hex(c, source_file))
|
||||
{
|
||||
if(toggle)
|
||||
{
|
||||
if(write) fputc(((hold * 16)) + hex(c, source_file), output);
|
||||
ip = ip + 1;
|
||||
hold = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hold = hex(c, source_file);
|
||||
}
|
||||
toggle = !toggle;
|
||||
}
|
||||
}
|
||||
|
||||
void first_pass(FILE* input)
|
||||
{
|
||||
toggle = FALSE;
|
||||
int c;
|
||||
for(c = fgetc(input); EOF != c; c = fgetc(input))
|
||||
{
|
||||
/* Check for and deal with label */
|
||||
if(':' == c)
|
||||
{
|
||||
c = storeLabel(input, ip);
|
||||
}
|
||||
|
||||
/* check for and deal with relative/absolute pointers to labels */
|
||||
if(in_set(c, "!@$~%&"))
|
||||
{ /* deal with 1byte pointer !; 2byte pointers (@ and $); 3byte pointers ~; 4byte pointers (% and &) */
|
||||
Update_Pointer(c);
|
||||
c = Throwaway_token(input);
|
||||
if ('>' == c)
|
||||
{ /* deal with label>base */
|
||||
c = Throwaway_token(input);
|
||||
}
|
||||
}
|
||||
else process_byte(c, input, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void second_pass(FILE* input)
|
||||
{
|
||||
toggle = FALSE;
|
||||
hold = 0;
|
||||
|
||||
int c;
|
||||
for(c = fgetc(input); EOF != c; c = fgetc(input))
|
||||
{
|
||||
if(':' == c) c = Throwaway_token(input); /* Deal with : */
|
||||
else if(in_set(c, "!@$~%&")) storePointer(c, input); /* Deal with !, @, $, ~, % and & */
|
||||
else process_byte(c, input, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void rewind(FILE* f)
|
||||
{
|
||||
f->set_position(f, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
boot = system->boot;
|
||||
stdout = system->out;
|
||||
|
||||
/* Open Loaded Image protocol */
|
||||
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 application name */
|
||||
in = ++options;
|
||||
do {
|
||||
++options;
|
||||
} while (*options != ' ');
|
||||
*options = 0;
|
||||
out = ++options;
|
||||
|
||||
/* Get root file system */
|
||||
efi_handle_t root_device = image->device;
|
||||
boot->open_protocol(root_device, &guid2, (void **) &rootfs, image_handle, 0,
|
||||
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
|
||||
/* Get root directory */
|
||||
rootfs->open_volume(rootfs, &rootdir);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Open file for reading */
|
||||
struct efi_file_protocol *input;
|
||||
rootdir->open(rootdir, &input, in, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY);
|
||||
|
||||
jump_table = NULL;
|
||||
Base_Address = 0x00600000;
|
||||
output = fout;
|
||||
scratch = calloc(max_string + 1, sizeof(char));
|
||||
|
||||
/* Get all of the labels */
|
||||
ip = Base_Address;
|
||||
first_pass(input);
|
||||
rewind(input);
|
||||
|
||||
/* Fix all the references*/
|
||||
ip = Base_Address;
|
||||
second_pass(input);
|
||||
|
||||
input->close(input);
|
||||
output->close(output);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue