1 /* $NetBSD: boot.c,v 1.20 2014/08/08 19:45:48 joerg 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 #include <powerpc/oea/spr.h> 44 45 #include "boot.h" 46 #include "sdvar.h" 47 48 char *names[] = { 49 "sd(0,0,0)netbsd", "sd(0,0,0)onetbsd", 50 "in()", 51 }; 52 #define NUMNAMES (sizeof (names) / sizeof (names[0])) 53 54 #define NAMELEN 128 55 char namebuf[NAMELEN]; 56 char nametmp[NAMELEN]; 57 58 char bootinfo[BOOTINFO_MAXSIZE]; 59 struct btinfo_residual btinfo_residual; 60 struct btinfo_console btinfo_console; 61 struct btinfo_clock btinfo_clock; 62 63 RESIDUAL residual; 64 65 extern u_long ns_per_tick; 66 extern char bootprog_name[], bootprog_rev[]; 67 68 void boot(void *, u_long); 69 static void exec_kernel(char *); 70 71 void 72 boot(void *resp, u_long loadaddr) 73 { 74 extern char _end[], _edata[]; 75 int n = 0; 76 int addr, speed; 77 unsigned int cpuvers; 78 char *name, *cnname, *p; 79 80 /* Clear all of BSS */ 81 memset(_edata, 0, _end - _edata); 82 83 /* 84 * console init 85 */ 86 cnname = cninit(&addr, &speed); 87 #ifdef VGA_RESET 88 vga_reset((u_char *)0xc0000000); 89 #endif 90 91 /* make bootinfo */ 92 /* 93 * residual data 94 */ 95 btinfo_residual.common.next = sizeof(btinfo_residual); 96 btinfo_residual.common.type = BTINFO_RESIDUAL; 97 if (resp) { 98 memcpy(&residual, resp, sizeof(residual)); 99 btinfo_residual.addr = (void *)&residual; 100 } else { 101 printf("Warning: no residual data.\n"); 102 btinfo_residual.addr = 0; 103 } 104 105 /* 106 * console 107 */ 108 btinfo_console.common.next = sizeof(btinfo_console); 109 btinfo_console.common.type = BTINFO_CONSOLE; 110 strcpy(btinfo_console.devname, cnname); 111 btinfo_console.addr = addr; 112 btinfo_console.speed = speed; 113 114 /* 115 * clock 116 */ 117 __asm volatile ("mfpvr %0" : "=r"(cpuvers)); 118 cpuvers >>= 16; 119 btinfo_clock.common.next = 0; 120 btinfo_clock.common.type = BTINFO_CLOCK; 121 if (cpuvers == MPC601) { 122 btinfo_clock.ticks_per_sec = 1000000000; 123 } else { 124 btinfo_clock.ticks_per_sec = resp ? 125 residual.VitalProductData.ProcessorBusHz/4 : TICKS_PER_SEC; 126 } 127 ns_per_tick = 1000000000 / btinfo_clock.ticks_per_sec; 128 129 p = bootinfo; 130 memcpy(p, (void *)&btinfo_residual, sizeof(btinfo_residual)); 131 p += sizeof(btinfo_residual); 132 memcpy(p, (void *)&btinfo_console, sizeof(btinfo_console)); 133 p += sizeof(btinfo_console); 134 memcpy(p, (void *)&btinfo_clock, sizeof(btinfo_clock)); 135 136 /* 137 * load kernel if attached 138 */ 139 init_in(loadaddr); 140 141 printf("\n"); 142 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev); 143 printf("\n"); 144 145 /* 146 * Initialize siop@pci0 dev 16 func 0 147 */ 148 siop_init(0, 16, 0); 149 150 for (;;) { 151 name = names[n++]; 152 if (n >= NUMNAMES) 153 n = 0; 154 155 exec_kernel(name); 156 } 157 } 158 159 /* 160 * Exec kernel 161 */ 162 static void 163 exec_kernel(char *name) 164 { 165 int howto = 0; 166 char c, *ptr; 167 u_long marks[MARK_MAX]; 168 #ifdef DBMONITOR 169 int go_monitor; 170 extern int db_monitor(void); 171 172 ret: 173 #endif /* DBMONITOR */ 174 printf("\nBoot: "); 175 memset(namebuf, 0, sizeof (namebuf)); 176 if (tgets(namebuf) == -1) 177 printf("\n"); 178 179 ptr = namebuf; 180 #ifdef DBMONITOR 181 go_monitor = 0; 182 if (*ptr == '!') { 183 if (*(++ptr) == NULL) { 184 db_monitor(); 185 printf("\n"); 186 goto ret; 187 } else { 188 go_monitor++; 189 } 190 } 191 #endif /* DBMONITOR */ 192 while ((c = *ptr)) { 193 while (c == ' ') 194 c = *++ptr; 195 if (!c) 196 goto next; 197 if (c == '-') { 198 while ((c = *++ptr) && c != ' ') 199 BOOT_FLAG(c, howto); 200 } else { 201 name = ptr; 202 while ((c = *++ptr) && c != ' '); 203 if (c) 204 *ptr++ = 0; 205 } 206 } 207 208 next: 209 printf("Loading %s", name); 210 if (howto) 211 printf(" (howto 0x%x)", howto); 212 printf("\n"); 213 214 marks[MARK_START] = 0; 215 if (loadfile(name, marks, LOAD_ALL) == 0) { 216 #ifdef DBMONITOR 217 if (go_monitor) { 218 db_monitor(); 219 printf("\n"); 220 } 221 #endif /* DBMONITOR */ 222 223 printf("start=0x%lx\n\n", marks[MARK_ENTRY]); 224 delay(1000); 225 __syncicache((void *)marks[MARK_ENTRY], 226 (u_int)marks[MARK_SYM] - (u_int)marks[MARK_ENTRY]); 227 228 run((void *)marks[MARK_SYM], 229 (void *)marks[MARK_END], 230 (void *)howto, 231 (void *)bootinfo, 232 (void *)marks[MARK_ENTRY]); 233 } 234 } 235 236 void 237 _rtt(void) 238 { 239 240 /* XXXX */ 241 __unreachable(); 242 } 243