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