2e60161337
Currently, all OF-related code in the bootloader is contained in of.c. of.c also provides the platform specific things necessary to boot on an OF platform. However, there are platforms (such as PReP) which can include an OF implementation, but are not bootable as pure OF systems. For use by such platforms, this patch splits out the low-level parts of the OF code (call_prom() and various wrappers thereof) into a new oflib.c file. In addition, the code related to bootwrapper console output via OF are moved to a new ofconsole.c file. Both these files are included in the wrapper.a library where they can be used by both full-OF and partial OF platforms. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
116 lines
2.6 KiB
C
116 lines
2.6 KiB
C
/*
|
|
* Copyright (C) Paul Mackerras 1997.
|
|
*
|
|
* 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; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
#include <stdarg.h>
|
|
#include <stddef.h>
|
|
#include "types.h"
|
|
#include "elf.h"
|
|
#include "string.h"
|
|
#include "stdio.h"
|
|
#include "page.h"
|
|
#include "ops.h"
|
|
|
|
#include "of.h"
|
|
|
|
extern char _end[];
|
|
|
|
/* Value picked to match that used by yaboot */
|
|
#define PROG_START 0x01400000 /* only used on 64-bit systems */
|
|
#define RAM_END (512<<20) /* Fixme: use OF */
|
|
#define ONE_MB 0x100000
|
|
|
|
|
|
|
|
static unsigned long claim_base;
|
|
|
|
static void *of_try_claim(unsigned long size)
|
|
{
|
|
unsigned long addr = 0;
|
|
|
|
if (claim_base == 0)
|
|
claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
|
|
|
|
for(; claim_base < RAM_END; claim_base += ONE_MB) {
|
|
#ifdef DEBUG
|
|
printf(" trying: 0x%08lx\n\r", claim_base);
|
|
#endif
|
|
addr = (unsigned long)of_claim(claim_base, size, 0);
|
|
if ((void *)addr != (void *)-1)
|
|
break;
|
|
}
|
|
if (addr == 0)
|
|
return NULL;
|
|
claim_base = PAGE_ALIGN(claim_base + size);
|
|
return (void *)addr;
|
|
}
|
|
|
|
static void of_image_hdr(const void *hdr)
|
|
{
|
|
const Elf64_Ehdr *elf64 = hdr;
|
|
|
|
if (elf64->e_ident[EI_CLASS] == ELFCLASS64) {
|
|
/*
|
|
* Maintain a "magic" minimum address. This keeps some older
|
|
* firmware platforms running.
|
|
*/
|
|
if (claim_base < PROG_START)
|
|
claim_base = PROG_START;
|
|
}
|
|
}
|
|
|
|
static void *of_vmlinux_alloc(unsigned long size)
|
|
{
|
|
void *p = malloc(size);
|
|
|
|
if (!p)
|
|
fatal("Can't allocate memory for kernel image!\n\r");
|
|
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
* OF device tree routines
|
|
*/
|
|
static void *of_finddevice(const char *name)
|
|
{
|
|
return (phandle) of_call_prom("finddevice", 1, 1, name);
|
|
}
|
|
|
|
static int of_getprop(const void *phandle, const char *name, void *buf,
|
|
const int buflen)
|
|
{
|
|
return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen);
|
|
}
|
|
|
|
static int of_setprop(const void *phandle, const char *name, const void *buf,
|
|
const int buflen)
|
|
{
|
|
return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen);
|
|
}
|
|
|
|
void platform_init(unsigned long a1, unsigned long a2, void *promptr)
|
|
{
|
|
platform_ops.image_hdr = of_image_hdr;
|
|
platform_ops.malloc = of_try_claim;
|
|
platform_ops.exit = of_exit;
|
|
platform_ops.vmlinux_alloc = of_vmlinux_alloc;
|
|
|
|
dt_ops.finddevice = of_finddevice;
|
|
dt_ops.getprop = of_getprop;
|
|
dt_ops.setprop = of_setprop;
|
|
|
|
of_console_init();
|
|
|
|
of_init(promptr);
|
|
loader_info.promptr = promptr;
|
|
if (a1 && a2 && a2 != 0xdeadbeef) {
|
|
loader_info.initrd_addr = a1;
|
|
loader_info.initrd_size = a2;
|
|
}
|
|
}
|