/*- * Copyright (c) 1998 Michael Smith * Copyright (c) 1998 Doug Rabson * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #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); }