boot_plat.c revision db9ce1c953f094d292df951aada6b8a85e1ff103
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/platnames.h>
#include <sys/boot_policy.h>
#include <sys/boot_redirect.h>
#include <sys/bootconf.h>
#include "boot_plat.h"
#define SUCCESS 0
#define FAILURE -1
#ifdef DEBUG
int debug = 0;
#else
static const int debug = 0;
#endif
#ifdef DEBUG_LISTS
#endif
extern void kmem_init(void);
extern void *kmem_alloc(size_t, int);
extern void get_boot_args(char *buf);
extern void setup_bootops(void);
extern void exitto(int (*entrypoint)());
/*
* filename is the name of the standalone we're going to execute.
*/
char filename[MAXPATHLEN];
/*
* We enable the cache by default
* but boot -n will leave it alone...
* that is, we use whatever state the PROM left it in.
*/
char *mfg_name;
int cache_state = 1;
char filename2[MAXPATHLEN];
int boothowto = 0;
int verbosemode = 0;
/*
* Copy filename and bargs into v2args_buf, which will be exported as the
* boot-args boot property. We should probably warn the user if anything gets
* cut off.
*/
void
{
int i = 0;
const char *s;
s = filename;
v2args_buf[i++] = *s++;
if (i >= V2ARGS_BUF_SZ - 2) {
/* Not enough room for a space and any of bargs. */
v2args_buf[i] = '\0';
return;
}
v2args_buf[i++] = ' ';
s = bargs;
v2args_buf[i++] = *s++;
v2args_buf[i] = '\0';
}
/*
* The slice redirection file is used on the install CD
*/
static int
read_redirect(char *redirect)
{
int fd;
char slicec;
/*
* Read the character out of the file - this is the
* slice to use, in base 36.
*/
if (nread == 1)
}
*redirect = '\0';
return (nread == 1);
}
void
{
int (*go2)();
int fd;
/* Save the bootfile, just in case we need it again */
for (;;) {
if (boothowto & RB_ASKNAME) {
char tmpname[MAXPATHLEN];
if (tmpname[0] != '\0')
}
printf("Boot halted.\n");
}
/*
* There are many reasons why this might've
* happened .. but one of them is that we're
* on the installation CD, and we need to
* revector ourselves off to a different partition
* of the CD. Check for the redirection file.
*/
/* restore bootfile */
return;
/*NOTREACHED*/
}
boothowto |= RB_ASKNAME;
/* restore bootfile */
continue;
}
(int(*)()) -1) {
} else {
printf("boot failed\n");
boothowto |= RB_ASKNAME;
continue;
}
printf("Boot halted before exit to 0x%p.\n",
(void *)go2);
}
(void *)elfbootvecELF64);
}
}
/*ARGSUSED*/
static int
{
}
/*
* Open the given filename, expanding to it's
* platform-dependent location if necessary.
*
* Boot supports OBP and IEEE1275.
*
* XXX: Move side effects out of this function!
*/
int
{
static char *fullpath;
static int once;
int fd;
if (once == 0) {
++once;
/*
* Setup exported 'boot' properties: 'mfg-name'.
* XXX: This shouldn't be a side effect of openfile().
*/
mfg_name = get_mfg_name();
}
if (*filename == '/') {
return (fd);
}
if (fd == -1)
return (-1);
/*
* Copy back the name we actually found
*/
return (fd);
}
/*
* Get the boot arguments from the PROM and split it into filename and
* options components.
*
* As per IEEE1275 and boot(1M), the boot arguments will have the syntax
* "[filename] [-options]". If filename is specified, it is copied into the
* first buffer. (Otherwise, the buffer is left alone.) The rest of the string
* is copied into the second buffer.
*/
static void
int bargs_buf_sz)
{
const char *tp = prom_bootargs();
*bargs_buf = '\0';
return;
}
/*
* If we don't have an option indicator, then we
* already have our filename prepended.
*/
int i;
/*
* Copy the filename into fname_buf.
*/
if (i >= fname_buf_sz) {
printf("boot: boot filename too long!\n");
printf("boot halted.\n");
/*NOTREACHED*/
} else {
*fname_buf = '\0';
}
}
/* The rest of the line is the options. */
--bargs_buf_sz;
}
*bargs_buf = '\0';
if (bargs_buf_sz == 1) {
printf("boot: boot arguments too long!\n");
printf("boot halted.\n");
/*NOTREACHED*/
}
}
{
char *options;
return (B_FALSE);
return (B_TRUE);
/*
* For Infiniband, network device names will be of the
* XXX is typically /pci@8,700000/pci@1. The device_type
* property will be "ib".
*/
#define SEARCHSTRING ",protocol=ip"
return (B_TRUE);
NULL) {
char nextc;
return (B_TRUE);
options += SEARCHSTRLEN;
}
}
}
return (B_FALSE);
}
/*
* Hook for modifying the OS boot path. This hook allows us to handle
* device arguments that the OS can't handle.
*/
void
mangle_os_bootpath(char *bpath)
{
char *stripped_pathname;
return;
/*
* The OS can't handle network device arguments
* eg: boot net:promiscuous,speed=100,duplex=full
* So, we remove any argument strings in the device
* pathname we hand off to the OS for network devices.
*
* Internally, within boot, bpath is used to access
* the device, but v2path (as the boot property "boot-path")
* is the pathname passed to the OS.
*/
}
/*
* Given the boot path in the native firmware format use
* the redirection string to mutate the boot path to the new device.
* Fix up the 'v2path' so that it matches the new firmware path.
*/
void
{
/*
* If the redirection character doesn't fall in this
* range, something went horribly wrong.
*/
return;
}
/*
* Handle fully qualified OpenBoot pathname.
*/
if (*p == ':')
break;
if (*p++ == ':') {
/*
* Convert slice number to partition 'letter'.
*/
*p = '\0';
return;
}
prom_panic("redirect_boot_path: mangled boot path!");
}
#define PROM_VERS_MAX_LEN 64
void
system_check(void)
{
char buf[PROM_VERS_MAX_LEN];
if (cpu_is_ultrasparc_1()) {
printf("UltraSPARC I processors are not supported by this "
"release of Solaris.\n");
}
printf("The firmware on this system does not support the 64-bit"
" OS.\n\tPlease upgrade to at least the following version:"
"\n\n\t%s\n", buf);
}
}
/*
* Reads in the standalone (client) program and jumps to it. If this
* attempt fails, prints "boot failed" and returns to its caller.
*
* It will try to determine if it is loading a Unix file by
* looking at what should be the magic number. If it makes
* sense, it will use it; otherwise it jumps to the first
* address of the blocks that it reads in.
*
* This new boot program will open a file, read the ELF header,
* attempt to allocate and map memory at the location at which
* the client desires to be linked, and load the program at
* that point. It will then jump there.
*/
/*ARGSUSED*/
int
{
/*
* bpath is the boot device path buffer.
* bargs is the boot arguments buffer.
*/
fiximp();
system_check();
#ifdef HALTBOOT
#endif /* HALTBOOT */
#ifdef DEBUG_LISTS
dprintf("Physmem avail:\n");
dprintf("Virtmem avail:\n");
dprintf("Phys installed:\n");
#endif /* DEBUG_LISTS */
/*
* Initialize the default filename (exported as "default-name" and
* used by kadb).
*/
/*
* Parse the arguments ASAP in case there are any flags which may
* affect execution.
*/
/*
* filename is the path to the standalone. Initialize it to the empty
* string so we can tell whether the user specified it in the
* arguments.
*/
filename[0] = '\0';
/*
* Fetch the boot arguments from the PROM and split the filename off
* if it's there.
*/
/*
* kadb was delivered as a standalone, and as such, people got used to
* typing `boot kadb'. kmdb isn't a standalone - it is loaded by krtld
* as just another kernel module. For compatibility, though, when we
* see an attempt to `boot kadb' or `boot kmdb', we'll transform that
* into a `boot -k' (or equivalent).
*/
}
/* Fetch the boot path from the PROM. */
/*
* *v2path will be exported to the standalone as the boot-path boot
* property.
*/
/*
* Our memory lists should be "up" by this time
*/
/*
* If bpath is a network card, set v2path to a copy of bpath with the
* options stripped off.
*/
#ifdef sun4u
#endif
/*NOTREACHED*/
}
return (0);
}