From 587e8f4925ec4263bdfe257d261e45ee543a5994 Mon Sep 17 00:00:00 2001 From: benno Date: Sun, 7 Oct 2001 13:22:25 +0000 Subject: [PATCH] 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. --- sys/boot/ofw/common/main.c | 47 ++++++++++++++------------------ sys/boot/ofw/libofw/Makefile | 5 ++-- sys/boot/ofw/libofw/libofw.h | 18 ++++++++++++ sys/boot/ofw/libofw/ofw_copy.c | 33 ++++++++++++++++++++-- sys/boot/ofw/libofw/ofw_net.c | 16 ++++++----- sys/boot/ofw/libofw/openfirm.c | 21 +++++++++++--- sys/boot/ofw/libofw/openfirm.h | 2 ++ sys/boot/powerpc/loader/Makefile | 6 +++- sys/boot/powerpc/loader/conf.c | 10 +++++-- sys/boot/powerpc/loader/start.c | 8 ++++-- sys/boot/powerpc/ofw/Makefile | 6 +++- sys/boot/powerpc/ofw/conf.c | 10 +++++-- sys/boot/powerpc/ofw/start.c | 8 ++++-- 13 files changed, 135 insertions(+), 55 deletions(-) diff --git a/sys/boot/ofw/common/main.c b/sys/boot/ofw/common/main.c index d9f3fd1b832b..93481352dcdd 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 5126ef1c5f08..0cd0cf10f2f2 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 e564417ab033..dcb0b0e6e958 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 ecfb8e6b5498..1ae37c764c96 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 11c8daba403b..712a4572232b 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 365358e9163c..70f0988beb4c 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 bytes starting at , then call with . */ -#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 5ee672a02f38..4bee076a517d 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 cd8ccaffe1e4..045f19070225 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 81ccbe7615b8..273815a692b5 100644 --- a/sys/boot/powerpc/loader/conf.c +++ b/sys/boot/powerpc/loader/conf.c @@ -27,7 +27,9 @@ */ #include +#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 a9aef2ae9724..9f37ce0027c6 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 @@ asm(" "); #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 cd8ccaffe1e4..045f19070225 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 81ccbe7615b8..273815a692b5 100644 --- a/sys/boot/powerpc/ofw/conf.c +++ b/sys/boot/powerpc/ofw/conf.c @@ -27,7 +27,9 @@ */ #include +#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 a9aef2ae9724..9f37ce0027c6 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 @@ asm(" "); #endif -asm(" +__asm(" + .data +stack: + .space 16388 + .text .globl _start _start: