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