/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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/types.h>
#include <sys/param.h>
#include <sys/fcntl.h>
#include <sys/obpdefs.h>
#include <sys/reboot.h>
#include <sys/promif.h>
#include <sys/stat.h>
#include <sys/bootvfs.h>
#include <sys/platnames.h>
#include <sys/salib.h>
#include <sys/elf.h>
#include <sys/link.h>
#include <sys/auxv.h>
#include <sys/boot_policy.h>
#include <sys/boot_redirect.h>
#include <sys/bootconf.h>
#include <sys/boot.h>
#include "boot_plat.h"
#include "ramdisk.h"
#define SUCCESS 0
#define FAILURE -1
#ifdef DEBUG
extern int debug = 0;
#else
static const int debug = 0;
#endif
#define dprintf if (debug) printf
char *def_boot_archive = "boot_archive";
char *def_miniroot = "miniroot";
extern char cmd_line_boot_archive[];
extern int openfile(char *filename);
static int
read_and_boot_ramdisk(int fd)
{
struct stat st;
caddr_t virt;
size_t size;
extern ssize_t xread(int, char *, size_t);
if ((fstat(fd, &st) != 0) ||
((virt = create_ramdisk(RD_ROOTFS, st.st_size, NULL)) == NULL))
return (-1);
dprintf("reading boot archive ...\n");
if ((size = xread(fd, (char *)virt, st.st_size)) != st.st_size) {
(void) printf("Error reading boot archive, bytes read = %ld, "
"filesize = %ld\n", (long)size, (long)st.st_size);
destroy_ramdisk(RD_ROOTFS);
return (-1);
}
boot_ramdisk(RD_ROOTFS);
/* NOT REACHED */
return (0); /* to make cc happy */
}
static void
post_mountroot_nfs(void)
{
int fd;
char *fn;
char tmpname[MAXPATHLEN];
for (;;) {
fn = NULL;
if (boothowto & RB_ASKNAME) {
char ctmpname[MAXPATHLEN];
fn = (cmd_line_boot_archive[0] != '\0') ?
cmd_line_boot_archive : def_boot_archive;
/* Avoid buffer overrun */
(void) strncpy(tmpname, fn, strlen(fn)+1);
fn = tmpname;
printf("Enter filename [%s]: ", fn);
(void) cons_gets(ctmpname, sizeof (ctmpname));
if (ctmpname[0] != '\0') {
(void) strncpy(tmpname, ctmpname,
strlen(ctmpname)+1);
fn = tmpname;
}
}
if (boothowto & RB_HALT) {
printf("Boot halted.\n");
prom_enter_mon();
}
if (fn != NULL) {
fd = openfile(fn);
} else if (cmd_line_boot_archive[0] != '\0') {
(void) strncpy(tmpname, cmd_line_boot_archive,
strlen(cmd_line_boot_archive)+1);
fn = tmpname;
fd = openfile(fn);
} else {
(void) strncpy(tmpname, def_boot_archive,
strlen(def_boot_archive)+1);
fn = tmpname;
if ((fd = openfile(fn)) == FAILURE) {
(void) strncpy(tmpname, def_miniroot,
strlen(def_miniroot)+1);
fn = tmpname;
fd = openfile(fn);
}
}
if (fn != tmpname || tmpname[0] == '\0') {
printf("Possible buffer overrun, "
"entering boot prompt\n");
prom_enter_mon();
}
if (fd == FAILURE) {
if (strncmp(fn, def_miniroot,
strlen(def_miniroot)+1) != 0)
printf("cannot open %s\n", fn);
else
printf("cannot open neither %s nor %s\n",
def_boot_archive, def_miniroot);
} else {
/*
* this function does not return if successful.
*/
(void) read_and_boot_ramdisk(fd);
printf("boot failed\n");
(void) close(fd);
}
boothowto |= RB_ASKNAME;
}
}
/*
* bpath is the boot device path buffer.
* bargs is the boot arguments buffer.
*/
/*ARGSUSED*/
int
bootprog(char *bpath, char *bargs, boolean_t user_specified_filename)
{
systype = set_fstype(v2path, bpath);
if (verbosemode) {
printf("device path '%s'\n", bpath);
if (strcmp(bpath, v2path) != 0)
printf("client path '%s'\n", v2path);
}
if (mountroot(bpath) != SUCCESS)
prom_panic("Could not mount filesystem.");
/*
* kernname (default-name) might have changed if mountroot() called
* boot_nfs_mountroot(), and it called set_default_filename().
*/
if (!user_specified_filename)
(void) strcpy(filename, kernname);
if (verbosemode)
printf("standalone = `%s', args = `%s'\n", filename, bargs);
set_client_bootargs(filename, bargs);
post_mountroot_nfs();
return (1);
}