1*6c99b301Skrw /* $OpenBSD: loongson_installboot.c,v 1.10 2022/11/06 20:03:48 krw Exp $ */
2a284d5afSderaadt /* $NetBSD: installboot.c,v 1.5 1995/11/17 23:23:50 gwr Exp $ */
3a284d5afSderaadt
4a284d5afSderaadt /*
5a284d5afSderaadt * Copyright (c) 2011 Joel Sing <jsing@openbsd.org>
6a284d5afSderaadt * Copyright (c) 2010 Otto Moerbeek <otto@openbsd.org>
7a284d5afSderaadt * Copyright (c) 2003 Tom Cosgrove <tom.cosgrove@arches-consulting.com>
8a284d5afSderaadt * Copyright (c) 1997 Michael Shalayeff
9a284d5afSderaadt * Copyright (c) 1994 Paul Kranenburg
10a284d5afSderaadt * All rights reserved.
11a284d5afSderaadt *
12a284d5afSderaadt * Redistribution and use in source and binary forms, with or without
13a284d5afSderaadt * modification, are permitted provided that the following conditions
14a284d5afSderaadt * are met:
15a284d5afSderaadt * 1. Redistributions of source code must retain the above copyright
16a284d5afSderaadt * notice, this list of conditions and the following disclaimer.
17a284d5afSderaadt * 2. Redistributions in binary form must reproduce the above copyright
18a284d5afSderaadt * notice, this list of conditions and the following disclaimer in the
19a284d5afSderaadt * documentation and/or other materials provided with the distribution.
20a284d5afSderaadt * 3. All advertising materials mentioning features or use of this software
21a284d5afSderaadt * must display the following acknowledgement:
22a284d5afSderaadt * This product includes software developed by Paul Kranenburg.
23a284d5afSderaadt * 4. The name of the author may not be used to endorse or promote products
24a284d5afSderaadt * derived from this software without specific prior written permission
25a284d5afSderaadt *
26a284d5afSderaadt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27a284d5afSderaadt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28a284d5afSderaadt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29a284d5afSderaadt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30a284d5afSderaadt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31a284d5afSderaadt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32a284d5afSderaadt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33a284d5afSderaadt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34a284d5afSderaadt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35a284d5afSderaadt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36a284d5afSderaadt */
37a284d5afSderaadt
38a284d5afSderaadt #include <sys/param.h> /* DEV_BSIZE */
39a284d5afSderaadt #include <sys/disklabel.h>
40a284d5afSderaadt #include <sys/dkio.h>
41a284d5afSderaadt #include <sys/ioctl.h>
42a284d5afSderaadt #include <sys/mount.h>
43a284d5afSderaadt #include <sys/stat.h>
44a284d5afSderaadt
45a284d5afSderaadt #include <err.h>
46a284d5afSderaadt #include <errno.h>
47a284d5afSderaadt #include <fcntl.h>
48a284d5afSderaadt #include <stdlib.h>
49a284d5afSderaadt #include <stdio.h>
50a284d5afSderaadt #include <string.h>
51a284d5afSderaadt #include <unistd.h>
52a284d5afSderaadt #include <util.h>
53a284d5afSderaadt
54a284d5afSderaadt #include "installboot.h"
55a284d5afSderaadt
56a284d5afSderaadt static void write_filesystem(struct disklabel *, char);
57a284d5afSderaadt static int findmbrfat(int, struct disklabel *);
58a284d5afSderaadt
59a284d5afSderaadt void
md_init(void)60a284d5afSderaadt md_init(void)
61a284d5afSderaadt {
62dea985b6Skn stages = 1;
63dea985b6Skn stage1 = "/usr/mdec/boot";
64a284d5afSderaadt }
65a284d5afSderaadt
66a284d5afSderaadt void
md_loadboot(void)67a284d5afSderaadt md_loadboot(void)
68a284d5afSderaadt {
69a284d5afSderaadt }
70a284d5afSderaadt
71a284d5afSderaadt void
md_prepareboot(int devfd,char * dev)72c3e1bf61Skettenis md_prepareboot(int devfd, char *dev)
73c3e1bf61Skettenis {
74c3e1bf61Skettenis }
75c3e1bf61Skettenis
76c3e1bf61Skettenis void
md_installboot(int devfd,char * dev)77a284d5afSderaadt md_installboot(int devfd, char *dev)
78a284d5afSderaadt {
79a284d5afSderaadt struct disklabel dl;
80a284d5afSderaadt int part;
81a284d5afSderaadt
82a284d5afSderaadt /* Get and check disklabel. */
83a284d5afSderaadt if (ioctl(devfd, DIOCGDINFO, &dl) == -1)
84a284d5afSderaadt err(1, "disklabel: %s", dev);
85a284d5afSderaadt if (dl.d_magic != DISKMAGIC)
86a284d5afSderaadt errx(1, "bad disklabel magic=0x%08x", dl.d_magic);
87a284d5afSderaadt
88a284d5afSderaadt /* Warn on unknown disklabel types. */
89a284d5afSderaadt if (dl.d_type == 0)
90a284d5afSderaadt warnx("disklabel type unknown");
91a284d5afSderaadt
92a284d5afSderaadt part = findmbrfat(devfd, &dl);
93a284d5afSderaadt if (part != -1) {
9435c2a5e8Smiod write_filesystem(&dl, (char)part);
9535c2a5e8Smiod return;
96a284d5afSderaadt }
97a284d5afSderaadt }
98a284d5afSderaadt
99a284d5afSderaadt
100a284d5afSderaadt static void
write_filesystem(struct disklabel * dl,char part)101a284d5afSderaadt write_filesystem(struct disklabel *dl, char part)
102a284d5afSderaadt {
103a08d2734Skn static const char *fsckfmt = "/sbin/fsck -t ext2fs %s >/dev/null";
104a08d2734Skn static const char *newfsfmt = "/sbin/newfs -t ext2fs %s >/dev/null";
10586850af8Svisa struct ufs_args args;
106a284d5afSderaadt char cmd[60];
107a284d5afSderaadt char dst[PATH_MAX];
108*6c99b301Skrw size_t mntlen;
109a284d5afSderaadt int rslt;
110a284d5afSderaadt
111a284d5afSderaadt /* Create directory for temporary mount point. */
112a284d5afSderaadt strlcpy(dst, "/tmp/installboot.XXXXXXXXXX", sizeof(dst));
113a284d5afSderaadt if (mkdtemp(dst) == NULL)
114a284d5afSderaadt err(1, "mkdtemp('%s') failed", dst);
115a284d5afSderaadt mntlen = strlen(dst);
116a284d5afSderaadt
117a284d5afSderaadt /* Mount <duid>.<part> as ext2fs filesystem. */
118a284d5afSderaadt memset(&args, 0, sizeof(args));
119a284d5afSderaadt rslt = asprintf(&args.fspec,
120a284d5afSderaadt "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx.%c",
121a284d5afSderaadt dl->d_uid[0], dl->d_uid[1], dl->d_uid[2], dl->d_uid[3],
122a284d5afSderaadt dl->d_uid[4], dl->d_uid[5], dl->d_uid[6], dl->d_uid[7],
123a284d5afSderaadt part);
124a284d5afSderaadt if (rslt == -1) {
125a284d5afSderaadt warn("bad special device");
126a284d5afSderaadt goto rmdir;
127a284d5afSderaadt }
128a284d5afSderaadt
129a284d5afSderaadt args.export_info.ex_root = -2;
130a284d5afSderaadt args.export_info.ex_flags = 0;
131a284d5afSderaadt
132a284d5afSderaadt if (mount(MOUNT_EXT2FS, dst, 0, &args) == -1) {
133a284d5afSderaadt /* Try fsck'ing it. */
134a284d5afSderaadt rslt = snprintf(cmd, sizeof(cmd), fsckfmt, args.fspec);
135a284d5afSderaadt if (rslt >= sizeof(cmd)) {
136a284d5afSderaadt warnx("can't build fsck command");
137a284d5afSderaadt rslt = -1;
138a284d5afSderaadt goto rmdir;
139a284d5afSderaadt }
140a284d5afSderaadt rslt = system(cmd);
141a284d5afSderaadt if (rslt == -1) {
142a284d5afSderaadt warn("system('%s') failed", cmd);
143a284d5afSderaadt goto rmdir;
144a284d5afSderaadt }
145a284d5afSderaadt if (mount(MOUNT_EXT2FS, dst, 0, &args) == -1) {
146a284d5afSderaadt /* Try newfs'ing it. */
147a284d5afSderaadt rslt = snprintf(cmd, sizeof(cmd), newfsfmt,
148a284d5afSderaadt args.fspec);
149a284d5afSderaadt if (rslt >= sizeof(cmd)) {
150a284d5afSderaadt warnx("can't build newfs command");
151a284d5afSderaadt rslt = -1;
152a284d5afSderaadt goto rmdir;
153a284d5afSderaadt }
154a284d5afSderaadt rslt = system(cmd);
155a284d5afSderaadt if (rslt == -1) {
156a284d5afSderaadt warn("system('%s') failed", cmd);
157a284d5afSderaadt goto rmdir;
158a284d5afSderaadt }
159a284d5afSderaadt rslt = mount(MOUNT_EXT2FS, dst, 0, &args);
160a284d5afSderaadt if (rslt == -1) {
16186850af8Svisa warn("unable to mount ext2fs partition");
162a284d5afSderaadt goto rmdir;
163a284d5afSderaadt }
164a284d5afSderaadt }
165a284d5afSderaadt }
166a284d5afSderaadt
167a284d5afSderaadt /* Create "/boot" directory in <duid>.<part>. */
168a284d5afSderaadt if (strlcat(dst, "/boot", sizeof(dst)) >= sizeof(dst)) {
169a284d5afSderaadt rslt = -1;
17086850af8Svisa warn("unable to build /boot directory");
171a284d5afSderaadt goto umount;
172a284d5afSderaadt }
173a284d5afSderaadt rslt = mkdir(dst, 0755);
174a284d5afSderaadt if (rslt == -1 && errno != EEXIST) {
175a284d5afSderaadt warn("mkdir('%s') failed", dst);
176a284d5afSderaadt goto umount;
177a284d5afSderaadt }
178a284d5afSderaadt
179a284d5afSderaadt /*
180a284d5afSderaadt * Copy /usr/mdec/boot to /boot/boot.
181a284d5afSderaadt */
182a284d5afSderaadt if (strlcat(dst, "/boot", sizeof(dst)) >= sizeof(dst)) {
183a284d5afSderaadt rslt = -1;
184a284d5afSderaadt warn("unable to build /boot path");
185a284d5afSderaadt goto umount;
186a284d5afSderaadt }
187a284d5afSderaadt if (verbose)
188a284d5afSderaadt fprintf(stderr, "%s %s to %s\n",
189dea985b6Skn (nowrite ? "would copy" : "copying"), stage1, dst);
190a284d5afSderaadt if (!nowrite) {
191dea985b6Skn rslt = filecopy(stage1, dst);
192a284d5afSderaadt if (rslt == -1)
193a284d5afSderaadt goto umount;
194a284d5afSderaadt }
195a284d5afSderaadt
196a284d5afSderaadt rslt = 0;
197a284d5afSderaadt
198a284d5afSderaadt umount:
199a284d5afSderaadt dst[mntlen] = '\0';
200a284d5afSderaadt if (unmount(dst, MNT_FORCE) == -1)
201a284d5afSderaadt err(1, "unmount('%s') failed", dst);
202a284d5afSderaadt
203a284d5afSderaadt rmdir:
204a284d5afSderaadt free(args.fspec);
205a284d5afSderaadt dst[mntlen] = '\0';
206a284d5afSderaadt if (rmdir(dst) == -1)
207a284d5afSderaadt err(1, "rmdir('%s') failed", dst);
208a284d5afSderaadt
209a284d5afSderaadt if (rslt == -1)
210a284d5afSderaadt exit(1);
211a284d5afSderaadt }
212a284d5afSderaadt
213a284d5afSderaadt int
findmbrfat(int devfd,struct disklabel * dl)214a284d5afSderaadt findmbrfat(int devfd, struct disklabel *dl)
215a284d5afSderaadt {
216a284d5afSderaadt struct dos_partition dp[NDOSPART];
217a284d5afSderaadt ssize_t len;
218a284d5afSderaadt u_int64_t start = 0;
219a284d5afSderaadt int i;
220a284d5afSderaadt u_int8_t *secbuf;
221a284d5afSderaadt
222a284d5afSderaadt if ((secbuf = malloc(dl->d_secsize)) == NULL)
223a284d5afSderaadt err(1, NULL);
224a284d5afSderaadt
225a284d5afSderaadt /* Read MBR. */
226a284d5afSderaadt len = pread(devfd, secbuf, dl->d_secsize, 0);
227a284d5afSderaadt if (len != dl->d_secsize)
228a284d5afSderaadt err(4, "can't read mbr");
229a284d5afSderaadt memcpy(dp, &secbuf[DOSPARTOFF], sizeof(dp));
230a284d5afSderaadt
231a284d5afSderaadt for (i = 0; i < NDOSPART; i++) {
232a284d5afSderaadt if (dp[i].dp_typ == DOSPTYP_UNUSED)
233a284d5afSderaadt continue;
234a284d5afSderaadt if (dp[i].dp_typ == DOSPTYP_LINUX)
235a284d5afSderaadt start = dp[i].dp_start;
236a284d5afSderaadt }
237a284d5afSderaadt
238a284d5afSderaadt free(secbuf);
239a284d5afSderaadt
240a284d5afSderaadt if (start) {
241a284d5afSderaadt for (i = 0; i < MAXPARTITIONS; i++) {
242a284d5afSderaadt if (DL_GETPSIZE(&dl->d_partitions[i]) > 0 &&
243a284d5afSderaadt DL_GETPOFFSET(&dl->d_partitions[i]) == start)
244a284d5afSderaadt return ('a' + i);
245a284d5afSderaadt }
246a284d5afSderaadt }
247a284d5afSderaadt
248a284d5afSderaadt return (-1);
249a284d5afSderaadt }
250