blob: 7942804bfc79c0761af2a022ab37aaec99c1f43b [file] [log] [blame]
/*
* 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 !");
}