1 /* $NetBSD: boot.c,v 1.12 2002/11/22 16:27:07 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 boot __P((u_int32_t, u_int32_t, uint32_t, u_int32_t, u_int32_t, 39 u_int32_t)); 40 41 void mips1_flushicache __P((void *, int)); 42 extern char _edata[], _end[]; 43 44 /* version strings in vers.c (generated by newvers.sh) */ 45 extern const char bootprog_name[]; 46 extern const char bootprog_rev[]; 47 extern const char bootprog_date[]; 48 extern const char bootprog_maker[]; 49 50 struct apbus_sysinfo *_sip; 51 int apbus; 52 53 char *devs[] = { "sd", "fh", "fd", NULL, NULL, "rd", "st" }; 54 char *kernels[] = { "/netbsd", "/netbsd.gz", NULL }; 55 56 #ifdef BOOT_DEBUG 57 # define DPRINTF(x) printf x 58 #else 59 # define DPRINTF(x) 60 #endif 61 62 void 63 boot(a0, a1, a2, a3, a4, a5) 64 u_int32_t a0, a1, a2, a3, a4, a5; 65 { 66 int fd, i; 67 char *netbsd = ""; 68 int maxmem; 69 u_long marks[MARK_MAX]; 70 char devname[32], file[32]; 71 void (*entry) __P((u_int32_t, u_int32_t, uint32_t, u_int32_t, 72 u_int32_t, u_int32_t)); 73 struct btinfo_symtab bi_sym; 74 struct btinfo_bootarg bi_arg; 75 struct btinfo_bootpath bi_bpath; 76 struct btinfo_systype bi_sys; 77 78 /* Clear BSS. */ 79 memset(_edata, 0, _end - _edata); 80 81 /* 82 * XXX a3 contains: 83 * maxmem (nws-3xxx) 84 * argv (apbus-based machine) 85 */ 86 if (a3 >= 0x80000000) 87 apbus = 1; 88 else 89 apbus = 0; 90 91 if (apbus) 92 _sip = (void *)a4; 93 94 printf("%s Secondary Boot, Revision %s\n", 95 bootprog_name, bootprog_rev); 96 printf("(%s, %s)\n", bootprog_maker, bootprog_date); 97 98 if (apbus) { 99 char *bootdev = (char *)a1; 100 int argc = a2; 101 char **argv = (char **)a3; 102 103 DPRINTF(("APbus-based system\n")); 104 105 DPRINTF(("argc = %d\n", argc)); 106 for (i = 0; i < argc; i++) { 107 DPRINTF(("argv[%d] = %s\n", i, argv[i])); 108 if (argv[i][0] != '-' && *netbsd == 0) 109 netbsd = argv[i]; 110 } 111 maxmem = _sip->apbsi_memsize; 112 maxmem -= 0x100000; /* reserve 1MB for ROM monitor */ 113 114 DPRINTF(("howto = 0x%x\n", a0)); 115 DPRINTF(("bootdev = %s\n", (char *)a1)); 116 DPRINTF(("bootname = %s\n", netbsd)); 117 DPRINTF(("maxmem = 0x%x\n", maxmem)); 118 119 /* XXX use "sonic()" instead of "tftp()" */ 120 if (strncmp(bootdev, "tftp", 4) == 0) 121 bootdev = "sonic"; 122 123 strcpy(devname, bootdev); 124 if (strchr(devname, '(') == NULL) 125 strcat(devname, "()"); 126 } else { 127 int bootdev = a1; 128 char *bootname = (char *)a2; 129 int ctlr, unit, part, type; 130 131 DPRINTF(("HB system.\n")); 132 133 /* bootname is "/boot" by default on HB system. */ 134 if (bootname && strcmp(bootname, "/boot") != 0) 135 netbsd = bootname; 136 maxmem = a3; 137 138 DPRINTF(("howto = 0x%x\n", a0)); 139 DPRINTF(("bootdev = 0x%x\n", a1)); 140 DPRINTF(("bootname = %s\n", netbsd)); 141 DPRINTF(("maxmem = 0x%x\n", maxmem)); 142 143 ctlr = BOOTDEV_CTLR(bootdev); 144 unit = BOOTDEV_UNIT(bootdev); 145 part = BOOTDEV_PART(bootdev); 146 type = BOOTDEV_TYPE(bootdev); 147 148 if (devs[type] == NULL) { 149 printf("unknown bootdev (0x%x)\n", bootdev); 150 _rtt(); 151 } 152 153 sprintf(devname, "%s(%d,%d,%d)", devs[type], ctlr, unit, part); 154 } 155 156 printf("Booting %s%s\n", devname, netbsd); 157 158 /* use user specified kernel name if exists */ 159 if (*netbsd) { 160 kernels[0] = netbsd; 161 kernels[1] = NULL; 162 } 163 164 marks[MARK_START] = 0; 165 166 for (i = 0; kernels[i]; i++) { 167 sprintf(file, "%s%s", devname, kernels[i]); 168 DPRINTF(("trying %s...\n", file)); 169 fd = loadfile(file, marks, LOAD_KERNEL); 170 if (fd != -1) 171 break; 172 } 173 if (kernels[i] == NULL) 174 _rtt(); 175 176 DPRINTF(("entry = 0x%x\n", (int)marks[MARK_ENTRY])); 177 DPRINTF(("ssym = 0x%x\n", (int)marks[MARK_SYM])); 178 DPRINTF(("esym = 0x%x\n", (int)marks[MARK_END])); 179 180 bi_init(BOOTINFO_ADDR); 181 182 bi_sym.nsym = marks[MARK_NSYM]; 183 bi_sym.ssym = marks[MARK_SYM]; 184 bi_sym.esym = marks[MARK_END]; 185 bi_add(&bi_sym, BTINFO_SYMTAB, sizeof(bi_sym)); 186 187 bi_arg.howto = a0; 188 bi_arg.bootdev = a1; 189 bi_arg.maxmem = maxmem; 190 bi_arg.sip = (int)_sip; 191 bi_add(&bi_arg, BTINFO_BOOTARG, sizeof(bi_arg)); 192 193 strcpy(bi_bpath.bootpath, file); 194 bi_add(&bi_bpath, BTINFO_BOOTPATH, sizeof(bi_bpath)); 195 196 bi_sys.type = apbus ? NEWS5000 : NEWS3400; /* XXX */ 197 bi_add(&bi_sys, BTINFO_SYSTYPE, sizeof(bi_sys)); 198 199 entry = (void *)marks[MARK_ENTRY]; 200 201 if (apbus) 202 apcall_flushcache(); 203 else 204 mips1_flushicache(entry, marks[MARK_SYM] - marks[MARK_ENTRY]); 205 206 printf("\n"); 207 (*entry)(a0, a1, a2, a3, a4, a5); 208 } 209 210 void 211 putchar(x) 212 int x; 213 { 214 char c = x; 215 216 if (apbus) 217 apcall_write(1, &c, 1); 218 else 219 rom_write(1, &c, 1); 220 } 221 222 int 223 getchar() 224 { 225 unsigned char c = '\0'; 226 int i; 227 228 for (;;) { 229 i = apbus ? apcall_read(1, &c, 1) : rom_read(1, &c, 1); 230 if (i == 1) 231 break; 232 if (i != -2 && i != 0) 233 return -1; 234 } 235 return c; 236 } 237 238 void 239 _rtt() 240 { 241 if (apbus) 242 apcall_exit(8); 243 else 244 rom_halt(); 245 246 for (;;); 247 } 248