Home | History | Annotate | Line # | Download | only in ofwboot
boot.c revision 1.7
      1 /*	$NetBSD: boot.c,v 1.7 2004/06/18 21:04:39 martin Exp $	*/
      2 #define DEBUG
      3 /*
      4  * Copyright (c) 1997, 1999 Eduardo E. Horvath.  All rights reserved.
      5  * Copyright (c) 1997 Jason R. Thorpe.  All rights reserved.
      6  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
      7  * Copyright (C) 1995, 1996 TooLs GmbH.
      8  * All rights reserved.
      9  *
     10  * ELF support derived from NetBSD/alpha's boot loader, written
     11  * by Christopher G. Demetriou.
     12  *
     13  * Redistribution and use in source and binary forms, with or without
     14  * modification, are permitted provided that the following conditions
     15  * are met:
     16  * 1. Redistributions of source code must retain the above copyright
     17  *    notice, this list of conditions and the following disclaimer.
     18  * 2. Redistributions in binary form must reproduce the above copyright
     19  *    notice, this list of conditions and the following disclaimer in the
     20  *    documentation and/or other materials provided with the distribution.
     21  * 3. All advertising materials mentioning features or use of this software
     22  *    must display the following acknowledgement:
     23  *	This product includes software developed by TooLs GmbH.
     24  * 4. The name of TooLs GmbH may not be used to endorse or promote products
     25  *    derived from this software without specific prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
     28  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     29  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     30  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     31  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     32  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     33  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     34  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     35  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     36  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*
     40  * First try for the boot code
     41  *
     42  * Input syntax is:
     43  *	[promdev[{:|,}partition]]/[filename] [flags]
     44  */
     45 
     46 #ifdef ELFSIZE
     47 #undef	ELFSIZE		/* We use both. */
     48 #endif
     49 
     50 #include <lib/libsa/stand.h>
     51 #include <lib/libkern/libkern.h>
     52 
     53 #include <sys/param.h>
     54 #include <sys/exec.h>
     55 #include <sys/exec_elf.h>
     56 #include <sys/reboot.h>
     57 #include <sys/disklabel.h>
     58 #include <sys/boot_flag.h>
     59 
     60 #include <machine/cpu.h>
     61 
     62 #include "ofdev.h"
     63 #include "openfirm.h"
     64 
     65 #define	MEG	(1024*1024)
     66 
     67 /*
     68  * Boot device is derived from ROM provided information, or if there is none,
     69  * this list is used in sequence, to find a kernel.
     70  */
     71 char *kernels[] = {
     72 	"netbsd ",
     73 	"netbsd.gz ",
     74 	"netbsd.old ",
     75 	"netbsd.old.gz ",
     76 	"onetbsd ",
     77 	"onetbsd.gz ",
     78 	"vmunix ",
     79 #ifdef notyet
     80 	"netbsd.pl ",
     81 	"netbsd.pl.gz ",
     82 	"netbsd.el ",
     83 	"netbsd.el.gz ",
     84 #endif
     85 	NULL
     86 };
     87 
     88 char *kernelname;
     89 char bootdev[128];
     90 char bootfile[128];
     91 int boothowto;
     92 int debug;
     93 
     94 
     95 #ifdef SPARC_BOOT_ELF
     96 int	elf32_exec __P((int, Elf32_Ehdr *, u_int64_t *, void **, void **));
     97 int	elf64_exec __P((int, Elf64_Ehdr *, u_int64_t *, void **, void **));
     98 #endif
     99 
    100 #ifdef SPARC_BOOT_AOUT
    101 int	aout_exec __P((int, struct exec *, u_int64_t *, void **));
    102 #endif
    103 
    104 #if 0
    105 static void
    106 prom2boot(dev)
    107 	char *dev;
    108 {
    109 	char *cp, *lp = 0;
    110 	int handle;
    111 	char devtype[16];
    112 
    113 	for (cp = dev; *cp; cp++)
    114 		if (*cp == ':')
    115 			lp = cp;
    116 	if (!lp)
    117 		lp = cp;
    118 	*lp = 0;
    119 }
    120 #endif
    121 
    122 static void
    123 parseargs(str, howtop)
    124 	char *str;
    125 	int *howtop;
    126 {
    127 	char *cp;
    128 	int i;
    129 
    130 	/* Allow user to drop back to the PROM. */
    131 	if (strcmp(str, "exit") == 0 || strcmp(str, "halt") == 0)
    132 		_rtt();
    133 
    134 	/* Insert the kernel name if it is not there. */
    135 	if (str[0] == 0 || str[0] == '-') {
    136 		/* Move args down the string */
    137 		i=0;
    138 		for (cp = str + strlen(kernelname); str[i]; i++)
    139 			cp[i] = str[i];
    140 		/* Copy over kernelname */
    141 		for (i = 0; kernelname[i]; i++)
    142 			str[i] = kernelname[i];
    143 	}
    144 	*howtop = 0;
    145 	for (cp = str; *cp; cp++)
    146 		if (*cp == ' ')
    147 			break;
    148 	if (!*cp)
    149 		return;
    150 
    151 	*cp++ = 0;
    152 	while (*cp) {
    153 		BOOT_FLAG(*cp, *howtop);
    154 		/* handle specialties */
    155 		switch (*cp++) {
    156 		case 'd':
    157 			if (!debug) debug = 1;
    158 			break;
    159 		case 'D':
    160 			debug = 2;
    161 			break;
    162 		default:
    163 			break;
    164 		}
    165 	}
    166 }
    167 
    168 
    169 static void
    170 chain(pentry, args, ssym, esym)
    171 	u_int64_t pentry;
    172 	char *args;
    173 	void *ssym;
    174 	void *esym;
    175 {
    176 	extern char end[];
    177 	void (*entry)();
    178 	int l, machine_tag;
    179 	long newargs[3];
    180 
    181 	entry = (void*)(long)pentry;
    182 
    183 	freeall();
    184 	/*
    185 	 * When we come in args consists of a pointer to the boot
    186 	 * string.  We need to fix it so it takes into account
    187 	 * other params such as romp.
    188 	 */
    189 
    190 	/*
    191 	 * Stash pointer to end of symbol table after the argument
    192 	 * strings.
    193 	 */
    194 	l = strlen(args) + 1;
    195 	bcopy(&esym, args + l, sizeof(esym));
    196 	l += sizeof(esym);
    197 
    198 	/*
    199 	 * Tell the kernel we're an OpenFirmware system.
    200 	 */
    201 #define SPARC_MACHINE_OPENFIRMWARE		0x44444230
    202 	machine_tag = SPARC_MACHINE_OPENFIRMWARE;
    203 	bcopy(&machine_tag, args + l, sizeof(machine_tag));
    204 	l += sizeof(machine_tag);
    205 
    206 	/*
    207 	 * Since we don't need the boot string (we can get it from /chosen)
    208 	 * we won't pass it in.  Just pass in esym and magic #
    209 	 */
    210 	newargs[0] = SPARC_MACHINE_OPENFIRMWARE;
    211 	newargs[1] = (long)esym;
    212 	newargs[2] = (long)ssym;
    213 	args = (char *)newargs;
    214 	l = sizeof(newargs);
    215 
    216 #ifdef DEBUG
    217 	printf("chain: calling OF_chain(%x, %x, %x, %x, %x)\n",
    218 	       (void *)RELOC, end - (char *)RELOC, entry, args, l);
    219 #endif
    220 	/* if -D is set then pause in the PROM. */
    221 	if (debug > 1) OF_enter();
    222 	OF_chain((void *)RELOC, ((end - (char *)RELOC)+NBPG)%NBPG, entry, args, l);
    223 	panic("chain");
    224 }
    225 
    226 int
    227 loadfile(fd, args)
    228 	int fd;
    229 	char *args;
    230 {
    231 	union {
    232 #ifdef SPARC_BOOT_AOUT
    233 		struct exec aout;
    234 #endif
    235 #ifdef SPARC_BOOT_ELF
    236 		Elf32_Ehdr elf32;
    237 		Elf64_Ehdr elf64;
    238 #endif
    239 	} hdr;
    240 	int rval;
    241 	u_int64_t entry = 0;
    242 	void *ssym;
    243 	void *esym;
    244 
    245 	rval = 1;
    246 	ssym = NULL;
    247 	esym = NULL;
    248 
    249 	/* Load the header. */
    250 #ifdef DEBUG
    251 	printf("loadfile: reading header\n");
    252 #endif
    253 	if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
    254 		printf("read header: %s\n", strerror(errno));
    255 		goto err;
    256 	}
    257 
    258 	/* Determine file type, load kernel. */
    259 #ifdef SPARC_BOOT_AOUT
    260 	if (N_BADMAG(hdr.aout) == 0 && N_GETMID(hdr.aout) == MID_SPARC) {
    261 		rval = aout_exec(fd, &hdr.aout, &entry, &esym);
    262 	} else
    263 #endif
    264 #ifdef SPARC_BOOT_ELF
    265 	if (bcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 &&
    266 	    hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
    267 		rval = elf32_exec(fd, &hdr.elf32, &entry, &ssym, &esym);
    268 	} else
    269 	if (bcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 &&
    270 	    hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) {
    271 		rval = elf64_exec(fd, &hdr.elf64, &entry, &ssym, &esym);
    272 	} else
    273 #endif
    274 	{
    275 		printf("unknown executable format\n");
    276 	}
    277 
    278 	if (rval)
    279 		goto err;
    280 
    281 	printf(" start=0x%lx\n", (unsigned long)entry);
    282 
    283 	close(fd);
    284 
    285 	/* XXX this should be replaced w/ a mountroothook. */
    286 	if (floppyboot) {
    287 		printf("Please insert root disk and press ENTER ");
    288 		getchar();
    289 		printf("\n");
    290 	}
    291 
    292 	chain(entry, args, ssym, esym);
    293 	/* NOTREACHED */
    294 
    295  err:
    296 	close(fd);
    297 	return (rval);
    298 }
    299 
    300 #ifdef SPARC_BOOT_AOUT
    301 int
    302 aout_exec(fd, hdr, entryp, esymp)
    303 	int fd;
    304 	struct exec *hdr;
    305 	u_int64_t *entryp;
    306 	void **esymp;
    307 {
    308 	void *addr;
    309 	int n, *paddr;
    310 
    311 #ifdef DEBUG
    312 	printf("auout_exec: ");
    313 #endif
    314 	/* Display the load address (entry point) for a.out. */
    315 	printf("Booting %s @ 0x%lx\n", opened_name, hdr->a_entry);
    316 	addr = (void *)(hdr->a_entry);
    317 
    318 	/*
    319 	 * Determine memory needed for kernel and allocate it from
    320 	 * the firmware.
    321 	 */
    322 	n = hdr->a_text + hdr->a_data + hdr->a_bss + hdr->a_syms + sizeof(int);
    323 	if ((paddr = OF_claim(addr, n, 0)) == (int *)-1)
    324 		panic("cannot claim memory");
    325 
    326 	/* Load text. */
    327 	lseek(fd, N_TXTOFF(*hdr), SEEK_SET);
    328 	printf("%lu", hdr->a_text);
    329 	if (read(fd, paddr, hdr->a_text) != hdr->a_text) {
    330 		printf("read text: %s\n", strerror(errno));
    331 		return (1);
    332 	}
    333 	syncicache((void *)paddr, hdr->a_text);
    334 
    335 	/* Load data. */
    336 	printf("+%lu", hdr->a_data);
    337 	if (read(fd, (void *)paddr + hdr->a_text, hdr->a_data) != hdr->a_data) {
    338 		printf("read data: %s\n", strerror(errno));
    339 		return (1);
    340 	}
    341 
    342 	/* Zero BSS. */
    343 	printf("+%lu", hdr->a_bss);
    344 	bzero((void *)paddr + hdr->a_text + hdr->a_data, hdr->a_bss);
    345 
    346 	/* Symbols. */
    347 	*esymp = paddr;
    348 	paddr = (int *)((void *)paddr + hdr->a_text + hdr->a_data + hdr->a_bss);
    349 	*paddr++ = hdr->a_syms;
    350 	if (hdr->a_syms) {
    351 		printf(" [%lu", hdr->a_syms);
    352 		if (read(fd, paddr, hdr->a_syms) != hdr->a_syms) {
    353 			printf("read symbols: %s\n", strerror(errno));
    354 			return (1);
    355 		}
    356 		paddr = (int *)((void *)paddr + hdr->a_syms);
    357 		if (read(fd, &n, sizeof(int)) != sizeof(int)) {
    358 			printf("read symbols: %s\n", strerror(errno));
    359 			return (1);
    360 		}
    361 		if (OF_claim((void *)paddr, n + sizeof(int), 0) == (void *)-1)
    362 			panic("cannot claim memory");
    363 		*paddr++ = n;
    364 		if (read(fd, paddr, n - sizeof(int)) != n - sizeof(int)) {
    365 			printf("read symbols: %s\n", strerror(errno));
    366 			return (1);
    367 		}
    368 		printf("+%d]", n - sizeof(int));
    369 		*esymp = paddr + (n - sizeof(int));
    370 	}
    371 
    372 	*entryp = hdr->a_entry;
    373 	return (0);
    374 }
    375 #endif /* SPARC_BOOT_AOUT */
    376 
    377 #ifdef SPARC_BOOT_ELF
    378 #if 1
    379 /* New style */
    380 
    381 #ifdef ELFSIZE
    382 #undef ELFSIZE
    383 #endif
    384 
    385 #define ELFSIZE	32
    386 #include "elfXX_exec.c"
    387 
    388 #undef ELFSIZE
    389 #define ELFSIZE	64
    390 #include "elfXX_exec.c"
    391 
    392 #else
    393 /* Old style */
    394 int
    395 elf32_exec(fd, elf, entryp, ssymp, esymp)
    396 	int fd;
    397 	Elf32_Ehdr *elf;
    398 	u_int64_t *entryp;
    399 	void **ssymp;
    400 	void **esymp;
    401 {
    402 	Elf32_Shdr *shp;
    403 	Elf32_Off off;
    404 	void *addr;
    405 	size_t size;
    406 	int i, first = 1;
    407 	long align;
    408 	int n;
    409 
    410 	/*
    411 	 * Don't display load address for ELF; it's encoded in
    412 	 * each section.
    413 	 */
    414 #ifdef DEBUG
    415 	printf("elf_exec: ");
    416 #endif
    417 	printf("Booting %s\n", opened_name);
    418 
    419 	for (i = 0; i < elf->e_phnum; i++) {
    420 		Elf32_Phdr phdr;
    421 		(void)lseek(fd, elf->e_phoff + sizeof(phdr) * i, SEEK_SET);
    422 		if (read(fd, (void *)&phdr, sizeof(phdr)) != sizeof(phdr)) {
    423 			printf("read phdr: %s\n", strerror(errno));
    424 			return (1);
    425 		}
    426 		if (phdr.p_type != PT_LOAD ||
    427 		    (phdr.p_flags & (PF_W|PF_X)) == 0)
    428 			continue;
    429 
    430 		/* Read in segment. */
    431 		printf("%s%lu@0x%lx", first ? "" : "+", phdr.p_filesz,
    432 		    (u_long)phdr.p_vaddr);
    433 		(void)lseek(fd, phdr.p_offset, SEEK_SET);
    434 
    435 		/*
    436 		 * If the segment's VA is aligned on a 4MB boundary, align its
    437 		 * request 4MB aligned physical memory.  Otherwise use default
    438 		 * alignment.
    439 		 */
    440 		align = phdr.p_align;
    441 		if ((phdr.p_vaddr & (4*MEG-1)) == 0)
    442 			align = 4*MEG;
    443 		if (OF_claim((void *)phdr.p_vaddr, phdr.p_memsz, phdr.p_align) ==
    444 		    (void *)-1)
    445 			panic("cannot claim memory");
    446 		if (read(fd, (void *)phdr.p_vaddr, phdr.p_filesz) !=
    447 		    phdr.p_filesz) {
    448 			printf("read segment: %s\n", strerror(errno));
    449 			return (1);
    450 		}
    451 		syncicache((void *)phdr.p_vaddr, phdr.p_filesz);
    452 
    453 		/* Zero BSS. */
    454 		if (phdr.p_filesz < phdr.p_memsz) {
    455 			printf("+%lu@0x%lx", phdr.p_memsz - phdr.p_filesz,
    456 			    (u_long)(phdr.p_vaddr + phdr.p_filesz));
    457 			bzero((void*)phdr.p_vaddr + phdr.p_filesz,
    458 			    phdr.p_memsz - phdr.p_filesz);
    459 		}
    460 		first = 0;
    461 	}
    462 
    463 	printf(" \n");
    464 
    465 #if 1 /* I want to rethink this... --thorpej (at) NetBSD.org */
    466 	/*
    467 	 * Compute the size of the symbol table.
    468 	 */
    469 	size = sizeof(Elf32_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr));
    470 	shp = addr = alloc(elf->e_shnum * sizeof(Elf32_Shdr));
    471 	(void)lseek(fd, elf->e_shoff, SEEK_SET);
    472 	if (read(fd, addr, elf->e_shnum * sizeof(Elf32_Shdr)) !=
    473 	    elf->e_shnum * sizeof(Elf32_Shdr)) {
    474 		printf("read section headers: %s\n", strerror(errno));
    475 		return (1);
    476 	}
    477 	for (i = 0; i < elf->e_shnum; i++, shp++) {
    478 		if (shp->sh_type == SHT_NULL)
    479 			continue;
    480 		if (shp->sh_type != SHT_SYMTAB
    481 		    && shp->sh_type != SHT_STRTAB) {
    482 			shp->sh_offset = 0;
    483 			shp->sh_type = SHT_NOBITS;
    484 			continue;
    485 		}
    486 		size += shp->sh_size;
    487 	}
    488 	shp = addr;
    489 
    490 	/*
    491 	 * Reserve memory for the symbols.
    492 	 */
    493 	if ((addr = OF_claim(0, size, NBPG)) == (void *)-1)
    494 		panic("no space for symbol table");
    495 
    496 	/*
    497 	 * Copy the headers.
    498 	 */
    499 	elf->e_phoff = 0;
    500 	elf->e_shoff = sizeof(Elf32_Ehdr);
    501 	elf->e_phentsize = 0;
    502 	elf->e_phnum = 0;
    503 	bcopy(elf, addr, sizeof(Elf32_Ehdr));
    504 	bcopy(shp, addr + sizeof(Elf32_Ehdr), elf->e_shnum * sizeof(Elf32_Shdr));
    505 	free(shp, elf->e_shnum * sizeof(Elf32_Shdr));
    506 	*ssymp = addr;
    507 
    508 	/*
    509 	 * Now load the symbol sections themselves.
    510 	 */
    511 	shp = addr + sizeof(Elf32_Ehdr);
    512 	addr += sizeof(Elf32_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr));
    513 	off = sizeof(Elf32_Ehdr) + (elf->e_shnum * sizeof(Elf32_Shdr));
    514 	for (first = 1, i = 0; i < elf->e_shnum; i++, shp++) {
    515 		if (shp->sh_type == SHT_SYMTAB
    516 		    || shp->sh_type == SHT_STRTAB) {
    517 			if (first)
    518 				printf("symbols @ 0x%lx ", (u_long)addr);
    519 			printf("%s%d", first ? "" : "+", shp->sh_size);
    520 			(void)lseek(fd, shp->sh_offset, SEEK_SET);
    521 			if (read(fd, addr, shp->sh_size) != shp->sh_size) {
    522 				printf("read symbols: %s\n", strerror(errno));
    523 				return (1);
    524 			}
    525 			addr += (shp->sh_size+3)&(~3);
    526 			shp->sh_offset = off;
    527 			off += (shp->sh_size+3)&(~3);
    528 			first = 0;
    529 		}
    530 	}
    531 	*esymp = addr;
    532 #endif /* 0 */
    533 
    534 	*entryp = elf->e_entry;
    535 	return (0);
    536 }
    537 #endif
    538 #endif /* SPARC_BOOT_ELF */
    539 
    540 void
    541 main()
    542 {
    543 	extern char bootprog_name[], bootprog_rev[],
    544 	    bootprog_maker[], bootprog_date[];
    545 	int chosen;
    546 	char bootline[512];		/* Should check size? */
    547 	char *cp;
    548 	int i, fd;
    549 
    550 	/* Initialize kernelname */
    551 	kernelname = kernels[0];
    552 
    553 	printf("\r>> %s, Revision %s\n", bootprog_name, bootprog_rev);
    554 	printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
    555 
    556 	/*
    557 	 * Get the boot arguments from Openfirmware
    558 	 */
    559 	if ((chosen = OF_finddevice("/chosen")) == -1
    560 	    || OF_getprop(chosen, "bootpath", bootdev, sizeof bootdev) < 0
    561 	    || OF_getprop(chosen, "bootargs", bootline, sizeof bootline) < 0) {
    562 		printf("Invalid Openfirmware environment\n");
    563 		exit(0);
    564 	}
    565 	/*prom2boot(bootdev);*/
    566 	kernelname = kernels[0];
    567 	parseargs(bootline, &boothowto);
    568 	for (i=0;;) {
    569 		kernelname = kernels[i];
    570 		if (boothowto & RB_ASKNAME) {
    571 			printf("Boot: ");
    572 			gets(bootline);
    573 			parseargs(bootline, &boothowto);
    574 		}
    575 		if ((fd = open(bootline, 0)) >= 0)
    576 			break;
    577 		if (errno)
    578 			printf("open %s: %s\n", opened_name, strerror(errno));
    579 		/*
    580 		 * if we have are not in askname mode, and we aren't using the
    581 		 * prom bootfile, try the next one (if it exits).  otherwise,
    582 		 * go into askname mode.
    583 		 */
    584 		if ((boothowto & RB_ASKNAME) == 0 &&
    585 		    i != -1 && kernels[++i]) {
    586 			printf(": trying %s...\n", kernels[i]);
    587 		} else {
    588 			printf("\n");
    589 			boothowto |= RB_ASKNAME;
    590 		}
    591 	}
    592 #ifdef	__notyet__
    593 	OF_setprop(chosen, "bootpath", opened_name, strlen(opened_name) + 1);
    594 	cp = bootline;
    595 #else
    596 	strcpy(bootline, opened_name);
    597 	cp = bootline + strlen(bootline);
    598 	*cp++ = ' ';
    599 #endif
    600 	*cp = '-';
    601 	if (boothowto & RB_ASKNAME)
    602 		*++cp = 'a';
    603 	if (boothowto & RB_SINGLE)
    604 		*++cp = 's';
    605 	if (boothowto & RB_KDB)
    606 		*++cp = 'd';
    607 	if (*cp == '-')
    608 #ifdef	__notyet__
    609 		*cp = 0;
    610 #else
    611 		*--cp = 0;
    612 #endif
    613 	else
    614 		*++cp = 0;
    615 #ifdef	__notyet__
    616 	OF_setprop(chosen, "bootargs", bootline, strlen(bootline) + 1);
    617 #endif
    618 	/* XXX void, for now */
    619 #ifdef DEBUG
    620 	if (debug)
    621 		printf("main: Calling loadfile(fd, %s)\n", bootline);
    622 #endif
    623 	(void)loadfile(fd, bootline);
    624 
    625 	_rtt();
    626 }
    627