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:
parent
853b59f901
commit
ce43b60d61
|
@ -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 -->
|
||||
|
|
|
@ -51,6 +51,7 @@ variable file-size
|
|||
10 constant fcode
|
||||
11 constant forth
|
||||
12 constant bootcode
|
||||
13 constant prep
|
||||
|
||||
|
||||
: init-program ( -- )
|
||||
|
|
|
@ -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 */
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 !");
|
||||
}
|
Loading…
Reference in New Issue