1 /* $NetBSD: boot.c,v 1.11 2005/12/24 20:07:31 perry Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <lib/libsa/stand.h> 35 #include <lib/libsa/loadfile.h> 36 #include <lib/libkern/libkern.h> 37 #include <sys/reboot.h> 38 #include <sys/boot_flag.h> 39 #include <machine/bootinfo.h> 40 #include <machine/cpu.h> 41 #include <machine/residual.h> 42 #include <powerpc/spr.h> 43 44 #include "boot.h" 45 46 char *names[] = { 47 "in()", 48 #if 0 49 "fd(0,0,0)netbsd", "fd(0,0,0)netbsd.gz", 50 "fd(0,0,0)netbsd.old", "fd(0,0,0)netbsd.old.gz", 51 "fd(0,0,0)onetbsd", "fd(0,0,0)onetbsd.gz" 52 #endif 53 }; 54 #define NUMNAMES (sizeof (names) / sizeof (names[0])) 55 56 #define NAMELEN 128 57 char namebuf[NAMELEN]; 58 char nametmp[NAMELEN]; 59 60 char bootinfo[BOOTINFO_MAXSIZE]; 61 struct btinfo_residual btinfo_residual; 62 struct btinfo_console btinfo_console; 63 struct btinfo_clock btinfo_clock; 64 65 RESIDUAL residual; 66 67 extern u_long ns_per_tick; 68 extern char bootprog_name[], bootprog_rev[], bootprog_maker[], bootprog_date[]; 69 70 void boot __P((void *, u_long)); 71 static void exec_kernel __P((char *)); 72 73 void 74 boot(resp, loadaddr) 75 void *resp; 76 u_long loadaddr; 77 { 78 extern char _end[], _edata[]; 79 int n = 0; 80 int addr, speed; 81 unsigned int cpuvers; 82 char *name, *cnname, *p; 83 84 /* Clear all of BSS */ 85 memset(_edata, 0, _end - _edata); 86 87 /* 88 * console init 89 */ 90 cnname = cninit(&addr, &speed); 91 92 /* make bootinfo */ 93 /* 94 * residual data 95 */ 96 btinfo_residual.common.next = sizeof(btinfo_residual); 97 btinfo_residual.common.type = BTINFO_RESIDUAL; 98 if (resp) { 99 memcpy(&residual, resp, sizeof(residual)); 100 btinfo_residual.addr = (void *)&residual; 101 } else { 102 printf("Warning: no residual data.\n"); 103 btinfo_residual.addr = 0; 104 } 105 106 /* 107 * console 108 */ 109 btinfo_console.common.next = sizeof(btinfo_console); 110 btinfo_console.common.type = BTINFO_CONSOLE; 111 strcpy(btinfo_console.devname, cnname); 112 btinfo_console.addr = addr; 113 btinfo_console.speed = speed; 114 115 /* 116 * clock 117 */ 118 __asm volatile ("mfpvr %0" : "=r"(cpuvers)); 119 cpuvers >>= 16; 120 btinfo_clock.common.next = 0; 121 btinfo_clock.common.type = BTINFO_CLOCK; 122 if (cpuvers == MPC601) { 123 btinfo_clock.ticks_per_sec = 1000000000; 124 } else { 125 btinfo_clock.ticks_per_sec = resp ? 126 residual.VitalProductData.ProcessorBusHz/4 : TICKS_PER_SEC; 127 } 128 ns_per_tick = 1000000000 / btinfo_clock.ticks_per_sec; 129 130 p = bootinfo; 131 memcpy(p, (void *)&btinfo_residual, sizeof(btinfo_residual)); 132 p += sizeof(btinfo_residual); 133 memcpy(p, (void *)&btinfo_console, sizeof(btinfo_console)); 134 p += sizeof(btinfo_console); 135 memcpy(p, (void *)&btinfo_clock, sizeof(btinfo_clock)); 136 137 /* 138 * load kernel if attached 139 */ 140 init_in(loadaddr); 141 142 printf("\n"); 143 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev); 144 printf(">> (%s, %s)\n", bootprog_maker, bootprog_date); 145 146 for (;;) { 147 name = names[n++]; 148 if (n >= NUMNAMES) 149 n = 0; 150 151 exec_kernel(name); 152 } 153 } 154 155 /* 156 * Exec kernel 157 */ 158 static void 159 exec_kernel(name) 160 char *name; 161 { 162 int howto = 0; 163 char c, *ptr; 164 u_long marks[MARK_MAX]; 165 #ifdef DBMONITOR 166 int go_monitor; 167 extern int db_monitor __P((void)); 168 #endif /* DBMONITOR */ 169 170 ret: 171 printf("\nBoot: "); 172 memset(namebuf, 0, sizeof (namebuf)); 173 (void)tgets(namebuf); 174 175 ptr = namebuf; 176 #ifdef DBMONITOR 177 go_monitor = 0; 178 if (*ptr == '!') { 179 if (*(++ptr) == NULL) { 180 db_monitor(); 181 printf("\n"); 182 goto ret; 183 } else { 184 go_monitor++; 185 } 186 } 187 #endif /* DBMONITOR */ 188 while ((c = *ptr)) { 189 while (c == ' ') 190 c = *++ptr; 191 if (!c) 192 goto next; 193 if (c == '-') { 194 while ((c = *++ptr) && c != ' ') 195 BOOT_FLAG(c, howto); 196 } else { 197 name = ptr; 198 while ((c = *++ptr) && c != ' '); 199 if (c) 200 *ptr++ = 0; 201 } 202 } 203 204 next: 205 printf("Loading %s", name); 206 if (howto) 207 printf(" (howto 0x%x)", howto); 208 printf("\n"); 209 210 marks[MARK_START] = 0; 211 if (loadfile(name, marks, LOAD_ALL) == 0) { 212 #ifdef DBMONITOR 213 if (go_monitor) { 214 db_monitor(); 215 printf("\n"); 216 } 217 #endif /* DBMONITOR */ 218 219 printf("start=0x%lx\n\n", marks[MARK_ENTRY]); 220 delay(1000); 221 __syncicache((void *)marks[MARK_ENTRY], 222 (u_int)marks[MARK_SYM] - (u_int)marks[MARK_ENTRY]); 223 224 run((void *)marks[MARK_SYM], 225 (void *)marks[MARK_END], 226 (void *)howto, 227 (void *)bootinfo, 228 (void *)marks[MARK_ENTRY]); 229 } 230 } 231