1 1.6 mrg /* $NetBSD: mbr.c,v 1.6 2021/05/17 20:21:05 mrg Exp $ */ 2 1.1 phx 3 1.1 phx /* 4 1.1 phx * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 1.1 phx * Copyright (C) 1995, 1996 TooLs GmbH. 6 1.1 phx * All rights reserved. 7 1.1 phx * 8 1.1 phx * Redistribution and use in source and binary forms, with or without 9 1.1 phx * modification, are permitted provided that the following conditions 10 1.1 phx * are met: 11 1.1 phx * 1. Redistributions of source code must retain the above copyright 12 1.1 phx * notice, this list of conditions and the following disclaimer. 13 1.1 phx * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 phx * notice, this list of conditions and the following disclaimer in the 15 1.1 phx * documentation and/or other materials provided with the distribution. 16 1.1 phx * 3. All advertising materials mentioning features or use of this software 17 1.1 phx * must display the following acknowledgement: 18 1.1 phx * This product includes software developed by TooLs GmbH. 19 1.1 phx * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 1.1 phx * derived from this software without specific prior written permission. 21 1.1 phx * 22 1.1 phx * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 1.1 phx * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 1.1 phx * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 1.1 phx * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 1.1 phx * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 1.1 phx * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 1.1 phx * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 1.1 phx * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 1.1 phx * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 1.1 phx * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 phx */ 33 1.1 phx 34 1.1 phx #include <sys/param.h> 35 1.1 phx #include <sys/bootblock.h> 36 1.1 phx 37 1.6 mrg #include <lib/libkern/libkern.h> 38 1.1 phx #include <lib/libsa/byteorder.h> 39 1.1 phx #include <lib/libsa/stand.h> 40 1.1 phx 41 1.1 phx #include "mbr.h" 42 1.1 phx 43 1.3 phx static int find_mbr_part(struct of_dev *, uint32_t, char *, 44 1.3 phx struct disklabel *, uint32_t, uint8_t, int); 45 1.3 phx static void make_dos_label(struct disklabel *, uint32_t); 46 1.1 phx 47 1.1 phx /* 48 1.1 phx * Find a valid MBR disklabel. 49 1.1 phx */ 50 1.1 phx int 51 1.1 phx search_mbr_label(struct of_dev *devp, u_long off, char *buf, 52 1.1 phx struct disklabel *lp, u_long off0) 53 1.1 phx { 54 1.3 phx static uint8_t fat_types[] = { 55 1.3 phx MBR_PTYPE_FAT12, MBR_PTYPE_FAT16S, MBR_PTYPE_FAT16B, 56 1.3 phx MBR_PTYPE_FAT32, MBR_PTYPE_FAT32L, MBR_PTYPE_FAT16L 57 1.3 phx }; 58 1.3 phx size_t read; 59 1.3 phx uint32_t poff; 60 1.3 phx int i; 61 1.3 phx 62 1.3 phx /* Find a disklabel in a NetBSD or 386BSD partition. */ 63 1.3 phx poff = find_mbr_part(devp, off, buf, lp, 0, MBR_PTYPE_NETBSD, 0); 64 1.3 phx #ifdef COMPAT_386BSD_MBRPART 65 1.3 phx if (poff == 0) { 66 1.3 phx poff = find_mbr_part(devp, off, buf, lp, 0, 67 1.3 phx MBR_PTYPE_386BSD, 0); 68 1.3 phx if (poff != 0) 69 1.3 phx printf("WARNING: old BSD partition ID!\n"); 70 1.3 phx } 71 1.3 phx #endif 72 1.3 phx if (poff != 0) { 73 1.4 phx if (strategy(devp, F_READ, poff + LABELSECTOR, DEV_BSIZE, 74 1.3 phx buf, &read) == 0 && read == DEV_BSIZE) 75 1.3 phx if (getdisklabel(buf, lp) == NULL) 76 1.3 phx return 0; 77 1.3 phx } 78 1.3 phx 79 1.3 phx /* 80 1.3 phx * No BSD partition with a valid disklabel found, so try to 81 1.3 phx * construct a label from a DOS partition. 82 1.3 phx */ 83 1.3 phx for (i = 0; i < sizeof(fat_types); i++) { 84 1.3 phx poff = find_mbr_part(devp, off, buf, lp, 0, fat_types[i], 0); 85 1.3 phx if (poff != 0) { 86 1.3 phx make_dos_label(lp, poff); 87 1.3 phx return 0; 88 1.3 phx } 89 1.3 phx } 90 1.3 phx 91 1.3 phx return ERDLAB; 92 1.3 phx } 93 1.3 phx 94 1.3 phx static int 95 1.3 phx find_mbr_part(struct of_dev *devp, uint32_t off, char *buf, 96 1.3 phx struct disklabel *lp, uint32_t off0, uint8_t ptype, int recursion) 97 1.3 phx { 98 1.1 phx size_t read; 99 1.1 phx struct mbr_partition *p; 100 1.1 phx int i; 101 1.3 phx uint32_t poff; 102 1.1 phx 103 1.1 phx if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read) 104 1.1 phx || read != DEV_BSIZE) 105 1.3 phx return 0; 106 1.1 phx 107 1.3 phx if (*(uint16_t *)&buf[MBR_MAGIC_OFFSET] != sa_htole16(MBR_MAGIC)) 108 1.3 phx return 0; 109 1.1 phx 110 1.1 phx if (recursion++ <= 1) 111 1.1 phx off0 += off; 112 1.3 phx 113 1.1 phx for (p = (struct mbr_partition *)(buf + MBR_PART_OFFSET), i = 0; 114 1.1 phx i < MBR_PART_COUNT; i++, p++) { 115 1.3 phx if (p->mbrp_type == ptype) { 116 1.3 phx recursion--; 117 1.3 phx return sa_le32toh(p->mbrp_start) + off0; 118 1.3 phx } 119 1.3 phx else if (p->mbrp_type == MBR_PTYPE_EXT) { 120 1.3 phx poff = find_mbr_part(devp, sa_le32toh(p->mbrp_start), 121 1.3 phx buf, lp, off0, ptype, recursion); 122 1.3 phx if (poff != 0) { 123 1.3 phx recursion--; 124 1.3 phx return poff; 125 1.1 phx } 126 1.1 phx if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read) 127 1.1 phx || read != DEV_BSIZE) { 128 1.1 phx recursion--; 129 1.1 phx return 0; 130 1.1 phx } 131 1.1 phx } 132 1.1 phx } 133 1.1 phx 134 1.3 phx return 0; 135 1.3 phx } 136 1.3 phx 137 1.3 phx static void 138 1.3 phx make_dos_label(struct disklabel *lp, uint32_t poff) 139 1.3 phx { 140 1.3 phx int i; 141 1.3 phx 142 1.3 phx /* clear all partitions */ 143 1.3 phx lp->d_npartitions = RAW_PART + 1; 144 1.3 phx for (i = 0; i < MAXPARTITIONS; i++) { 145 1.3 phx lp->d_partitions[i].p_size = 0; 146 1.3 phx lp->d_partitions[i].p_offset = 0; 147 1.3 phx lp->d_partitions[i].p_fstype = 0; 148 1.3 phx } 149 1.3 phx 150 1.3 phx /* set DOS partition as root partition */ 151 1.3 phx lp->d_partitions[0].p_offset = poff; 152 1.3 phx lp->d_partitions[0].p_fstype = FS_MSDOS; 153 1.3 phx 154 1.3 phx /* disklabel is valid */ 155 1.3 phx lp->d_magic = lp->d_magic2 = DISKMAGIC; 156 1.3 phx lp->d_checksum = 0; 157 1.3 phx lp->d_checksum = dkcksum(lp); 158 1.1 phx } 159