prg/prg_load [ Functions ]
NAME
prg_load
SYNOPSIS
bool prg_load(const char* filename, uint32_t prev_load_addr, slots_t* slots, uint32_t* load_addr, prgerr_t* err)
FUNCTION
Loads a program from the host's local filesystem into the emulator's RAM.
After loading, the memory layout will look as follows:
+-----+----------+----------+---------+---------------+-----+
... | PRG text | PRG data | PRG BSS | PRG stack | ...
+-----+----------+----------+---------+---------------+-----+
^ ^
| |
load_addr prev_load_addr
(aka default evproc PC) (aka default evproc SP)
INPUTS
filename The name of the program file to try and load.
prev_load_addr The end of free memory.
slots A pointer to the slots_t structure, through which
we can access memory as viewed by the RISC-V processor.
load_addr Pointer to a variable that will receive the load
address of the module, if successful. If additional
modules are to be loaded, this address becomes the
prev_load_addr for the next invokation of this
function.
err Pointer to a variable that will receive an error
indication, should this function fail.
RESULT
TRUE if successful; FALSE otherwise. Check the err variable for
details.
SEE ALSO
SOURCE
{
int h = open(filename, O_RDONLY);
if (!h) {
fprintf(stderr, "K2PRG010 Failed to open \"%s\"\n", filename);
goto error_open;
}
prg_t ao;
size_t actual = read(h, &ao, sizeof(ao));
if (actual != sizeof(ao)) {
fprintf(stderr, "K2PRG011 File too small\n");
goto error_read;
}
if (ao.magic != PRG_MAGIC) {
fprintf(stderr, "K2PRG012 Header indicates wrong file format\n");
goto error_magic;
}
// How much code/data yet to read from the file
uint32_t remainder_size = ao.text_size + ao.data_size;
// Total amount of memory space required by the program
uint32_t allocation_size = remainder_size + ao.bss_size + ao.stack_size;
// Load address
uint32_t code_base = prev_load_addr - allocation_size;
fprintf(stderr, "K2PRG013 Code Base = $%08X\n", code_base);
uint8_t* load_ptr;
bool error = false;
slots_translate_address_from_virtual(
slots, code_base,
&load_ptr, &error
);
if (error) {
fprintf(stderr, "K2PRG014 Load Address Translation Failure\n");
goto error_translate;
}
actual = read(h, load_ptr, remainder_size);
if (actual < remainder_size) {
fprintf(stderr, "K2PRG015 File too small\n");
goto error_read;
}
close(h);
*load_addr = code_base;
return true;
error_translate:
*err = PRGLOAD_MEM_TRANSLATE;
goto error_;
error_magic:
*err = PRGLOAD_MAGIC;
goto error_;
error_read:
*err = PRGLOAD_ERR_TOO_SMALL;
goto error_;
error_open:
*err = PRGLOAD_FILENAME;
error_:
if (h) close(h);
return false;
}