407 lines
9.8 KiB
C
407 lines
9.8 KiB
C
/* $NetBSD: boot.c,v 1.7 2008/07/16 14:45:17 tsutsui Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 2004 The NetBSD Foundation, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
|
* by UCHIYAMA Yasushi.
|
|
*
|
|
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <lib/libsa/stand.h>
|
|
#include <lib/libkern/libkern.h>
|
|
|
|
#include "local.h"
|
|
#include "cmd.h"
|
|
#include "common.h"
|
|
|
|
#include <machine/sbd.h>
|
|
#include <machine/pdinfo.h>
|
|
#include <machine/vtoc.h>
|
|
|
|
#include "console.h"
|
|
|
|
|
|
extern const char bootprog_name[];
|
|
extern const char bootprog_rev[];
|
|
extern const char bootprog_kernrev[];
|
|
|
|
struct cmd_batch_tab cmd_batch_tab[] = {
|
|
/* func argc argp... */
|
|
#if 0
|
|
{ cmd_boot, 1, { "mem:", 0, 0, 0, 0, 0, 0 } },
|
|
{ cmd_boot, 1, { "sd0k:netbsd", 0, 0, 0, 0, 0, 0 } },
|
|
{ cmd_load_binary, 1, { "0x80001000", 0, 0, 0, 0, 0, 0 } },
|
|
{ cmd_jump, 2, { "0x80001000", "0x80001000", 0, 0, 0, 0, 0 } },
|
|
#endif
|
|
{ NULL, 0, { 0, 0, 0, 0, 0, 0, 0 } } /* terminate */
|
|
};
|
|
|
|
struct ipl_args ipl_args;
|
|
struct device_capability DEVICE_CAPABILITY;
|
|
void set_device_capability(void);
|
|
bool guess_boot_kernel(char *, size_t, int);
|
|
extern int kernel_binary_size;
|
|
|
|
void
|
|
main(int a0, int v0, int v1)
|
|
{
|
|
extern char edata[], end[];
|
|
char boot_kernel[32];
|
|
char *args[CMDARG_MAX];
|
|
int i;
|
|
|
|
memset(edata, 0, end - edata);
|
|
/* Save args for chain-boot to iopboot */
|
|
ipl_args.a0 = a0;
|
|
ipl_args.v0 = v0;
|
|
ipl_args.v1 = v1;
|
|
|
|
console_init();
|
|
|
|
printf("\n");
|
|
printf("%s boot, Revision %s (from NetBSD %s)\n",
|
|
bootprog_name, bootprog_rev, bootprog_kernrev);
|
|
|
|
|
|
/* Inquire IPL activated device */
|
|
set_device_capability();
|
|
|
|
if (!guess_boot_kernel(boot_kernel, sizeof boot_kernel, 0))
|
|
goto prompt;
|
|
printf(
|
|
">> Press return to boot now, any other key for boot console.\n");
|
|
|
|
for (i = 5000; i >= 0; i--) {
|
|
int c;
|
|
if (i % 1000 == 0)
|
|
printf("booting %s - starting %d\r",
|
|
boot_kernel, i / 1000);
|
|
if ((c = cnscan()) == -1) {
|
|
delay(10);
|
|
continue;
|
|
}
|
|
else if (c == '\r')
|
|
break;
|
|
else
|
|
goto prompt;
|
|
}
|
|
printf("\n[non-interactive mode]\n");
|
|
args[0] = "boot";
|
|
args[1] = boot_kernel;
|
|
cmd_boot(2, args, false);
|
|
prompt:
|
|
|
|
printf("\ntype \"help\" for help.\n");
|
|
console_cursor(true);
|
|
prompt();
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
bool
|
|
guess_boot_kernel(char *name, size_t len, int pri)
|
|
{
|
|
extern struct vtoc_sector vtoc;
|
|
struct ux_partition *partition;
|
|
int i, unit;
|
|
|
|
if (!DEVICE_CAPABILITY.active)
|
|
return false;
|
|
|
|
unit = DEVICE_CAPABILITY.booted_unit;
|
|
|
|
switch (DEVICE_CAPABILITY.booted_device) {
|
|
default:
|
|
return false;
|
|
case NVSRAM_BOOTDEV_FLOPPYDISK:
|
|
strncpy(name, "fd:netbsd", len); /* ustarfs */
|
|
return true;
|
|
|
|
case NVSRAM_BOOTDEV_HARDDISK:
|
|
snprintf(name, len, "sd%d:netbsd", unit); /* ustarfs */
|
|
if (!read_vtoc())
|
|
return true;
|
|
|
|
partition = vtoc.partition;
|
|
for (i = 0; i < VTOC_MAXPARTITIONS; i++, partition++) {
|
|
if (partition->tag != __VTOC_TAG_BSDFFS)
|
|
continue;
|
|
/* ffs */
|
|
snprintf(name, len, "sd%d%c:netbsd", unit, 'a' + i);
|
|
return true;
|
|
}
|
|
return true;
|
|
|
|
case NVSRAM_BOOTDEV_CGMT:
|
|
break;
|
|
case NVSRAM_BOOTDEV_NETWORK:
|
|
/*FALLTHROUGH*/
|
|
case NVSRAM_BOOTDEV_NETWORK_T_AND_D:
|
|
if (kernel_binary_size) {
|
|
strncpy(name, "mem:", len); /* datafs */
|
|
return true;
|
|
}
|
|
if (DEVICE_CAPABILITY.network_enabled) {
|
|
strncpy(name, "nfs:netbsd", len); /* nfs */
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int
|
|
cmd_info(int argc, char *argp[], int interactive)
|
|
{
|
|
extern char _ftext[], _etext[], _fdata[], _edata[];
|
|
extern char _fbss[], end[];
|
|
uint32_t m;
|
|
int i, size, total;
|
|
struct sbdinfo *sbd = SBD_INFO;
|
|
|
|
printf("\n>> %s boot, Revision %s (from NetBSD %s) <<\n",
|
|
bootprog_name, bootprog_rev, bootprog_kernrev);
|
|
|
|
printf("IPL args: 0x%x 0x%x 0x%x\n", ipl_args.a0, ipl_args.v0,
|
|
ipl_args.v1);
|
|
printf("\ttext : %p-%p\n\tdata : %p-%p\n\t"
|
|
"bss : %p-%p\n\tstack: %p\n\theap : %p\n",
|
|
_ftext, _etext, _fdata, _edata,
|
|
_fbss, end, _ftext, end);
|
|
|
|
m = ipl_args.v1;
|
|
total = 0;
|
|
printf("Memory Area:\n\t");
|
|
for (i = 0; i < 8; i++, m >>= 4) {
|
|
size = m & 0xf ? ((m & 0xf) << 4) : 0;
|
|
total += size;
|
|
if (size)
|
|
printf("M%d=%dMB ", i, size);
|
|
}
|
|
printf(" total %dMB\n", total);
|
|
|
|
printf("Board Revision:\n");
|
|
printf("\tmachine=0x%x, ", sbd->machine);
|
|
printf("model=0x%x\n", sbd->model);
|
|
printf("\tpmmu=%d, ", sbd->mmu);
|
|
printf("cache=%d, ", sbd->cache);
|
|
printf("panel=%d, ", sbd->panel);
|
|
printf("fdd=%d\n", sbd->fdd);
|
|
printf("\tcpu=%d, fpp=%d, fpa=%d, iop=%d\n",
|
|
sbd->cpu, sbd->fpp, sbd->fpa, sbd->iop);
|
|
printf("\tclock=%d\n", sbd->clock);
|
|
printf("\tipl=%d, cpu_ex=%d, fpp_ex=%d\n",
|
|
sbd->ipl, sbd->cpu_ex, sbd->fpp_ex);
|
|
printf("\tkbms=%d, sio=%d, battery=%d, scsi=%d\n",
|
|
sbd->kbms, sbd->sio, sbd->battery, sbd->scsi);
|
|
printf("model name=%s\n", sbd->model_name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
cmd_reboot(int argc, char *argp[], int interactive)
|
|
{
|
|
int bootdev = -1;
|
|
|
|
if (argc > 1)
|
|
bootdev = strtoul(argp[1], 0, 0); /* next boot device. */
|
|
if (bootdev != NVSRAM_BOOTDEV_FLOPPYDISK &&
|
|
bootdev != NVSRAM_BOOTDEV_HARDDISK &&
|
|
bootdev != NVSRAM_BOOTDEV_CGMT &&
|
|
bootdev != NVSRAM_BOOTDEV_NETWORK) {
|
|
printf("invalid boot device.");
|
|
bootdev = -1;
|
|
}
|
|
|
|
switch (SBD_INFO->machine) {
|
|
case MACHINE_TR2A:
|
|
if (bootdev != -1)
|
|
*(uint8_t *)0xbe493030 = bootdev;
|
|
*(volatile uint32_t *)0xbe000064 |= 0x80000000;
|
|
*(volatile uint8_t *)0xba000004 = 1;
|
|
*(uint8_t *)0xbfbffffc = 255;
|
|
break;
|
|
case MACHINE_TR2:
|
|
if (bootdev != -1)
|
|
*(uint8_t *)0xbb023030 = bootdev;
|
|
*(volatile uint32_t *)0xbfb00000 |= 0x10;
|
|
break;
|
|
default:
|
|
ROM_MONITOR();
|
|
}
|
|
|
|
while (/*CONSTCOND*/1)
|
|
;
|
|
/* NOTREACHED */
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
set_device_capability(void)
|
|
{
|
|
const char *devname[] = {
|
|
"Floppy disk",
|
|
"Unknown",
|
|
"Hard disk",
|
|
"Unknown",
|
|
"CGMT",
|
|
"Unknown",
|
|
"Network",
|
|
"Unknown",
|
|
"Network T&D"
|
|
};
|
|
int booted_device, booted_unit, fd_format;
|
|
|
|
boot_device(&booted_device, &booted_unit, &fd_format);
|
|
if (booted_device > NVSRAM_BOOTDEV_MAX ||
|
|
booted_device < NVSRAM_BOOTDEV_MIN) {
|
|
printf(
|
|
"invalid booted device. NVSRAM information isn't valid\n");
|
|
} else {
|
|
DEVICE_CAPABILITY.booted_device = booted_device;
|
|
}
|
|
DEVICE_CAPABILITY.booted_unit = booted_unit;
|
|
|
|
switch (SBD_INFO->machine) {
|
|
case MACHINE_TR2A:
|
|
DEVICE_CAPABILITY.active = true;
|
|
/* boot has LANCE driver */
|
|
DEVICE_CAPABILITY.network_enabled = true;
|
|
break;
|
|
case MACHINE_TR2:
|
|
DEVICE_CAPABILITY.active = true;
|
|
break;
|
|
default:
|
|
DEVICE_CAPABILITY.active = false;
|
|
break;
|
|
}
|
|
|
|
DEVICE_CAPABILITY.fd_enabled = true; /* always enabled */
|
|
|
|
if (DEVICE_CAPABILITY.active) {
|
|
/*
|
|
* When NETWORK IPL, FD IPL doesn't activate ROM DISK routine.
|
|
*/
|
|
if (DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_HARDDISK)
|
|
DEVICE_CAPABILITY.disk_enabled = true;
|
|
}
|
|
|
|
printf("FD[%c] DISK[%c] NETWORK[%c] COMPILED[%c]\n",
|
|
DEVICE_CAPABILITY.fd_enabled ? 'x' : '_',
|
|
DEVICE_CAPABILITY.disk_enabled ? 'x' : '_',
|
|
DEVICE_CAPABILITY.network_enabled ? 'x' : '_',
|
|
kernel_binary_size ? 'x' : '_');
|
|
|
|
printf("booted from %s IPL", devname[DEVICE_CAPABILITY.booted_device]);
|
|
if ((DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_NETWORK) ||
|
|
(DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_NETWORK_T_AND_D))
|
|
{
|
|
printf("\n");
|
|
} else {
|
|
printf(" unit %d\n", DEVICE_CAPABILITY.booted_unit);
|
|
}
|
|
}
|
|
|
|
int
|
|
cmd_test(int argc, char *argp[], int interactive)
|
|
{
|
|
|
|
/* MISC TEST ROUTINE */
|
|
extern int fdd_test(void);
|
|
fdd_test();
|
|
#if 0
|
|
int i;
|
|
|
|
printf("argc=%d\n", argc);
|
|
for (i = 0; i < argc; i++)
|
|
printf("[%d] %s\n", i, argp[i]);
|
|
#endif
|
|
#if 0 /* Recover my 360ADII NVSRAM.. */
|
|
uint8_t *p = (uint8_t *)0xbe490000;
|
|
uint8_t *q = nvsram_tr2a;
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof nvsram_tr2a; i++) {
|
|
*p = *q;
|
|
p += 4;
|
|
q += 1;
|
|
}
|
|
#endif
|
|
#if 0 /* ROM PUTC test */
|
|
char a[]= "ohayotest!";
|
|
int i;
|
|
for (i = 0; i < 10; i++)
|
|
ROM_PUTC(120 + i * 12, 24 * 10, a[i]);
|
|
#endif
|
|
#if 0 /* ROM SCSI disk routine test TR2 */
|
|
uint8_t buf[512*2];
|
|
uint8_t *p;
|
|
int i;
|
|
|
|
printf("type=%d\n", *(uint8_t *)0xbb023034);
|
|
memset(buf, 0, sizeof buf);
|
|
p = (uint8_t *)(((uint32_t)buf + 511) & ~511);
|
|
i = ROM_DK_READ(0, 0, 1, p);
|
|
printf("err=%d\n", i);
|
|
for (i = 0; i < 64; i++) {
|
|
printf("%x ", p[i]);
|
|
if (((i + 1) & 0xf) == 0)
|
|
printf("\n");
|
|
}
|
|
#endif
|
|
#if 0
|
|
/*XXX failed. */
|
|
__asm volatile(
|
|
".set noreorder;"
|
|
"li $4, 2;"
|
|
"mtc0 $4, $16;" /* Config */
|
|
"lui $4, 0xbfc2;"
|
|
"jr $4;"
|
|
"nop;"
|
|
".set reorder");
|
|
/* NOTREACHED */
|
|
#endif
|
|
#if 0
|
|
/* FPU test */
|
|
{
|
|
int v;
|
|
__asm volatile(
|
|
".set noreorder;"
|
|
"lui %0, 0x2000;"
|
|
"mtc0 %0, $12;" /* Cu1 */
|
|
"nop;"
|
|
"nop;"
|
|
"cfc1 %0, $%1;"
|
|
"nop;"
|
|
"nop;"
|
|
".set reorder"
|
|
: "=r"(v) : "i"(0));
|
|
printf("FPUId: %x\n", v);
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|