1/* $OpenBSD: loongson_installboot.c,v 1.10 2022/11/06 20:03:48 krw 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 56static void write_filesystem(struct disklabel *, char); 57static int findmbrfat(int, struct disklabel *); 58 59void 60md_init(void) 61{ 62 stages = 1; 63 stage1 = "/usr/mdec/boot"; 64} 65 66void 67md_loadboot(void) 68{ 69} 70 71void 72md_prepareboot(int devfd, char *dev) 73{ 74} 75 76void 77md_installboot(int devfd, char *dev) 78{ 79 struct disklabel dl; 80 int part; 81 82 /* Get and check disklabel. */ 83 if (ioctl(devfd, DIOCGDINFO, &dl) == -1) 84 err(1, "disklabel: %s", dev); 85 if (dl.d_magic != DISKMAGIC) 86 errx(1, "bad disklabel magic=0x%08x", dl.d_magic); 87 88 /* Warn on unknown disklabel types. */ 89 if (dl.d_type == 0) 90 warnx("disklabel type unknown"); 91 92 part = findmbrfat(devfd, &dl); 93 if (part != -1) { 94 write_filesystem(&dl, (char)part); 95 return; 96 } 97} 98 99 100static void 101write_filesystem(struct disklabel *dl, char part) 102{ 103 static const char *fsckfmt = "/sbin/fsck -t ext2fs %s >/dev/null"; 104 static const char *newfsfmt = "/sbin/newfs -t ext2fs %s >/dev/null"; 105 struct ufs_args args; 106 char cmd[60]; 107 char dst[PATH_MAX]; 108 size_t mntlen; 109 int rslt; 110 111 /* Create directory for temporary mount point. */ 112 strlcpy(dst, "/tmp/installboot.XXXXXXXXXX", sizeof(dst)); 113 if (mkdtemp(dst) == NULL) 114 err(1, "mkdtemp('%s') failed", dst); 115 mntlen = strlen(dst); 116 117 /* Mount <duid>.<part> as ext2fs filesystem. */ 118 memset(&args, 0, sizeof(args)); 119 rslt = asprintf(&args.fspec, 120 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx.%c", 121 dl->d_uid[0], dl->d_uid[1], dl->d_uid[2], dl->d_uid[3], 122 dl->d_uid[4], dl->d_uid[5], dl->d_uid[6], dl->d_uid[7], 123 part); 124 if (rslt == -1) { 125 warn("bad special device"); 126 goto rmdir; 127 } 128 129 args.export_info.ex_root = -2; 130 args.export_info.ex_flags = 0; 131 132 if (mount(MOUNT_EXT2FS, dst, 0, &args) == -1) { 133 /* Try fsck'ing it. */ 134 rslt = snprintf(cmd, sizeof(cmd), fsckfmt, args.fspec); 135 if (rslt >= sizeof(cmd)) { 136 warnx("can't build fsck command"); 137 rslt = -1; 138 goto rmdir; 139 } 140 rslt = system(cmd); 141 if (rslt == -1) { 142 warn("system('%s') failed", cmd); 143 goto rmdir; 144 } 145 if (mount(MOUNT_EXT2FS, dst, 0, &args) == -1) { 146 /* Try newfs'ing it. */ 147 rslt = snprintf(cmd, sizeof(cmd), newfsfmt, 148 args.fspec); 149 if (rslt >= sizeof(cmd)) { 150 warnx("can't build newfs command"); 151 rslt = -1; 152 goto rmdir; 153 } 154 rslt = system(cmd); 155 if (rslt == -1) { 156 warn("system('%s') failed", cmd); 157 goto rmdir; 158 } 159 rslt = mount(MOUNT_EXT2FS, dst, 0, &args); 160 if (rslt == -1) { 161 warn("unable to mount ext2fs partition"); 162 goto rmdir; 163 } 164 } 165 } 166 167 /* Create "/boot" directory in <duid>.<part>. */ 168 if (strlcat(dst, "/boot", sizeof(dst)) >= sizeof(dst)) { 169 rslt = -1; 170 warn("unable to build /boot directory"); 171 goto umount; 172 } 173 rslt = mkdir(dst, 0755); 174 if (rslt == -1 && errno != EEXIST) { 175 warn("mkdir('%s') failed", dst); 176 goto umount; 177 } 178 179 /* 180 * Copy /usr/mdec/boot to /boot/boot. 181 */ 182 if (strlcat(dst, "/boot", sizeof(dst)) >= sizeof(dst)) { 183 rslt = -1; 184 warn("unable to build /boot path"); 185 goto umount; 186 } 187 if (verbose) 188 fprintf(stderr, "%s %s to %s\n", 189 (nowrite ? "would copy" : "copying"), stage1, dst); 190 if (!nowrite) { 191 rslt = filecopy(stage1, dst); 192 if (rslt == -1) 193 goto umount; 194 } 195 196 rslt = 0; 197 198umount: 199 dst[mntlen] = '\0'; 200 if (unmount(dst, MNT_FORCE) == -1) 201 err(1, "unmount('%s') failed", dst); 202 203rmdir: 204 free(args.fspec); 205 dst[mntlen] = '\0'; 206 if (rmdir(dst) == -1) 207 err(1, "rmdir('%s') failed", dst); 208 209 if (rslt == -1) 210 exit(1); 211} 212 213int 214findmbrfat(int devfd, struct disklabel *dl) 215{ 216 struct dos_partition dp[NDOSPART]; 217 ssize_t len; 218 u_int64_t start = 0; 219 int i; 220 u_int8_t *secbuf; 221 222 if ((secbuf = malloc(dl->d_secsize)) == NULL) 223 err(1, NULL); 224 225 /* Read MBR. */ 226 len = pread(devfd, secbuf, dl->d_secsize, 0); 227 if (len != dl->d_secsize) 228 err(4, "can't read mbr"); 229 memcpy(dp, &secbuf[DOSPARTOFF], sizeof(dp)); 230 231 for (i = 0; i < NDOSPART; i++) { 232 if (dp[i].dp_typ == DOSPTYP_UNUSED) 233 continue; 234 if (dp[i].dp_typ == DOSPTYP_LINUX) 235 start = dp[i].dp_start; 236 } 237 238 free(secbuf); 239 240 if (start) { 241 for (i = 0; i < MAXPARTITIONS; i++) { 242 if (DL_GETPSIZE(&dl->d_partitions[i]) > 0 && 243 DL_GETPOFFSET(&dl->d_partitions[i]) == start) 244 return ('a' + i); 245 } 246 } 247 248 return (-1); 249} 250