1 /* $Id: boot.c,v 1.2 1998/01/19 03:00:57 sakamoto 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 #include <stand.h> 34 35 #include <sys/exec_elf.h> 36 #include <sys/reboot.h> 37 #include <machine/param.h> 38 #include <bebox/include/bootinfo.h> 39 #ifdef CONS_SERIAL 40 #include "ns16550.h" 41 #endif /* CONS_SERIAL */ 42 43 #define NAMELEN 128 44 45 char *name; 46 char *names[] = { 47 "in()", 48 "fd(0,1,0)netbsd", "fd(0,1,0)netbsd.gz", 49 "fd(0,1,0)netbsd.old", "fd(0,1,0)netbsd.old.gz", 50 "fd(0,1,0)onetbsd", "fd(0,1,0)onetbsd.gz" 51 }; 52 #define NUMNAMES (sizeof (names) / sizeof (names[0])) 53 54 char namebuf[NAMELEN]; 55 char nametmp[NAMELEN]; 56 int args; 57 void *startsym, *endsym, *bootinfo; 58 struct btinfo_memory btinfo_memory; 59 struct btinfo_console btinfo_console; 60 struct btinfo_clock btinfo_clock; 61 extern int errno; 62 63 void 64 main() 65 { 66 int fd, n = 0; 67 void *p; 68 void start_CPU1(); 69 extern int CPU1_alive; 70 extern char bootprog_name[], bootprog_rev[], 71 bootprog_maker[], bootprog_date[]; 72 73 if (whichCPU() == 1) 74 cpu1(); 75 resetCPU1(); 76 77 /* 78 * make bootinfo 79 */ 80 bootinfo = (void *)0x3030; 81 82 btinfo_memory.common.next = sizeof (btinfo_memory); 83 btinfo_memory.common.type = BTINFO_MEMORY; 84 btinfo_memory.memsize = *(int *)0x3010; 85 86 btinfo_console.common.next = sizeof (btinfo_console); 87 btinfo_console.common.type = BTINFO_CONSOLE; 88 #ifdef CONS_VGA 89 strcpy(btinfo_console.devname, "vga"); 90 #endif /* CONS_VGA */ 91 #ifdef CONS_SERIAL 92 strcpy(btinfo_console.devname, "com"); 93 # ifdef COMPORT 94 btinfo_console.addr = COMPORT; 95 # else /* COMPORT */ 96 btinfo_console.addr = COM1; 97 # endif /* COMPORT */ 98 # ifdef COMSPEED 99 btinfo_console.speed = COMSPEED; 100 # else /* COMSPEED */ 101 btinfo_console.speed = 9600; 102 # endif /* COMSPEED */ 103 #endif /* CONS_SERIAL */ 104 105 btinfo_clock.common.next = 0; 106 btinfo_clock.common.type = BTINFO_CLOCK; 107 btinfo_clock.ticks_per_sec = findcpuspeed(); 108 109 p = bootinfo; 110 bcopy((void *)&btinfo_memory, p, sizeof (btinfo_memory)); 111 p += sizeof (btinfo_memory); 112 bcopy((void *)&btinfo_console, p, sizeof (btinfo_console)); 113 p += sizeof (btinfo_console); 114 bcopy((void *)&btinfo_clock, p, sizeof (btinfo_clock)); 115 116 /* 117 * console init 118 */ 119 cninit(); 120 121 /* 122 * attached kernel check 123 */ 124 init_in(); 125 126 runCPU1(start_CPU1); 127 wait_for(&CPU1_alive); 128 129 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev); 130 printf(">> (%s, %s)\n", bootprog_maker, bootprog_date); 131 printf(">> Memory: %d k\n", btinfo_memory.memsize / 1024); 132 133 for (;;) { 134 args = 0; 135 name = names[n++]; 136 if (n >= NUMNAMES) 137 n = 0; 138 139 getbootdev(&args); 140 fd = open(name, 0); 141 if (fd >= 0) { 142 exec_kernel(fd, &args); 143 close(fd); /* exec failed */ 144 } else { 145 printf("open error:%s\n", strerror(errno)); 146 } 147 } 148 } 149 150 /* 151 * Get boot device, file name, flag 152 */ 153 getbootdev(howto) 154 int *howto; 155 { 156 char c, *ptr; 157 #ifdef DBMONITOR 158 extern int load_flag; 159 #endif /* DBMONITOR */ 160 161 #ifdef DBMONITOR 162 ret: 163 if (load_flag) 164 printf("Load: "); 165 else 166 #endif /* DBMONITOR */ 167 printf("Boot: "); 168 169 bzero(namebuf, sizeof (namebuf)); 170 if (tgets(namebuf) != -1) { 171 ptr = namebuf; 172 #ifdef DBMONITOR 173 if (*ptr == '!') { 174 db_monitor(); 175 printf("\n"); 176 goto ret; 177 } 178 #endif /* DBMONITOR */ 179 while (c = *ptr) { 180 while (c == ' ') 181 c = *++ptr; 182 if (!c) 183 return; 184 if (c == '-') 185 while ((c = *++ptr) && c != ' ') { 186 if (c == 'a') 187 *howto |= RB_ASKNAME; 188 else if (c == 'b') 189 *howto |= RB_HALT; 190 else if (c == 'd') 191 *howto |= RB_KDB; 192 else if (c == 'r') 193 *howto |= RB_DFLTROOT; 194 else if (c == 's') 195 *howto |= RB_SINGLE; 196 } 197 else { 198 name = ptr; 199 while ((c = *++ptr) && c != ' '); 200 if (c) 201 *ptr++ = 0; 202 } 203 } 204 } else { 205 putchar('\n'); 206 } 207 } 208 209 exec_kernel(fd, howto) 210 int fd; 211 int *howto; 212 { 213 int i, first = 1; 214 Elf32_Ehdr hdr; 215 Elf32_Phdr phdr; 216 Elf32_Shdr shdr; 217 void *sp, *ssp; 218 #ifdef DBMONITOR 219 extern int load_flag; 220 #endif /* DBMONITOR */ 221 222 #ifdef DBMONITOR 223 printf("%s %s ", (load_flag ? "Loading" : "Booting"), name); 224 #else /* DBMONITOR */ 225 printf("Booting %s ", name); 226 #endif /* DBMONITOR */ 227 228 if (read(fd, &hdr, ELF32_HDR_SIZE) != ELF32_HDR_SIZE) { 229 printf("\nread error: %s\n", strerror(errno)); 230 return; 231 } 232 if (bcmp(hdr.e_ident, Elf32_e_ident, Elf32_e_siz)) { 233 printf("\nnot ELF32 format\n"); 234 return; 235 } 236 if (hdr.e_machine != Elf_em_ppc) { 237 printf("\nnot PowerPC exec binary\n"); 238 return; 239 } 240 #if 0 241 printf("e_entry= 0x%x\n", hdr.e_entry); 242 printf("e_phoff= 0x%x\n", hdr.e_phoff); 243 printf("e_shoff= 0x%x\n", hdr.e_shoff); 244 printf("e_flags= 0x%x\n", hdr.e_flags); 245 printf("e_ehsize= 0x%x\n", hdr.e_ehsize); 246 printf("e_phentsize= 0x%x\n", hdr.e_phentsize); 247 printf("e_phnum= 0x%x\n", hdr.e_phnum); 248 printf("e_shentsize= 0x%x\n", hdr.e_shentsize); 249 printf("e_shnum= 0x%x\n", hdr.e_shnum); 250 printf("e_shstrndx= 0x%x\n", hdr.e_shstrndx); 251 #endif 252 printf("@ 0x%x\n", hdr.e_entry); 253 254 for (i = 0; i < hdr.e_phnum; i++) { 255 lseek(fd, hdr.e_phoff + sizeof(phdr) * i, SEEK_SET); 256 if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) { 257 printf("\nread phdr error: %s\n", strerror(errno)); 258 return; 259 } 260 if (phdr.p_type != Elf_pt_load || 261 (phdr.p_flags & (Elf_pf_w|Elf_pf_x)) == 0) 262 continue; 263 264 /* Read in segment. */ 265 printf("%s%d", first ? "" : "+", phdr.p_filesz); 266 lseek(fd, phdr.p_offset, SEEK_SET); 267 if (read(fd, (void *)phdr.p_vaddr, phdr.p_filesz) 268 != phdr.p_filesz) { 269 printf("read text error: %s\n", strerror(errno)); 270 return; 271 } 272 273 /* Zero out bss. */ 274 if (phdr.p_filesz < phdr.p_memsz) { 275 printf("+%d", phdr.p_memsz - phdr.p_filesz); 276 bzero(phdr.p_vaddr + phdr.p_filesz, 277 phdr.p_memsz - phdr.p_filesz); 278 sp = (void *)(phdr.p_vaddr + phdr.p_memsz); 279 startsym = sp = (void *)ALIGN(sp); 280 } 281 first = 0; 282 } 283 284 bcopy(&hdr, startsym, ELF32_HDR_SIZE); 285 ((Elf32_Ehdr *)startsym)->e_shoff = ELF32_HDR_SIZE; 286 sp += ELF32_HDR_SIZE; 287 ssp = sp + sizeof(shdr) * hdr.e_shnum; 288 first = 1; 289 printf("+["); 290 291 for (i = 0; i < hdr.e_shnum; i++) { 292 lseek(fd, hdr.e_shoff + sizeof(shdr) * i, SEEK_SET); 293 if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) { 294 printf("\nread shdr error: %s\n", strerror(errno)); 295 return; 296 } 297 bcopy(&shdr, sp, sizeof(shdr)); 298 ((Elf32_Shdr *)sp)->sh_offset = ssp - startsym; 299 sp += sizeof(shdr); 300 301 if (shdr.sh_type != Elf_sht_strtab && 302 shdr.sh_type != Elf_sht_symtab) 303 continue; 304 305 /* Read in segment. */ 306 printf("%s%d", first ? "" : "+", shdr.sh_size); 307 lseek(fd, shdr.sh_offset, SEEK_SET); 308 if (read(fd, ssp, shdr.sh_size) != shdr.sh_size) { 309 printf("read symbol error: %s\n", strerror(errno)); 310 return; 311 } 312 ssp += shdr.sh_size; 313 ssp = (void *)ALIGN(ssp); 314 first = 0; 315 } 316 endsym = ssp; 317 printf("]\n"); 318 close(fd); 319 320 #ifdef DBMONITOR 321 if (!load_flag) { 322 *(volatile long *)0x0080 = (long)hdr.e_entry; 323 run((void *)hdr.e_entry); 324 } 325 #else /* DBMONITOR */ 326 *(volatile long *)0x0080 = (long)hdr.e_entry; 327 run((void *)hdr.e_entry); 328 #endif /* DBMONITOR */ 329 } 330