freebsd-nq/sys/boot/arc/loader/main.c
2004-01-04 23:30:47 +00:00

406 lines
9.4 KiB
C

/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* Copyright (c) 1998 Doug Rabson <dfr@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stand.h>
#include <string.h>
#include <setjmp.h>
#include <sys/param.h>
#include "bootstrap.h"
#include "libarc.h"
#include "arctypes.h"
#include "arcfuncs.h"
extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
struct arc_devdesc currdev; /* our current device */
struct arch_switch archsw; /* MI/MD interface boundary */
extern char end[];
extern void halt(void);
#define ARCENV_BOOTFILE "OSLoadFilename"
static char *MemoryTypes[] = {
"MemoryExceptionBlock",
"MemorySystemBlock",
"MemoryFree",
"MemoryBad",
"MemoryLoadedProgram",
"MemoryFirmwareTemporary",
"MemoryFirmwarePermanent",
"MemoryFreeContiguous",
"MemorySpecialMemory",
"MemoryMaximum",
};
#ifdef __alpha__
#define ptob(p) ((p) << 13)
#endif
unsigned long
memsize()
{
unsigned long amount = 0;
MEMORY_DESCRIPTOR *desc;
for (desc = GetMemoryDescriptor(NULL); desc;
desc = GetMemoryDescriptor(desc)) {
printf("%s at %x-%x\n", MemoryTypes[desc->Type],
ptob(desc->BasePage),
ptob(desc->BasePage + desc->PageCount));
if (desc->Type == MemoryFree
|| desc->Type == MemoryFirmwareTemporary)
amount += (desc->PageCount << 13); /* XXX pagesize */
}
return amount;
}
static char *ConfigurationClasses[] = {
"SystemClass",
"ProcessorClass",
"CacheClass",
"AdapterClass",
"ControllerClass",
"PeripheralClass",
"MemoryClass",
"MaximumClass",
};
static char *ConfigurationTypes[] = {
"ArcSystem",
"CentralProcessor",
"FloatingPointProcessor",
"PrimaryIcache",
"PrimaryDcache",
"SecondaryIcache",
"SecondaryDcache",
"SecondaryCache",
"EisaAdapter",
"TcAdapter",
"ScsiAdapter",
"DtiAdapter",
"MultiFunctionAdapter",
"DiskController",
"TapeController",
"CdromController",
"WormController",
"SerialController",
"NetworkController",
"DisplayController",
"ParallelController",
"PointerController",
"KeyboardController",
"AudioController",
"OtherController",
"DiskPeripheral",
"FloppyDiskPeripheral",
"TapePeripheral",
"ModemPeripheral",
"MonitorPeripheral",
"PrinterPeripheral",
"PointerPeripheral",
"KeyboardPeripheral",
"TerminalPeripheral",
"OtherPeripheral",
"LinePeripheral",
"NetworkPeripheral",
"SystemMemory",
"MaximumType",
};
static char *ConfigurationTypeCodes[] = {
"ARC",
"CPU",
"FPC",
"PrimaryIcache",
"PrimaryDcache",
"SecondaryIcache",
"SecondaryDcache",
"SecondaryCache",
"eisa",
"tc",
"scsi",
"dti",
"multi",
"disk",
"tape",
"cdrom",
"worm",
"serial",
"network",
"video",
"par",
"point",
"key",
"audio",
"other",
"rdisk",
"fdisk",
"tape",
"modem",
"monitor",
"print",
"pointer",
"keyboard",
"term",
"other",
"line",
"network",
"Memory",
"MaximumType"
};
static void
indent(int level)
{
while (level--)
putchar(' ');
}
void
printconfig(unsigned int level, CONFIGURATION_COMPONENT *component)
{
CONFIGURATION_COMPONENT *child;
indent(level);
printf("%s(%s,%d)",
ConfigurationClasses[component->Class],
ConfigurationTypes[component->Type],
component->Key);
#if 1
if (component->IdentifierLength)
printf("=%d,%s\n", component->IdentifierLength,
ptr(component->Identifier));
else
putchar('\n');
#endif
getchar();
for (child = GetChild(component); child; child = GetPeer(child)) {
printconfig(level + 2, child);
}
}
void
dumpdisk(const char *name)
{
u_int32_t fd, count;
unsigned char buf[512];
int i, j;
printf("dump first sector of %s\n", name);
if (Open(name, OpenReadOnly, &fd) != ESUCCESS) {
printf("can't open disk\n");
return;
}
if (Read(fd, buf, 512, &count) != ESUCCESS) {
printf("can't read from disk\n");
Close(fd);
return;
}
for (i = 0; i < 16; i++) {
for (j = 0; j < 32; j++)
printf("%02x", buf[i*32 + j]);
putchar('\n');
}
Close(fd);
}
void
listdisks(char *path, CONFIGURATION_COMPONENT *component)
{
CONFIGURATION_COMPONENT *child;
char newpath[80];
char keybuf[20];
if (path == NULL) {
printf("\nARC disk devices:\n");
newpath[0] = '\0';
} else {
strcpy(newpath, path);
strcat(newpath, ConfigurationTypeCodes[component->Type]);
sprintf(keybuf, "(%d)", component->Key);
strcat(newpath, keybuf);
}
if (!strcmp(ConfigurationTypeCodes[component->Type], "rdisk") ||
!strcmp(ConfigurationTypeCodes[component->Type], "fdisk")) {
printf("%s\n", newpath);
}
for (child = GetChild(component); child; child = GetPeer(child)) {
listdisks(newpath, child);
}
}
static int exit_code = 0;
jmp_buf exit_env;
void
exit(int code)
{
exit_code = 0;
longjmp(exit_env, 1);
}
int
main(int argc, int argv[], int envp[])
{
int i;
char *bootfile;
if (setjmp(exit_env))
return exit_code;
/*
* Initialise the heap as early as possible. Once this is done,
* alloc() is usable. The stack is buried inside us, so this is
* safe.
*/
setheap((void *)end, (void *)(end + 512*1024));
/*
* XXX Chicken-and-egg problem; we want to have console output
* early, but some console attributes may depend on reading from
* eg. the boot device, which we can't do yet. We can use
* printf() etc. once this is done.
*/
cons_probe();
#if 0
printconfig(0, GetChild(NULL));
dumpdisk("scsi(0)disk(0)rdisk(0)partition(0)");
#endif
listdisks(NULL, GetChild(NULL));
printf("\n");
make_rpb();
/*
* Initialise the block cache
*/
bcache_init(32, 512); /* 16k XXX tune this */
/*
* March through the device switch probing for things.
*/
for (i = 0; devsw[i] != NULL; i++)
if (devsw[i]->dv_init != NULL)
(devsw[i]->dv_init)();
printf("\n");
printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
printf("Memory: %ld k\n", memsize() / 1024);
/* We're booting from an SRM disk, try to spiff this */
/* XXX presumes that biosdisk is first in devsw */
currdev.d_dev = devsw[0];
currdev.d_type = currdev.d_dev->dv_type;
currdev.d_kind.arcdisk.unit = 0;
/* XXX should be able to detect this, default to autoprobe */
currdev.d_kind.arcdisk.slice = -1;
/* default to 'a' */
currdev.d_kind.arcdisk.partition = 0;
/* Create arc-specific variables */
bootfile = GetEnvironmentVariable(ARCENV_BOOTFILE);
if (bootfile)
setenv("bootfile", bootfile, 1);
env_setenv("currdev", EV_VOLATILE,
arc_fmtdev(&currdev), arc_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE,
arc_fmtdev(&currdev), env_noset, env_nounset);
setenv("LINES", "24", 1); /* optional */
archsw.arch_autoload = arc_autoload;
archsw.arch_getdev = arc_getdev;
archsw.arch_copyin = arc_copyin;
archsw.arch_copyout = arc_copyout;
archsw.arch_readin = arc_readin;
interact(); /* doesn't return */
return 0; /* keep compiler happy */
}
COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
static int
command_reboot(int argc, char *argv[])
{
printf("Rebooting...\n");
delay(1000000);
FwReboot();
/* Note: we shouldn't get to this point! */
panic("Reboot failed!");
exit(0);
}
COMMAND_SET(quit, "quit", "exit the loader", command_quit);
static int
command_quit(int argc, char *argv[])
{
exit(0);
return(CMD_OK);
}
#if 0
COMMAND_SET(stack, "stack", "show stack usage", command_stack);
static int
command_stack(int argc, char *argv[])
{
char *cp;
for (cp = &stackbase; cp < &stacktop; cp++)
if (*cp != 0)
break;
printf("%d bytes of stack used\n", &stacktop - cp);
return(CMD_OK);
}
#endif
COMMAND_SET(heap, "heap", "show heap usage", command_heap);
static int
command_heap(int argc, char *argv[])
{
printf("heap base at %p, top at %p, used %ld\n", end, sbrk(0), sbrk(0) - end);
return(CMD_OK);
}