#include <sys/endian.h>
#include <stand.h>
#include "openfirm.h"
#include "libofw.h"
#include "bootstrap.h"
#include <machine/asm.h>
#include <machine/psl.h>
#ifdef CAS
static int ppc64_autoload(void);
#endif
struct arch_switch archsw = {
.arch_getdev = ofw_getdev,
.arch_copyin = ofw_copyin,
.arch_copyout = ofw_copyout,
.arch_readin = ofw_readin,
#ifdef CAS
.arch_autoload = ppc64_autoload,
#else
.arch_autoload = ofw_autoload,
#endif
};
uint32_t acells, scells;
static char bootargs[128];
#define HEAP_SIZE 0x800000
static char heap[HEAP_SIZE];
#define OF_puts(fd, text) OF_write(fd, text, strlen(text))
static __inline register_t
mfmsr(void)
{
register_t value;
__asm __volatile ("mfmsr %0" : "=r"(value));
return (value);
}
void
init_heap(void)
{
bzero(heap, HEAP_SIZE);
setheap(heap, (void *)((uintptr_t)heap + HEAP_SIZE));
}
uint64_t
memsize(void)
{
phandle_t memoryp;
cell_t reg[24];
int i, sz;
uint64_t memsz;
memsz = 0;
memoryp = OF_instance_to_package(memory);
sz = OF_getencprop(memoryp, "reg", ®[0], sizeof(reg));
sz /= sizeof(reg[0]);
for (i = 0; i < sz; i += (acells + scells)) {
if (scells > 1)
memsz += (uint64_t)reg[i + acells] << 32;
memsz += reg[i + acells + scells - 1];
}
return (memsz);
}
#ifdef CAS
extern int ppc64_cas(void);
static int
ppc64_autoload(void)
{
const char *cas;
if ((cas = getenv("cas")) && cas[0] == '1')
if (ppc64_cas() != 0)
return (-1);
return (ofw_autoload());
}
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
static int (*openfirmware_entry)(void *);
extern int openfirmware_trampoline(void *buf, int (*cb)(void *));
static int
openfirmware_docall(void *buf)
{
return openfirmware_trampoline(buf, openfirmware_entry);
}
#endif
int
main(int (*openfirm)(void *))
{
phandle_t root;
int i;
char bootpath[64];
char *ch;
int bargc;
char **bargv;
#if BYTE_ORDER == LITTLE_ENDIAN
openfirmware_entry = openfirm;
OF_init(openfirmware_docall);
#else
OF_init(openfirm);
#endif
root = OF_finddevice("/");
scells = acells = 1;
OF_getencprop(root, "#address-cells", &acells, sizeof(acells));
OF_getencprop(root, "#size-cells", &scells, sizeof(scells));
init_heap();
cons_probe();
#ifdef CAS
setenv("cas", "1", 0);
#endif
env_setenv("currdev", EV_VOLATILE, "", gen_setcurrdev, env_nounset);
devinit();
printf("\n%s", bootprog_info);
printf("Memory: %lldKB\n", memsize() / 1024);
OF_getprop(chosen, "bootpath", bootpath, 64);
ch = strchr(bootpath, ':');
*ch = '\0';
printf("Booted from: %s\n", bootpath);
printf("\n");
OF_getprop(chosen, "bootargs", bootargs, sizeof(bootargs));
bargc = 0;
parse(&bargc, &bargv, bootargs);
if (bargc == 1)
env_setenv("currdev", EV_VOLATILE, bargv[0], gen_setcurrdev,
env_nounset);
else
env_setenv("currdev", EV_VOLATILE, bootpath,
gen_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, bootpath, env_noset,
env_nounset);
setenv("LINES", "24", 1);
if (!(mfmsr() & PSL_DR))
setenv("usefdt", "1", 1);
interact();
OF_exit();
return 0;
}
COMMAND_SET(halt, "halt", "halt the system", command_halt);
static int
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(acells);
return (CMD_OK);
}