1 /* $OpenBSD: mbr.c,v 1.12 2001/01/28 00:51:46 weingart Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Tobias Weingartner 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Tobias Weingartner. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <err.h> 34 #include <util.h> 35 #include <stdio.h> 36 #include <unistd.h> 37 #include <memory.h> 38 #include <sys/fcntl.h> 39 #include <sys/ioctl.h> 40 #include <sys/types.h> 41 #include <sys/stat.h> 42 #include <sys/disklabel.h> 43 #include <sys/dkio.h> 44 #include <machine/param.h> 45 #include "disk.h" 46 #include "misc.h" 47 #include "mbr.h" 48 #include "part.h" 49 50 51 void 52 MBR_init(disk, mbr) 53 disk_t *disk; 54 mbr_t *mbr; 55 { 56 /* Fix up given mbr for this disk */ 57 mbr->part[0].flag = 0; 58 mbr->part[1].flag = 0; 59 mbr->part[2].flag = 0; 60 61 mbr->part[3].flag = DOSACTIVE; 62 mbr->signature = DOSMBR_SIGNATURE; 63 64 /* Use whole disk, save for first head, on first cyl. */ 65 mbr->part[3].id = DOSPTYP_OPENBSD; 66 mbr->part[3].scyl = 0; 67 mbr->part[3].shead = 1; 68 mbr->part[3].ssect = 1; 69 70 /* Go right to the end */ 71 mbr->part[3].ecyl = disk->real->cylinders - 1; 72 mbr->part[3].ehead = disk->real->heads - 1; 73 mbr->part[3].esect = disk->real->sectors; 74 75 /* Fix up start/length fields */ 76 PRT_fix_BN(disk, &mbr->part[3], 3); 77 78 #if defined(__powerpc__) || defined(__mips__) 79 /* Now fix up for the MS-DOS boot partition on PowerPC. */ 80 mbr->part[0].flag = DOSACTIVE; /* Boot from dos part */ 81 mbr->part[3].flag = 0; 82 mbr->part[3].ns += mbr->part[3].bs; 83 mbr->part[3].bs = mbr->part[0].bs + mbr->part[0].ns; 84 mbr->part[3].ns -= mbr->part[3].bs; 85 PRT_fix_CHS(disk, &mbr->part[3], 3); 86 if ((mbr->part[3].shead != 1) || (mbr->part[3].ssect != 1)) { 87 /* align the partition on a cylinder boundary */ 88 mbr->part[3].shead = 0; 89 mbr->part[3].ssect = 1; 90 mbr->part[3].scyl += 1; 91 } 92 /* Fix up start/length fields */ 93 PRT_fix_BN(disk, &mbr->part[3], 3); 94 #endif 95 } 96 97 void 98 MBR_parse(disk, mbr_buf, offset, reloff, mbr) 99 disk_t *disk; 100 char *mbr_buf; 101 off_t offset; 102 off_t reloff; 103 mbr_t *mbr; 104 { 105 int i; 106 107 memcpy(mbr->code, mbr_buf, MBR_CODE_SIZE); 108 mbr->offset = offset; 109 mbr->reloffset = reloff; 110 mbr->nt_serial = getlong(&mbr_buf[MBR_NTSER_OFF]); 111 mbr->spare = getshort(&mbr_buf[MBR_SPARE_OFF]); 112 mbr->signature = getshort(&mbr_buf[MBR_SIG_OFF]); 113 114 for (i = 0; i < NDOSPART; i++) 115 PRT_parse(disk, &mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i], 116 offset, reloff, &mbr->part[i], i); 117 } 118 119 void 120 MBR_make(mbr, mbr_buf) 121 mbr_t *mbr; 122 char *mbr_buf; 123 { 124 int i; 125 126 memcpy(mbr_buf, mbr->code, MBR_CODE_SIZE); 127 putlong(&mbr_buf[MBR_NTSER_OFF], mbr->nt_serial); 128 putshort(&mbr_buf[MBR_SPARE_OFF], mbr->spare); 129 putshort(&mbr_buf[MBR_SIG_OFF], mbr->signature); 130 131 for (i = 0; i < NDOSPART; i++) 132 PRT_make(&mbr->part[i], mbr->offset, mbr->reloffset, 133 &mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i]); 134 } 135 136 void 137 MBR_print(mbr) 138 mbr_t *mbr; 139 { 140 int i; 141 142 /* Header */ 143 printf("Signatures: 0x%X,0x%X\n", 144 (int)mbr->signature, (int)mbr->nt_serial); 145 PRT_print(0, NULL); 146 147 /* Entries */ 148 for (i = 0; i < NDOSPART; i++) 149 PRT_print(i, &mbr->part[i]); 150 } 151 152 int 153 MBR_read(fd, where, buf) 154 int fd; 155 off_t where; 156 char *buf; 157 { 158 off_t off; 159 int len; 160 161 where *= DEV_BSIZE; 162 off = lseek(fd, where, SEEK_SET); 163 if (off != where) 164 return (off); 165 len = read(fd, buf, DEV_BSIZE); 166 if (len != DEV_BSIZE) 167 return (len); 168 return (0); 169 } 170 171 int 172 MBR_write(fd, where, buf) 173 int fd; 174 off_t where; 175 char *buf; 176 { 177 off_t off; 178 int len; 179 180 where *= DEV_BSIZE; 181 off = lseek(fd, where, SEEK_SET); 182 if (off != where) 183 return (off); 184 len = write(fd, buf, DEV_BSIZE); 185 if (len != DEV_BSIZE) 186 return (len); 187 (void) ioctl(fd, DIOCRLDINFO, 0); 188 return (0); 189 } 190