summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbenno <benno@FreeBSD.org>2001-10-07 13:22:25 +0000
committerbenno <benno@FreeBSD.org>2001-10-07 13:22:25 +0000
commit994f7977f13d1c6ac31ef785fbbc104972efe7b3 (patch)
treee41d72af3d7b410a29de1cb1506f5f96b1102823
parentc0f87bdb1611f3ab744711a34cfc945ccc336830 (diff)
downloadFreeBSD-src-994f7977f13d1c6ac31ef785fbbc104972efe7b3.zip
FreeBSD-src-994f7977f13d1c6ac31ef785fbbc104972efe7b3.tar.gz
Mega-patch for OpenFirmware loader support.
- Flesh out ofw_readin routine. - Add OpenFirmware load and exec routines. - Make sure memory allocation for the kernel is done correctly. - Change the way the heap is allocated so as to make it easier to deallocate when we hand over. - Add a command to print memory maps similar to the one for ia64. With this patch, I can now load and hand over to a kernel on my iMac. There are some problems with OpenFirmware routines failing after the hand over that still need to be addressed.
-rw-r--r--sys/boot/ofw/common/main.c47
-rw-r--r--sys/boot/ofw/libofw/Makefile5
-rw-r--r--sys/boot/ofw/libofw/libofw.h18
-rw-r--r--sys/boot/ofw/libofw/ofw_copy.c33
-rw-r--r--sys/boot/ofw/libofw/ofw_net.c16
-rw-r--r--sys/boot/ofw/libofw/openfirm.c21
-rw-r--r--sys/boot/ofw/libofw/openfirm.h2
-rw-r--r--sys/boot/powerpc/loader/Makefile6
-rw-r--r--sys/boot/powerpc/loader/conf.c10
-rw-r--r--sys/boot/powerpc/loader/start.c8
-rw-r--r--sys/boot/powerpc/ofw/Makefile6
-rw-r--r--sys/boot/powerpc/ofw/conf.c10
-rw-r--r--sys/boot/powerpc/ofw/start.c8
13 files changed, 135 insertions, 55 deletions
diff --git a/sys/boot/ofw/common/main.c b/sys/boot/ofw/common/main.c
index d9f3fd1..9348135 100644
--- a/sys/boot/ofw/common/main.c
+++ b/sys/boot/ofw/common/main.c
@@ -41,48 +41,30 @@ extern char bootprog_rev[];
extern char bootprog_date[];
extern char bootprog_maker[];
-struct ofw_reg
-{
- uint32_t base;
- uint32_t size;
-};
+phandle_t chosen;
+
+#define HEAP_SIZE 0x40000
void
init_heap(void)
{
- ihandle_t meminstance;
- phandle_t chosen, memory;
- struct ofw_reg available;
- void * aligned_end;
+ void *base;
- chosen = OF_finddevice("/chosen");
- OF_getprop(chosen, "memory", &meminstance, sizeof(meminstance));
- memory = OF_instance_to_package(meminstance);
- OF_getprop(memory, "available", &available, sizeof(available));
- printf("available.base = 0x%08x\n", available.base);
- printf("available.size = 0x%08x\n", available.size);
-
- if (OF_claim((void *)available.base, 0x00040000, 0) ==
- (void *) 0xffffffff) {
+ if ((base = ofw_alloc_heap(HEAP_SIZE)) == (void *)0xffffffff) {
printf("Heap memory claim failed!\n");
OF_enter();
}
- aligned_end = (void *)(((int)end + sizeof(int) - 1) &
- ~(sizeof(int) - 1));
- printf("end = 0x%08x, aligned_end = 0x%08x\n", (uint32_t)end,
- (uint32_t)aligned_end);
- setheap((void *)aligned_end, (void *)(available.base + available.size));
+ setheap(base, base + (HEAP_SIZE / sizeof(base)));
}
uint32_t
memsize(void)
{
ihandle_t meminstance;
- phandle_t chosen, memory;
+ phandle_t memory;
struct ofw_reg reg;
- chosen = OF_finddevice("/chosen");
OF_getprop(chosen, "memory", &meminstance, sizeof(meminstance));
memory = OF_instance_to_package(meminstance);
@@ -95,7 +77,6 @@ int
main(int (*openfirm)(void *))
{
int i;
- phandle_t chosen;
char bootpath[64];
char *ch;
@@ -104,6 +85,8 @@ main(int (*openfirm)(void *))
*/
OF_init(openfirm);
+ chosen = OF_finddevice("/chosen");
+
/*
* Set up console.
*/
@@ -133,7 +116,6 @@ main(int (*openfirm)(void *))
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
printf("Memory: %dKB\n", memsize() / 1024);
- chosen = OF_finddevice("/chosen");
OF_getprop(chosen, "bootpath", bootpath, 64);
ch = index(bootpath, ':');
*ch = '\0';
@@ -183,6 +165,7 @@ main(int (*openfirm)(void *))
archsw.arch_copyin = ofw_copyin;
archsw.arch_copyout = ofw_copyout;
archsw.arch_readin = ofw_readin;
+ archsw.arch_autoload = ofw_autoload;
interact(); /* doesn't return */
@@ -200,3 +183,13 @@ command_halt(int argc, char *argv[])
OF_exit();
return (CMD_OK);
}
+
+COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
+
+int
+command_memmap(int argc, char **argv)
+{
+
+ ofw_memmap();
+ return (CMD_OK);
+}
diff --git a/sys/boot/ofw/libofw/Makefile b/sys/boot/ofw/libofw/Makefile
index 5126ef1..0cd0cf1 100644
--- a/sys/boot/ofw/libofw/Makefile
+++ b/sys/boot/ofw/libofw/Makefile
@@ -6,8 +6,9 @@ NOPROFILE= true
INTERNALLIB= true
INTERNALSTATICLIB= true
-SRCS= devicename.c ofw_copy.c ofw_module.c ofw_disk.c ofw_net.c \
- ofw_console.c ofw_time.c ofw_devsearch.c ofw_reboot.c openfirm.c
+SRCS= devicename.c elf_freebsd.c ofw_console.c ofw_copy.c ofw_devsearch.c \
+ ofw_disk.c ofw_memory.c ofw_module.c ofw_net.c ofw_reboot.c \
+ ofw_time.c openfirm.c
CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
diff --git a/sys/boot/ofw/libofw/libofw.h b/sys/boot/ofw/libofw/libofw.h
index e564417..dcb0b0e 100644
--- a/sys/boot/ofw/libofw/libofw.h
+++ b/sys/boot/ofw/libofw/libofw.h
@@ -82,6 +82,24 @@ int ofw_devicetype(char *);
extern int ofw_boot(void);
extern int ofw_autoload(void);
+void ofw_memmap(void);
+void *ofw_alloc_heap(unsigned int);
+void ofw_release_heap(void);
+
+struct preloaded_file;
+struct file_format;
+
+int ofw_elf_loadfile(char *, vm_offset_t, struct preloaded_file **);
+int ofw_elf_exec(struct preloaded_file *);
+
+extern struct file_format ofw_elf;
+
extern void reboot(void);
extern int main(int (*openfirm)(void *));
+
+struct ofw_reg
+{
+ uint32_t base;
+ uint32_t size;
+};
diff --git a/sys/boot/ofw/libofw/ofw_copy.c b/sys/boot/ofw/libofw/ofw_copy.c
index ecfb8e6..1ae37c7 100644
--- a/sys/boot/ofw/libofw/ofw_copy.c
+++ b/sys/boot/ofw/libofw/ofw_copy.c
@@ -34,6 +34,8 @@
#include "libofw.h"
+#define READIN_BUF (4 * 1024)
+
ssize_t
ofw_copyin(const void *src, vm_offset_t dest, const size_t len)
{
@@ -51,7 +53,32 @@ ofw_copyout(const vm_offset_t src, void *dest, const size_t len)
ssize_t
ofw_readin(const int fd, vm_offset_t dest, const size_t len)
{
- return(read(fd, (void *) dest, len));
-}
+ void *buf;
+ size_t resid, chunk, get;
+ ssize_t got;
+ vm_offset_t p;
+
+ p = dest;
+
+ chunk = min(READIN_BUF, len);
+ buf = malloc(chunk);
+ if (buf == NULL) {
+ printf("ofw_readin: buf malloc failed\n");
+ return(0);
+ }
-
+ for (resid = len; resid > 0; resid -= got, p += got) {
+ get = min(chunk, resid);
+ got = read(fd, buf, get);
+
+ if (got <= 0) {
+ printf("ofw_readin: read failed\n");
+ break;
+ }
+
+ bcopy(buf, (void *)p, got);
+ }
+
+ free(buf);
+ return(len - resid);
+}
diff --git a/sys/boot/ofw/libofw/ofw_net.c b/sys/boot/ofw/libofw/ofw_net.c
index 11c8dab..712a457 100644
--- a/sys/boot/ofw/libofw/ofw_net.c
+++ b/sys/boot/ofw/libofw/ofw_net.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000 Benno Rice
+ * Copyright (c) 2000-2001 Benno Rice
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,8 +45,8 @@
static int ofwn_probe(struct netif *, void *);
static int ofwn_match(struct netif *, void *);
static void ofwn_init(struct iodesc *, void *);
-static int ofwn_get(struct iodesc *, void *, int, time_t);
-static int ofwn_put(struct iodesc *, void *, int);
+static int ofwn_get(struct iodesc *, void *, size_t, time_t);
+static int ofwn_put(struct iodesc *, void *, size_t);
static void ofwn_end(struct netif *);
extern struct netif_stats ofwn_stats[];
@@ -89,7 +89,7 @@ ofwn_probe(struct netif *nif, void *machdep_hint)
}
static int
-ofwn_put(struct iodesc *desc, void *pkt, int len)
+ofwn_put(struct iodesc *desc, void *pkt, size_t len)
{
struct ether_header *eh;
size_t sendlen;
@@ -126,7 +126,7 @@ ofwn_put(struct iodesc *desc, void *pkt, int len)
}
static int
-ofwn_get(struct iodesc *desc, void *pkt, int len, time_t timeout)
+ofwn_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout)
{
time_t t;
int length;
@@ -196,8 +196,10 @@ ofwn_init(struct iodesc *desc, void *machdep_hint)
printf("boot: ethernet address: %s\n", ether_sprintf(desc->myea));
- if ((netinstance = OF_open(path)) == -1)
+ if ((netinstance = OF_open(path)) == -1) {
+ printf("Could not open network device.\n");
goto punt;
+ }
#if defined(NETIF_DEBUG)
printf("ofwn_init: OpenFirmware instance handle: %08x\n", netinstance);
@@ -218,7 +220,7 @@ ofwn_init(struct iodesc *desc, void *machdep_hint)
punt:
printf("\n");
printf("Could not boot from %s.\n", path);
- OF_exit();
+ OF_enter();
}
static void
diff --git a/sys/boot/ofw/libofw/openfirm.c b/sys/boot/ofw/libofw/openfirm.c
index 365358e..70f0988 100644
--- a/sys/boot/ofw/libofw/openfirm.c
+++ b/sys/boot/ofw/libofw/openfirm.c
@@ -67,12 +67,25 @@ static int (*openfirmware)(void *);
static ihandle_t stdin;
static ihandle_t stdout;
+static ihandle_t mmu;
+static ihandle_t memory;
+
/* Initialiaser */
void
OF_init(int (*openfirm)(void *))
{
+ phandle_t chosen;
+
openfirmware = openfirm;
+
+ chosen = OF_finddevice("/chosen");
+ OF_getprop(chosen, "memory", &memory, sizeof(memory));
+ if (memory == 0)
+ panic("failed to get memory ihandle");
+ OF_getprop(chosen, "mmu", &mmu, sizeof(mmu));
+ if (mmu == 0)
+ panic("failed to get mmu ihandle");
}
/*
@@ -706,7 +719,7 @@ OF_exit()
}
/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
-#ifdef __notyet__
+#if 0
void
OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
{
@@ -739,9 +752,9 @@ OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
/*
* This is a REALLY dirty hack till the firmware gets this going
*/
-#if 0
- OF_release(virt, size);
-#endif
+ if (size > 0)
+ OF_release(virt, size);
+
entry(0, 0, openfirmware, arg, len);
}
#endif
diff --git a/sys/boot/ofw/libofw/openfirm.h b/sys/boot/ofw/libofw/openfirm.h
index 5ee672a..4bee076 100644
--- a/sys/boot/ofw/libofw/openfirm.h
+++ b/sys/boot/ofw/libofw/openfirm.h
@@ -67,6 +67,8 @@
typedef int ihandle_t;
typedef int phandle_t;
+extern phandle_t chosen;
+
/*
* This isn't actually an OpenFirmware function, but it seemed like the right
* place for it to go.
diff --git a/sys/boot/powerpc/loader/Makefile b/sys/boot/powerpc/loader/Makefile
index cd8ccaf..045f190 100644
--- a/sys/boot/powerpc/loader/Makefile
+++ b/sys/boot/powerpc/loader/Makefile
@@ -11,6 +11,10 @@ INSTALLFLAGS= -b
LOADER_DISK_SUPPORT?= yes
LOADER_NET_SUPPORT?= yes
+# load address
+RELOC?= 0x6c0000
+CFLAGS+= -DRELOC=${RELOC}
+
# architecture-specific loader code
SRCS= conf.c
@@ -45,7 +49,7 @@ CFLAGS+= -I${.CURDIR}/../../.. -I.
CLEANFILES+= vers.c vers.o ${BASE}.list ${BASE}.bin ${BASE}.sym ${BASE}.help
CFLAGS+= -Wall
-LDFLAGS= -nostdlib -static -Ttext 6c0000
+LDFLAGS= -nostdlib -static -Ttext ${RELOC}
# OpenFirmware standalone support library
LIBOFW= ${.OBJDIR}/../../ofw/libofw/libofw.a
diff --git a/sys/boot/powerpc/loader/conf.c b/sys/boot/powerpc/loader/conf.c
index 81ccbe7..273815a 100644
--- a/sys/boot/powerpc/loader/conf.c
+++ b/sys/boot/powerpc/loader/conf.c
@@ -27,7 +27,9 @@
*/
#include <stand.h>
+#include "bootstrap.h"
#include "libofw.h"
+#include "openfirm.h"
#if defined(LOADER_NET_SUPPORT)
#include "dev_net.h"
@@ -82,10 +84,9 @@ struct netif_driver *netif_drivers[] = {
* Sort formats so that those that can detect based on arguments
* rather than reading the file go first.
*/
-extern struct file_format powerpc_elf;
struct file_format *file_formats[] = {
-/* &powerpc_elf,*/
+ &ofw_elf,
NULL
};
@@ -101,3 +102,8 @@ struct console *consoles[] = {
&ofwconsole,
NULL
};
+
+/*
+ * reloc - our load address
+ */
+vm_offset_t reloc = RELOC;
diff --git a/sys/boot/powerpc/loader/start.c b/sys/boot/powerpc/loader/start.c
index a9aef2a..9f37ce0 100644
--- a/sys/boot/powerpc/loader/start.c
+++ b/sys/boot/powerpc/loader/start.c
@@ -37,8 +37,6 @@
void startup(void *, int, int (*)(void *), char *, int);
-static int stack[8192/4 + 4];
-
#ifdef XCOFF_GLUE
asm("
.text
@@ -48,7 +46,11 @@ _entry:
");
#endif
-asm("
+__asm("
+ .data
+stack:
+ .space 16388
+
.text
.globl _start
_start:
diff --git a/sys/boot/powerpc/ofw/Makefile b/sys/boot/powerpc/ofw/Makefile
index cd8ccaf..045f190 100644
--- a/sys/boot/powerpc/ofw/Makefile
+++ b/sys/boot/powerpc/ofw/Makefile
@@ -11,6 +11,10 @@ INSTALLFLAGS= -b
LOADER_DISK_SUPPORT?= yes
LOADER_NET_SUPPORT?= yes
+# load address
+RELOC?= 0x6c0000
+CFLAGS+= -DRELOC=${RELOC}
+
# architecture-specific loader code
SRCS= conf.c
@@ -45,7 +49,7 @@ CFLAGS+= -I${.CURDIR}/../../.. -I.
CLEANFILES+= vers.c vers.o ${BASE}.list ${BASE}.bin ${BASE}.sym ${BASE}.help
CFLAGS+= -Wall
-LDFLAGS= -nostdlib -static -Ttext 6c0000
+LDFLAGS= -nostdlib -static -Ttext ${RELOC}
# OpenFirmware standalone support library
LIBOFW= ${.OBJDIR}/../../ofw/libofw/libofw.a
diff --git a/sys/boot/powerpc/ofw/conf.c b/sys/boot/powerpc/ofw/conf.c
index 81ccbe7..273815a 100644
--- a/sys/boot/powerpc/ofw/conf.c
+++ b/sys/boot/powerpc/ofw/conf.c
@@ -27,7 +27,9 @@
*/
#include <stand.h>
+#include "bootstrap.h"
#include "libofw.h"
+#include "openfirm.h"
#if defined(LOADER_NET_SUPPORT)
#include "dev_net.h"
@@ -82,10 +84,9 @@ struct netif_driver *netif_drivers[] = {
* Sort formats so that those that can detect based on arguments
* rather than reading the file go first.
*/
-extern struct file_format powerpc_elf;
struct file_format *file_formats[] = {
-/* &powerpc_elf,*/
+ &ofw_elf,
NULL
};
@@ -101,3 +102,8 @@ struct console *consoles[] = {
&ofwconsole,
NULL
};
+
+/*
+ * reloc - our load address
+ */
+vm_offset_t reloc = RELOC;
diff --git a/sys/boot/powerpc/ofw/start.c b/sys/boot/powerpc/ofw/start.c
index a9aef2a..9f37ce0 100644
--- a/sys/boot/powerpc/ofw/start.c
+++ b/sys/boot/powerpc/ofw/start.c
@@ -37,8 +37,6 @@
void startup(void *, int, int (*)(void *), char *, int);
-static int stack[8192/4 + 4];
-
#ifdef XCOFF_GLUE
asm("
.text
@@ -48,7 +46,11 @@ _entry:
");
#endif
-asm("
+__asm("
+ .data
+stack:
+ .space 16388
+
.text
.globl _start
_start:
OpenPOWER on IntegriCloud