1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/fcntl.h>
31 #include <sys/obpdefs.h>
32 #include <sys/reboot.h>
33 #include <sys/promif.h>
34 #include <sys/stat.h>
35 #include <sys/bootvfs.h>
36 #include <sys/platnames.h>
37 #include <sys/salib.h>
38 #include <sys/elf.h>
39 #include <sys/link.h>
40 #include <sys/auxv.h>
41 #include <sys/boot_policy.h>
42 #include <sys/boot_redirect.h>
43 #include <sys/bootconf.h>
44 #include <sys/boot.h>
45 #include "boot_plat.h"
46 #include "ramdisk.h"
47 
48 #define	SUCCESS		0
49 #define	FAILURE		-1
50 
51 #ifdef DEBUG
52 extern int debug = 0;
53 #else
54 static const int debug = 0;
55 #endif
56 
57 #define	dprintf		if (debug) printf
58 
59 char		*def_boot_archive = "boot_archive";
60 char		*def_miniroot = "miniroot";
61 extern char	cmd_line_boot_archive[];
62 
63 extern int	openfile(char *filename);
64 
65 static int
66 read_and_boot_ramdisk(int fd)
67 {
68 	struct stat	st;
69 	caddr_t		virt;
70 	size_t		size;
71 	extern		ssize_t xread(int, char *, size_t);
72 
73 	if ((fstat(fd, &st) != 0) ||
74 	    ((virt = create_ramdisk(RD_ROOTFS, st.st_size, NULL)) == NULL))
75 		return (-1);
76 
77 	dprintf("reading boot archive ...\n");
78 	if ((size = xread(fd, (char *)virt, st.st_size)) != st.st_size) {
79 		(void) printf("Error reading boot archive, bytes read = %ld, "
80 		    "filesize = %ld\n", (long)size, (long)st.st_size);
81 		destroy_ramdisk(RD_ROOTFS);
82 		return (-1);
83 	}
84 
85 	boot_ramdisk(RD_ROOTFS);
86 	/* NOT REACHED */
87 	return (0);	/* to make cc happy */
88 }
89 
90 
91 static void
92 post_mountroot_nfs(void)
93 {
94 	int	fd;
95 	char	*fn;
96 	char	tmpname[MAXPATHLEN];
97 
98 	for (;;) {
99 		fn = NULL;
100 		if (boothowto & RB_ASKNAME) {
101 			fn = (cmd_line_boot_archive[0] != '\0') ?
102 			    cmd_line_boot_archive : def_boot_archive;
103 			printf("Enter filename [%s]: ", fn);
104 			(void) cons_gets(tmpname, sizeof (tmpname));
105 			if (tmpname[0] != '\0')
106 				fn = tmpname;
107 		}
108 
109 		if (boothowto & RB_HALT) {
110 			printf("Boot halted.\n");
111 			prom_enter_mon();
112 		}
113 
114 		if (fn != NULL)
115 			fd = openfile(fn);
116 		else if (cmd_line_boot_archive[0] != '\0') {
117 			fn = cmd_line_boot_archive;
118 			fd = openfile(fn);
119 		} else {
120 			fn = def_boot_archive;
121 			if ((fd = openfile(fn)) == FAILURE) {
122 				fn = def_miniroot;
123 				fd = openfile(fn);
124 			}
125 		}
126 
127 		if (fd == FAILURE) {
128 			if (fn != def_miniroot)
129 				printf("cannot open %s\n", fn);
130 			else
131 				printf("cannot open neither %s nor %s\n",
132 				    def_boot_archive, def_miniroot);
133 		} else {
134 			/*
135 			 * this function does not return if successful.
136 			 */
137 			(void) read_and_boot_ramdisk(fd);
138 
139 			printf("boot failed\n");
140 			(void) close(fd);
141 		}
142 		boothowto |= RB_ASKNAME;
143 	}
144 }
145 
146 
147 /*
148  * bpath is the boot device path buffer.
149  * bargs is the boot arguments buffer.
150  */
151 /*ARGSUSED*/
152 int
153 bootprog(char *bpath, char *bargs, boolean_t user_specified_filename)
154 {
155 	systype = set_fstype(v2path, bpath);
156 
157 	if (verbosemode) {
158 		printf("device path '%s'\n", bpath);
159 		if (strcmp(bpath, v2path) != 0)
160 			printf("client path '%s'\n", v2path);
161 	}
162 
163 	if (mountroot(bpath) != SUCCESS)
164 		prom_panic("Could not mount filesystem.");
165 
166 	/*
167 	 * kernname (default-name) might have changed if mountroot() called
168 	 * boot_nfs_mountroot(), and it called set_default_filename().
169 	 */
170 	if (!user_specified_filename)
171 		(void) strcpy(filename, kernname);
172 
173 	if (verbosemode)
174 		printf("standalone = `%s', args = `%s'\n", filename, bargs);
175 
176 	set_client_bootargs(filename, bargs);
177 
178 	post_mountroot_nfs();
179 
180 	return (1);
181 }
182