libopenbios: add PReP boot partition loader for PPC

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
This commit is contained in:
Mark Cave-Ayland 2018-05-26 20:09:22 +01:00
parent 853b59f901
commit ce43b60d61
7 changed files with 152 additions and 0 deletions

View File

@ -32,6 +32,7 @@
<option name="CONFIG_LOADER_ELF" type="boolean" value="true"/>
<option name="CONFIG_LOADER_FCODE" type="boolean" value="false"/>
<option name="CONFIG_LOADER_FORTH" type="boolean" value="false"/>
<option name="CONFIG_LOADER_PREP" type="boolean" value="true"/>
<option name="CONFIG_LOADER_XCOFF" type="boolean" value="true"/>
<!-- Filesystem Configuration -->

View File

@ -51,6 +51,7 @@ variable file-size
10 constant fcode
11 constant forth
12 constant bootcode
13 constant prep
: init-program ( -- )

View File

@ -0,0 +1,24 @@
/*
* Creation Date: <2010/03/22 18:00:00 mcayland>
* Time-stamp: <2010/03/22 18:00:00 mcayland>
*
* <prep_load.h>
*
* PReP boot partition loader
*
* Copyright (C) 2018 Mark Cave-Ayland (mark.cave-ayland@ilande.co.uk)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation
*
*/
#ifndef _H_PREPLOAD
#define _H_PREPLOAD
extern int prep_load(ihandle_t dev);
int is_prep(char *addr);
void prep_init_program(void);
#endif /* _H_PREPLOAD */

View File

@ -19,6 +19,7 @@
<object source="load.c"/>
<object source="linuxbios_info.c" condition="LINUXBIOS"/>
<object source="ofmem_common.c" condition="OFMEM"/>
<object source="prep_load.c" condition="LOADER_PREP"/>
<object source="xcoff_load.c" condition="LOADER_XCOFF"/>
<object source="video_common.c"/>
</library>

View File

@ -29,6 +29,7 @@
#include "libopenbios/elf_load.h"
#include "libopenbios/fcode_load.h"
#include "libopenbios/forth_load.h"
#include "libopenbios/prep_load.h"
#include "libopenbios/xcoff_load.h"
@ -90,6 +91,13 @@ void init_program(void)
}
#endif
#ifdef CONFIG_LOADER_PREP
if (is_prep((char *)cell2pointer(addr))) {
prep_init_program();
return;
}
#endif
}
void init_fcode_context(void)

View File

@ -45,6 +45,10 @@
#include "libopenbios/bootcode_load.h"
#endif
#ifdef CONFIG_LOADER_PREP
#include "libopenbios/prep_load.h"
#endif
struct sys_info sys_info;
void *elf_boot_notes = NULL;
@ -113,6 +117,13 @@ void load(ihandle_t dev)
}
#endif
#ifdef CONFIG_LOADER_PREP
if (prep_load(dev) != LOADER_NOT_SUPPORT) {
feval("load-state >ls.file-size @");
return;
}
#endif
/* Didn't load anything, so return zero size */
PUSH(0);
}

106
libopenbios/prep_load.c Normal file
View File

@ -0,0 +1,106 @@
/*
* 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 !");
}