106 lines
2.3 KiB
C
106 lines
2.3 KiB
C
/*
|
|
* PReP boot partition loader
|
|
* Written by Mark Cave-Ayland 2018
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "kernel/kernel.h"
|
|
#include "libopenbios/bindings.h"
|
|
#include "libopenbios/prep_load.h"
|
|
#include "libopenbios/initprogram.h"
|
|
#include "libopenbios/sys_info.h"
|
|
#include "libc/byteorder.h"
|
|
#include "libc/diskio.h"
|
|
#include "drivers/drivers.h"
|
|
#define printf printk
|
|
#define debug printk
|
|
|
|
|
|
int
|
|
prep_load(ihandle_t dev)
|
|
{
|
|
int retval = LOADER_NOT_SUPPORT, fd, count, size;
|
|
ucell *loadbase;
|
|
unsigned char *image;
|
|
uint32_t entry_point_offset, load_image_length;
|
|
unsigned long entry;
|
|
|
|
/* Mark the saved-program-state as invalid */
|
|
feval("0 state-valid !");
|
|
|
|
fd = open_ih(dev);
|
|
if (fd == -1) {
|
|
goto out;
|
|
}
|
|
|
|
/* Default to loading at load-base */
|
|
fword("load-base");
|
|
loadbase = cell2pointer(POP());
|
|
|
|
/* Read block 2 containing the boot info */
|
|
seek_io(fd, 512);
|
|
count = read_io(fd, (void *)loadbase, 512);
|
|
if (count != 512) {
|
|
goto out;
|
|
}
|
|
|
|
entry_point_offset = __le32_to_cpu(loadbase[0]);
|
|
load_image_length = __le32_to_cpu(loadbase[1]);
|
|
|
|
/* Load the entire image */
|
|
size = 0;
|
|
image = (unsigned char *)loadbase;
|
|
entry = (uintptr_t)loadbase + entry_point_offset;
|
|
|
|
seek_io(fd, 0);
|
|
while (size < load_image_length) {
|
|
count = read_io(fd, (void *)image, 512);
|
|
if (count == -1) {
|
|
break;
|
|
}
|
|
|
|
size += count;
|
|
image += count;
|
|
}
|
|
|
|
/* If we didn't read anything, something went wrong */
|
|
if (!size) {
|
|
goto out;
|
|
}
|
|
|
|
/* Set correct size */
|
|
size = load_image_length;
|
|
|
|
/* Initialise load-state */
|
|
PUSH(entry);
|
|
feval("load-state >ls.entry !");
|
|
PUSH(size);
|
|
feval("load-state >ls.file-size !");
|
|
feval("prep load-state >ls.file-type !");
|
|
|
|
out:
|
|
close_io(fd);
|
|
return retval;
|
|
}
|
|
|
|
int
|
|
is_prep(char *addr)
|
|
{
|
|
/* PReP bootloaders are executed directly. So we'll say that something is
|
|
* PReP if the loader detected the PReP type sucessfully */
|
|
ucell filetype;
|
|
|
|
feval("load-state >ls.file-type @");
|
|
filetype = POP();
|
|
|
|
return (filetype == 0x13);
|
|
}
|
|
|
|
void
|
|
prep_init_program(void)
|
|
{
|
|
/* Entry point is already set, just need to setup the context */
|
|
arch_init_program();
|
|
|
|
feval("-1 state-valid !");
|
|
}
|