[OpenBIOS] [PATCH 10/11] libopenbios: add PReP boot partition loader for PPC
Mark Cave-Ayland
mark.cave-ayland at ilande.co.uk
Sat May 26 21:29:55 CEST 2018
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
---
config/examples/ppc_config.xml | 1 +
forth/debugging/client.fs | 1 +
include/libopenbios/prep_load.h | 24 +++++++++
libopenbios/build.xml | 1 +
libopenbios/initprogram.c | 8 +++
libopenbios/load.c | 11 +++++
libopenbios/prep_load.c | 106 ++++++++++++++++++++++++++++++++++++++++
7 files changed, 152 insertions(+)
create mode 100644 include/libopenbios/prep_load.h
create mode 100644 libopenbios/prep_load.c
diff --git a/config/examples/ppc_config.xml b/config/examples/ppc_config.xml
index 0ac3817..3112ea5 100644
--- a/config/examples/ppc_config.xml
+++ b/config/examples/ppc_config.xml
@@ -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 -->
diff --git a/forth/debugging/client.fs b/forth/debugging/client.fs
index c8cd5b6..5ee6003 100644
--- a/forth/debugging/client.fs
+++ b/forth/debugging/client.fs
@@ -51,6 +51,7 @@ variable file-size
10 constant fcode
11 constant forth
12 constant bootcode
+13 constant prep
: init-program ( -- )
diff --git a/include/libopenbios/prep_load.h b/include/libopenbios/prep_load.h
new file mode 100644
index 0000000..ed1882e
--- /dev/null
+++ b/include/libopenbios/prep_load.h
@@ -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 at 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 */
diff --git a/libopenbios/build.xml b/libopenbios/build.xml
index feb8f6c..0c89110 100644
--- a/libopenbios/build.xml
+++ b/libopenbios/build.xml
@@ -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>
diff --git a/libopenbios/initprogram.c b/libopenbios/initprogram.c
index ffd3254..3213378 100644
--- a/libopenbios/initprogram.c
+++ b/libopenbios/initprogram.c
@@ -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)
diff --git a/libopenbios/load.c b/libopenbios/load.c
index 174d221..16dc74a 100644
--- a/libopenbios/load.c
+++ b/libopenbios/load.c
@@ -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);
}
diff --git a/libopenbios/prep_load.c b/libopenbios/prep_load.c
new file mode 100644
index 0000000..7942804
--- /dev/null
+++ b/libopenbios/prep_load.c
@@ -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 !");
+}
--
2.11.0
More information about the OpenBIOS
mailing list