xref: /openbsd-src/usr.sbin/installboot/installboot.c (revision 26ce53eaba1cc603bed743660370c90ad92eddc7)
1*26ce53eaSkn /*	$OpenBSD: installboot.c,v 1.16 2022/11/08 12:08:53 kn Exp $	*/
2a7036d21Sjsing 
3a7036d21Sjsing /*
4a7036d21Sjsing  * Copyright (c) 2012, 2013 Joel Sing <jsing@openbsd.org>
5a7036d21Sjsing  *
6a7036d21Sjsing  * Permission to use, copy, modify, and distribute this software for any
7a7036d21Sjsing  * purpose with or without fee is hereby granted, provided that the above
8a7036d21Sjsing  * copyright notice and this permission notice appear in all copies.
9a7036d21Sjsing  *
10a7036d21Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11a7036d21Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12a7036d21Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13a7036d21Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14a7036d21Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15a7036d21Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16a7036d21Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17a7036d21Sjsing  */
18a7036d21Sjsing 
19a7036d21Sjsing #include <err.h>
20a7036d21Sjsing #include <fcntl.h>
21a7036d21Sjsing #include <stdio.h>
22a7036d21Sjsing #include <stdlib.h>
2346339098Sjsing #include <string.h>
24a7036d21Sjsing #include <unistd.h>
25a7036d21Sjsing #include <util.h>
26a7036d21Sjsing 
27a7036d21Sjsing #include "installboot.h"
28a7036d21Sjsing 
29a7036d21Sjsing int	nowrite;
30c3e1bf61Skettenis int	prepare;
31a7036d21Sjsing int	stages;
32a7036d21Sjsing int	verbose;
33a7036d21Sjsing 
34c770c5a2Skn char	*root;
35a7036d21Sjsing char	*stage1;
36a7036d21Sjsing char	*stage2;
37a7036d21Sjsing 
38a7036d21Sjsing static __dead void
usage(void)39a7036d21Sjsing usage(void)
40a7036d21Sjsing {
41c770c5a2Skn 	fprintf(stderr, "usage:\t%1$s [-nv] [-r root] disk [stage1%2$s]\n"
42c770c5a2Skn 	    "\t%1$s [-nv] -p disk\n",
43c770c5a2Skn 	    getprogname(), (stages >= 2) ? " [stage2]" : "");
44a7036d21Sjsing 
45a7036d21Sjsing 	exit(1);
46a7036d21Sjsing }
47a7036d21Sjsing 
48a7036d21Sjsing int
main(int argc,char ** argv)49a7036d21Sjsing main(int argc, char **argv)
50a7036d21Sjsing {
51e09cbf07Skrw 	char *dev, *realdev;
527a970b3eSmiod 	int devfd, opt;
53a7036d21Sjsing 
54a7036d21Sjsing 	md_init();
55a7036d21Sjsing 
56c3e1bf61Skettenis 	while ((opt = getopt(argc, argv, "npr:v")) != -1) {
57a7036d21Sjsing 		switch (opt) {
58a7036d21Sjsing 		case 'n':
59a7036d21Sjsing 			nowrite = 1;
60a7036d21Sjsing 			break;
61c3e1bf61Skettenis 		case 'p':
62c3e1bf61Skettenis 			prepare = 1;
63c3e1bf61Skettenis 			break;
6446339098Sjsing 		case 'r':
65c770c5a2Skn 			root = optarg;
6646339098Sjsing 			break;
67a7036d21Sjsing 		case 'v':
68a7036d21Sjsing 			verbose = 1;
69a7036d21Sjsing 			break;
70a7036d21Sjsing 		default:
71a7036d21Sjsing 			usage();
72a7036d21Sjsing 		}
73a7036d21Sjsing 	}
74a7036d21Sjsing 
75a7036d21Sjsing 	argc -= optind;
76a7036d21Sjsing 	argv += optind;
77a7036d21Sjsing 
78a7036d21Sjsing 	if (argc < 1 || argc > stages + 1)
79a7036d21Sjsing 		usage();
80c770c5a2Skn 	if (prepare && (root != NULL || argc > 1))
81c770c5a2Skn 		usage();
82a7036d21Sjsing 
83a7036d21Sjsing 	dev = argv[0];
84a7036d21Sjsing 	if (argc > 1)
85a7036d21Sjsing 		stage1 = argv[1];
86a7036d21Sjsing 	if (argc > 2)
87a7036d21Sjsing 		stage2 = argv[2];
88a7036d21Sjsing 
89c770c5a2Skn 	if ((devfd = opendev(dev, (nowrite ? O_RDONLY : O_RDWR), OPENDEV_PART,
90c770c5a2Skn 	    &realdev)) == -1)
91c770c5a2Skn 		err(1, "open: %s", realdev);
92c770c5a2Skn 
93c770c5a2Skn 	if (prepare) {
94*26ce53eaSkn #if SOFTRAID
95*26ce53eaSkn 		sr_prepareboot(devfd, dev);
96*26ce53eaSkn #else
97c770c5a2Skn 		md_prepareboot(devfd, realdev);
98*26ce53eaSkn #endif
99c770c5a2Skn 		return 0;
100c770c5a2Skn 	}
101c770c5a2Skn 
10274d09653Sjsing 	/* Prefix stages with root, unless they were user supplied. */
103c770c5a2Skn 	if (root == NULL)
104c770c5a2Skn 		root = "/";
10546339098Sjsing 	if (verbose)
10646339098Sjsing 		fprintf(stderr, "Using %s as root\n", root);
107597864b7Skrw 	if (argc <= 1 && stage1 != NULL) {
10846339098Sjsing 		stage1 = fileprefix(root, stage1);
109597864b7Skrw 		if (stage1 == NULL)
110597864b7Skrw 			exit(1);
111597864b7Skrw 	}
112597864b7Skrw 	if (argc <= 2 && stage2 != NULL) {
11346339098Sjsing 		stage2 = fileprefix(root, stage2);
114597864b7Skrw 		if (stage2 == NULL)
115597864b7Skrw 			exit(1);
116597864b7Skrw 	}
11746339098Sjsing 
118a7036d21Sjsing         if (verbose) {
119a7036d21Sjsing 		fprintf(stderr, "%s bootstrap on %s\n",
120a7036d21Sjsing 		    (nowrite ? "would install" : "installing"), realdev);
121f45b016aSderaadt 		if (stage1 || stage2) {
122a7036d21Sjsing 			if (stage1)
123a7036d21Sjsing 				fprintf(stderr, "using first-stage %s", stage1);
124a7036d21Sjsing 			if (stage2)
125a7036d21Sjsing 				fprintf(stderr, ", second-stage %s", stage2);
126a7036d21Sjsing 			fprintf(stderr, "\n");
127a7036d21Sjsing 		}
128f45b016aSderaadt 	}
129a7036d21Sjsing 
130a7036d21Sjsing 	md_loadboot();
131a7036d21Sjsing 
132a7036d21Sjsing #ifdef SOFTRAID
133a7036d21Sjsing 	sr_installboot(devfd, dev);
134a7036d21Sjsing #else
135a7036d21Sjsing 	md_installboot(devfd, realdev);
136a7036d21Sjsing #endif
137a7036d21Sjsing 
138a7036d21Sjsing 	return 0;
139a7036d21Sjsing }
140