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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <sys/fcntl.h>
30 #include <sys/obpdefs.h>
31 #include <sys/reboot.h>
32 #include <sys/promif.h>
33 #include <sys/stat.h>
34 #include <sys/bootvfs.h>
35 #include <sys/platnames.h>
36 #include <sys/salib.h>
37 #include <sys/elf.h>
38 #include <sys/link.h>
39 #include <sys/auxv.h>
40 #include <sys/boot_policy.h>
41 #include <sys/boot_redirect.h>
42 #include <sys/bootconf.h>
43 #include <sys/boot.h>
44 #include "boot_plat.h"
45 #include "ramdisk.h"
46 
47 #define	SUCCESS		0
48 #define	FAILURE		-1
49 
50 #ifdef DEBUG
51 extern int debug = 0;
52 #else
53 static const int debug = 0;
54 #endif
55 
56 #define	dprintf		if (debug) printf
57 
58 char		*def_boot_archive = "boot_archive";
59 char		*def_miniroot = "miniroot";
60 extern char	cmd_line_boot_archive[];
61 
62 extern int	openfile(char *filename);
63 
64 static int
read_and_boot_ramdisk(int fd)65 read_and_boot_ramdisk(int fd)
66 {
67 	struct stat	st;
68 	caddr_t		virt;
69 	size_t		size;
70 	extern		ssize_t xread(int, char *, size_t);
71 
72 	if ((fstat(fd, &st) != 0) ||
73 	    ((virt = create_ramdisk(RD_ROOTFS, st.st_size, NULL)) == NULL))
74 		return (-1);
75 
76 	dprintf("reading boot archive ...\n");
77 	if ((size = xread(fd, (char *)virt, st.st_size)) != st.st_size) {
78 		(void) printf("Error reading boot archive, bytes read = %ld, "
79 		    "filesize = %ld\n", (long)size, (long)st.st_size);
80 		destroy_ramdisk(RD_ROOTFS);
81 		return (-1);
82 	}
83 
84 	boot_ramdisk(RD_ROOTFS);
85 	/* NOT REACHED */
86 	return (0);	/* to make cc happy */
87 }
88 
89 
90 static void
post_mountroot_nfs(void)91 post_mountroot_nfs(void)
92 {
93 	int	fd;
94 	char	*fn;
95 	char	tmpname[MAXPATHLEN];
96 
97 	for (;;) {
98 		fn = NULL;
99 		if (boothowto & RB_ASKNAME) {
100 			char ctmpname[MAXPATHLEN];
101 
102 			fn = (cmd_line_boot_archive[0] != '\0') ?
103 			    cmd_line_boot_archive : def_boot_archive;
104 
105 			/* Avoid buffer overrun */
106 			(void) strncpy(tmpname, fn, strlen(fn)+1);
107 			fn = tmpname;
108 
109 			printf("Enter filename [%s]: ", fn);
110 			(void) cons_gets(ctmpname, sizeof (ctmpname));
111 			if (ctmpname[0] != '\0') {
112 				(void) strncpy(tmpname, ctmpname,
113 				    strlen(ctmpname)+1);
114 				fn = tmpname;
115 			}
116 		}
117 
118 		if (boothowto & RB_HALT) {
119 			printf("Boot halted.\n");
120 			prom_enter_mon();
121 		}
122 
123 
124 		if (fn != NULL) {
125 			fd = openfile(fn);
126 		} else if (cmd_line_boot_archive[0] != '\0') {
127 			(void) strncpy(tmpname, cmd_line_boot_archive,
128 			    strlen(cmd_line_boot_archive)+1);
129 			fn = tmpname;
130 			fd = openfile(fn);
131 		} else {
132 			(void) strncpy(tmpname, def_boot_archive,
133 			    strlen(def_boot_archive)+1);
134 			fn = tmpname;
135 			if ((fd = openfile(fn)) == FAILURE) {
136 				(void) strncpy(tmpname, def_miniroot,
137 				    strlen(def_miniroot)+1);
138 				fn = tmpname;
139 				fd = openfile(fn);
140 			}
141 		}
142 
143 		if (fn != tmpname || tmpname[0] == '\0') {
144 			printf("Possible buffer overrun, "
145 			    "entering boot prompt\n");
146 			prom_enter_mon();
147 		}
148 
149 
150 		if (fd == FAILURE) {
151 			if (strncmp(fn, def_miniroot,
152 			    strlen(def_miniroot)+1) != 0)
153 				printf("cannot open %s\n", fn);
154 			else
155 				printf("cannot open neither %s nor %s\n",
156 				    def_boot_archive, def_miniroot);
157 		} else {
158 			/*
159 			 * this function does not return if successful.
160 			 */
161 			(void) read_and_boot_ramdisk(fd);
162 
163 			printf("boot failed\n");
164 			(void) close(fd);
165 		}
166 		boothowto |= RB_ASKNAME;
167 	}
168 }
169 
170 
171 /*
172  * bpath is the boot device path buffer.
173  * bargs is the boot arguments buffer.
174  */
175 /*ARGSUSED*/
176 int
bootprog(char * bpath,char * bargs,boolean_t user_specified_filename)177 bootprog(char *bpath, char *bargs, boolean_t user_specified_filename)
178 {
179 	systype = set_fstype(v2path, bpath);
180 
181 	if (verbosemode) {
182 		printf("device path '%s'\n", bpath);
183 		if (strcmp(bpath, v2path) != 0)
184 			printf("client path '%s'\n", v2path);
185 	}
186 
187 	if (mountroot(bpath) != SUCCESS)
188 		prom_panic("Could not mount filesystem.");
189 
190 	/*
191 	 * kernname (default-name) might have changed if mountroot() called
192 	 * boot_nfs_mountroot(), and it called set_default_filename().
193 	 */
194 	if (!user_specified_filename)
195 		(void) strcpy(filename, kernname);
196 
197 	if (verbosemode)
198 		printf("standalone = `%s', args = `%s'\n", filename, bargs);
199 
200 	set_client_bootargs(filename, bargs);
201 
202 	post_mountroot_nfs();
203 
204 	return (1);
205 }
206