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.
This commit is contained in:
parent
f2eeb19063
commit
cae2c81dc2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=84617
@ -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);
|
||||
}
|
||||
|
@ -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/
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user