/* $NetBSD: boot.c,v 1.35 2017/09/15 13:25:34 martin Exp $ */
/*
* Copyright (c) 1997, 1999 Eduardo E. Horvath. All rights reserved.
* Copyright (c) 1997 Jason R. Thorpe. All rights reserved.
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
* Copyright (C) 1995, 1996 TooLs GmbH.
* All rights reserved.
*
* ELF support derived from NetBSD/alpha's boot loader, written
* by Christopher G. Demetriou.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* First try for the boot code
*
* Input syntax is:
* [promdev[{:|,}partition]]/[filename] [flags]
*/
typedef void (*entry_t)(long o0, long bootargs, long bootsize, long o3,
long ofw);
/*
* Boot device is derived from ROM provided information, or if there is none,
* this list is used in sequence, to find a kernel.
*/
const char *kernelnames[] = {
"netbsd",
"netbsd.gz",
"netbsd.old",
"netbsd.old.gz",
"onetbsd",
"onetbsd.gz",
"vmunix ",
#ifdef notyet
"netbsd.pl ",
"netbsd.pl.gz ",
"netbsd.el ",
"netbsd.el.gz ",
#endif
NULL
};
/*
* The older (those relying on ofwboot v1.8 and earlier) kernels can't handle
* ksyms information unless it resides in a dedicated memory allocated from
* PROM and aligned on NBPG boundary. This is because the kernels calculate
* their ends on their own, they use address of 'end[]' reference which follows
* text segment. Ok, allocate some memory from PROM and copy symbol information
* over there.
*/
static void
ksyms_copyout(void **ssym, void **esym)
{
uint8_t *addr;
int kssize = (int)(long)((char *)*esym - (char *)*ssym + 1);
/* Adjust ksyms pointers, if needed. */
if (COMPAT_BOOT(marks) || compatmode) {
ksyms_copyout(&ssym, &esym);
}
freeall();
/*
* When we come in args consists of a pointer to the boot
* string. We need to fix it so it takes into account
* other params such as romp.
*/
/*
* Stash pointer to end of symbol table after the argument
* strings.
*/
l = strlen(args) + 1;
memcpy(args + l, &esym, sizeof(esym));
l += sizeof(esym);
/*
* Tell the kernel we're an OpenFirmware system.
*/
machine_tag = SPARC_MACHINE_OPENFIRMWARE;
memcpy(args + l, &machine_tag, sizeof(machine_tag));
l += sizeof(machine_tag);
/*
* Since we don't need the boot string (we can get it from /chosen)
* we won't pass it in. Just pass in esym and magic #
*/
newargs[0] = SPARC_MACHINE_OPENFIRMWARE;
newargs[1] = (long)esym;
newargs[2] = (long)ssym;
newargs[3] = (long)(void*)bootinfo;
args = (char *)newargs;
l = sizeof(newargs);
/* if -D is set then pause in the PROM. */
if (debug > 1) callrom();
/*
* Jump directly to the kernel. Solaris kernel and Sun PROM
* flash updates expect ROMP vector in %o0, so we do. Format
* of other parameters and their order reflect OF_chain()
* symantics since this is what older NetBSD kernels rely on.
* (see sparc64/include/bootinfo.h for specification).
*/
DPRINTF(("jump_to_kernel(%lx, %lx, %lx, %lx, %lx) @ %p\n", (long)ofw,
(long)args, (long)l, (long)ofw, (long)ofw,
(void*)marks[MARK_ENTRY]));
(*(entry_t)marks[MARK_ENTRY])((long)ofw, (long)args, (long)l, (long)ofw,
(long)ofw);
printf("Returned from kernel entry point!\n");
}
static void
start_kernel(char *kernel, char *bootline, void *ofw, int isfloppy,
int boothowto)
{
int fd;
u_long marks[MARK_MAX] = {0};
int flags = LOAD_ALL;
if (isfloppy)
flags &= ~LOAD_BACKWARDS;
/*
* First, load headers using default allocator and check whether kernel
* entry address matches kernel text load address. If yes, this is the
* old kernel designed for ofwboot v1.8 and therefore it must be mapped
* by PROM. Otherwise, map the kernel with 4MB permanent pages.
*/
loadfile_set_allocator(LOADFILE_NOP_ALLOCATOR);
if ( (fd = loadfile(kernel, marks, LOAD_HDR|COUNT_TEXT)) != -1) {
if (COMPAT_BOOT(marks) || compatmode) {
(void)printf("[c] ");
loadfile_set_allocator(LOADFILE_OFW_ALLOCATOR);
} else {
loadfile_set_allocator(LOADFILE_MMU_ALLOCATOR);
}
(void)printf("Loading %s: ", kernel);
if (*kernel == '\0') {
if (kernelnames[i] == NULL) {
boothowto |= RB_ASKNAME;
continue;
}
strncpy(kernel, kernelnames[i++], PROM_MAX_PATH);
} else if (i == 0) {
/*
* Kernel name was passed via command line -- ask user
* again if requested image fails to boot.
*/
boothowto |= RB_ASKNAME;
}
/*
* Try next name from kernel name list if not in askname mode,
* enter askname on reaching list's end.
*/
if ((boothowto & RB_ASKNAME) == 0 && (kernelnames[i] != NULL)) {
printf(": trying %s...\n", kernelnames[i]);
} else {
printf("\n");
boothowto |= RB_ASKNAME;
}
}
(void)printf("Boot failed! Exiting to the Firmware.\n");
prom_halt();
}