1 /* $NetBSD: boot.c,v 1.11 2002/04/30 01:14:39 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (C) 1999 Tsubai Masanari. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <lib/libkern/libkern.h> 30 #include <lib/libsa/stand.h> 31 #include <lib/libsa/loadfile.h> 32 33 #include <machine/apcall.h> 34 #include <machine/bootinfo.h> 35 #include <machine/cpu.h> 36 #include <machine/romcall.h> 37 38 void mips1_flushicache __P((void *, int)); 39 extern char _edata[], _end[]; 40 41 /* version strings in vers.c (generated by newvers.sh) */ 42 extern const char bootprog_name[]; 43 extern const char bootprog_rev[]; 44 extern const char bootprog_date[]; 45 extern const char bootprog_maker[]; 46 47 struct apbus_sysinfo *_sip; 48 int apbus; 49 50 char *devs[] = { "sd", "fh", "fd", NULL, NULL, "rd", "st" }; 51 char *kernels[] = { "/netbsd", "/netbsd.gz", NULL }; 52 53 #ifdef BOOT_DEBUG 54 # define DPRINTF(x) printf x 55 #else 56 # define DPRINTF(x) 57 #endif 58 59 void 60 boot(a0, a1, a2, a3, a4, a5) 61 u_int a0, a1, a2, a3, a4, a5; 62 { 63 int fd, i; 64 char *netbsd = ""; 65 int maxmem; 66 u_long marks[MARK_MAX]; 67 char devname[32], file[32]; 68 void (*entry)(); 69 struct btinfo_symtab bi_sym; 70 struct btinfo_bootarg bi_arg; 71 struct btinfo_bootpath bi_bpath; 72 struct btinfo_systype bi_sys; 73 74 /* Clear BSS. */ 75 memset(_edata, 0, _end - _edata); 76 77 /* 78 * XXX a3 contains: 79 * maxmem (nws-3xxx) 80 * argv (apbus-based machine) 81 */ 82 if (a3 >= 0x80000000) 83 apbus = 1; 84 else 85 apbus = 0; 86 87 if (apbus) 88 _sip = (void *)a4; 89 90 printf("%s Secondary Boot, Revision %s\n", 91 bootprog_name, bootprog_rev); 92 printf("(%s, %s)\n", bootprog_maker, bootprog_date); 93 94 if (apbus) { 95 char *bootdev = (char *)a1; 96 int argc = a2; 97 char **argv = (char **)a3; 98 99 DPRINTF(("APbus-based system\n")); 100 101 DPRINTF(("argc = %d\n", argc)); 102 for (i = 0; i < argc; i++) { 103 DPRINTF(("argv[%d] = %s\n", i, argv[i])); 104 if (argv[i][0] != '-' && *netbsd == 0) 105 netbsd = argv[i]; 106 } 107 maxmem = _sip->apbsi_memsize; 108 maxmem -= 0x100000; /* reserve 1MB for ROM monitor */ 109 110 DPRINTF(("howto = 0x%x\n", a0)); 111 DPRINTF(("bootdev = %s\n", (char *)a1)); 112 DPRINTF(("bootname = %s\n", netbsd)); 113 DPRINTF(("maxmem = 0x%x\n", maxmem)); 114 115 /* XXX use "sonic()" instead of "tftp()" */ 116 if (strncmp(bootdev, "tftp", 4) == 0) 117 bootdev = "sonic"; 118 119 strcpy(devname, bootdev); 120 if (strchr(devname, '(') == NULL) 121 strcat(devname, "()"); 122 } else { 123 int bootdev = a1; 124 char *bootname = (char *)a2; 125 int ctlr, unit, part, type; 126 127 DPRINTF(("HB system.\n")); 128 129 /* bootname is "/boot" by default on HB system. */ 130 if (bootname && strcmp(bootname, "/boot") != 0) 131 netbsd = bootname; 132 maxmem = a3; 133 134 DPRINTF(("howto = 0x%x\n", a0)); 135 DPRINTF(("bootdev = 0x%x\n", a1)); 136 DPRINTF(("bootname = %s\n", netbsd)); 137 DPRINTF(("maxmem = 0x%x\n", maxmem)); 138 139 ctlr = BOOTDEV_CTLR(bootdev); 140 unit = BOOTDEV_UNIT(bootdev); 141 part = BOOTDEV_PART(bootdev); 142 type = BOOTDEV_TYPE(bootdev); 143 144 if (devs[type] == NULL) { 145 printf("unknown bootdev (0x%x)\n", bootdev); 146 _rtt(); 147 } 148 149 sprintf(devname, "%s(%d,%d,%d)", devs[type], ctlr, unit, part); 150 } 151 152 printf("Booting %s%s\n", devname, netbsd); 153 154 /* use user specified kernel name if exists */ 155 if (*netbsd) { 156 kernels[0] = netbsd; 157 kernels[1] = NULL; 158 } 159 160 marks[MARK_START] = 0; 161 162 for (i = 0; kernels[i]; i++) { 163 sprintf(file, "%s%s", devname, kernels[i]); 164 DPRINTF(("trying %s...\n", file)); 165 fd = loadfile(file, marks, LOAD_KERNEL); 166 if (fd != -1) 167 break; 168 } 169 if (kernels[i] == NULL) 170 _rtt(); 171 172 DPRINTF(("entry = 0x%x\n", (int)marks[MARK_ENTRY])); 173 DPRINTF(("ssym = 0x%x\n", (int)marks[MARK_SYM])); 174 DPRINTF(("esym = 0x%x\n", (int)marks[MARK_END])); 175 176 bi_init(BOOTINFO_ADDR); 177 178 bi_sym.nsym = marks[MARK_NSYM]; 179 bi_sym.ssym = marks[MARK_SYM]; 180 bi_sym.esym = marks[MARK_END]; 181 bi_add(&bi_sym, BTINFO_SYMTAB, sizeof(bi_sym)); 182 183 bi_arg.howto = a0; 184 bi_arg.bootdev = a1; 185 bi_arg.maxmem = maxmem; 186 bi_arg.sip = (int)_sip; 187 bi_add(&bi_arg, BTINFO_BOOTARG, sizeof(bi_arg)); 188 189 strcpy(bi_bpath.bootpath, file); 190 bi_add(&bi_bpath, BTINFO_BOOTPATH, sizeof(bi_bpath)); 191 192 bi_sys.type = apbus ? NEWS5000 : NEWS3400; /* XXX */ 193 bi_add(&bi_sys, BTINFO_SYSTYPE, sizeof(bi_sys)); 194 195 entry = (void *)marks[MARK_ENTRY]; 196 197 if (apbus) 198 apcall_flushcache(); 199 else 200 mips1_flushicache(entry, marks[MARK_SYM] - marks[MARK_ENTRY]); 201 202 printf("\n"); 203 (*entry)(a0, a1, a2, a3, a4, a5); 204 } 205 206 void 207 putchar(x) 208 int x; 209 { 210 char c = x; 211 212 if (apbus) 213 apcall_write(1, &c, 1); 214 else 215 rom_write(1, &c, 1); 216 } 217 218 int 219 getchar() 220 { 221 unsigned char c = '\0'; 222 int i; 223 224 for (;;) { 225 i = apbus ? apcall_read(1, &c, 1) : rom_read(1, &c, 1); 226 if (i == 1) 227 break; 228 if (i != -2 && i != 0) 229 return -1; 230 } 231 return c; 232 } 233 234 void 235 _rtt() 236 { 237 if (apbus) 238 apcall_exit(8); 239 else 240 rom_halt(); 241 242 for (;;); 243 } 244