Home | History | Annotate | Line # | Download | only in ofwboot
mbr.c revision 1.4.24.1
      1  1.4.24.1  skrll /*	$NetBSD: mbr.c,v 1.4.24.1 2016/04/22 15:44:11 skrll 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.1    phx #include <lib/libsa/byteorder.h>
     38       1.1    phx #include <lib/libsa/stand.h>
     39       1.1    phx 
     40       1.1    phx #include "mbr.h"
     41       1.1    phx 
     42       1.3    phx static int find_mbr_part(struct of_dev *, uint32_t, char *,
     43       1.3    phx     struct disklabel *, uint32_t, uint8_t, int);
     44       1.3    phx static void make_dos_label(struct disklabel *, uint32_t);
     45       1.1    phx 
     46       1.1    phx /*
     47       1.1    phx  * Find a valid MBR disklabel.
     48       1.1    phx  */
     49       1.1    phx int
     50       1.1    phx search_mbr_label(struct of_dev *devp, u_long off, char *buf,
     51       1.1    phx     struct disklabel *lp, u_long off0)
     52       1.1    phx {
     53       1.3    phx 	static uint8_t fat_types[] = {
     54       1.3    phx 		MBR_PTYPE_FAT12, MBR_PTYPE_FAT16S, MBR_PTYPE_FAT16B,
     55       1.3    phx 		MBR_PTYPE_FAT32, MBR_PTYPE_FAT32L, MBR_PTYPE_FAT16L
     56       1.3    phx 	};
     57       1.3    phx 	size_t read;
     58       1.3    phx 	uint32_t poff;
     59       1.3    phx 	int i;
     60       1.3    phx 
     61       1.3    phx 	/* Find a disklabel in a NetBSD or 386BSD partition. */
     62       1.3    phx 	poff = find_mbr_part(devp, off, buf, lp, 0, MBR_PTYPE_NETBSD, 0);
     63       1.3    phx #ifdef COMPAT_386BSD_MBRPART
     64       1.3    phx 	if (poff == 0) {
     65       1.3    phx 		poff = find_mbr_part(devp, off, buf, lp, 0,
     66       1.3    phx 		    MBR_PTYPE_386BSD, 0);
     67       1.3    phx 		if (poff != 0)
     68       1.3    phx 			printf("WARNING: old BSD partition ID!\n");
     69       1.3    phx 	}
     70       1.3    phx #endif
     71       1.3    phx 	if (poff != 0) {
     72       1.4    phx 		if (strategy(devp, F_READ, poff + LABELSECTOR, DEV_BSIZE,
     73       1.3    phx 		    buf, &read) == 0 && read == DEV_BSIZE)
     74       1.3    phx 			if (getdisklabel(buf, lp) == NULL)
     75       1.3    phx 				return 0;
     76       1.3    phx 	}
     77       1.3    phx 
     78       1.3    phx 	/*
     79       1.3    phx 	 * No BSD partition with a valid disklabel found, so try to
     80       1.3    phx 	 * construct a label from a DOS partition.
     81       1.3    phx 	 */
     82       1.3    phx 	for (i = 0; i < sizeof(fat_types); i++) {
     83       1.3    phx 		poff = find_mbr_part(devp, off, buf, lp, 0, fat_types[i], 0);
     84       1.3    phx 		if (poff != 0) {
     85       1.3    phx 			make_dos_label(lp, poff);
     86       1.3    phx 			return 0;
     87       1.3    phx 		}
     88       1.3    phx 	}
     89       1.3    phx 
     90       1.3    phx 	return ERDLAB;
     91       1.3    phx }
     92       1.3    phx 
     93       1.3    phx static int
     94       1.3    phx find_mbr_part(struct of_dev *devp, uint32_t off, char *buf,
     95       1.3    phx     struct disklabel *lp, uint32_t off0, uint8_t ptype, int recursion)
     96       1.3    phx {
     97       1.1    phx 	size_t read;
     98       1.1    phx 	struct mbr_partition *p;
     99       1.1    phx 	int i;
    100       1.3    phx 	uint32_t poff;
    101       1.1    phx 
    102       1.1    phx 	if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
    103       1.1    phx 	    || read != DEV_BSIZE)
    104       1.3    phx 		return 0;
    105       1.1    phx 
    106       1.3    phx 	if (*(uint16_t *)&buf[MBR_MAGIC_OFFSET] != sa_htole16(MBR_MAGIC))
    107       1.3    phx 		return 0;
    108       1.1    phx 
    109       1.1    phx 	if (recursion++ <= 1)
    110       1.1    phx 		off0 += off;
    111       1.3    phx 
    112       1.1    phx 	for (p = (struct mbr_partition *)(buf + MBR_PART_OFFSET), i = 0;
    113       1.1    phx 	     i < MBR_PART_COUNT; i++, p++) {
    114       1.3    phx 		if (p->mbrp_type == ptype) {
    115       1.3    phx 			recursion--;
    116       1.3    phx 			return sa_le32toh(p->mbrp_start) + off0;
    117       1.3    phx 		}
    118       1.3    phx 		else if (p->mbrp_type == MBR_PTYPE_EXT) {
    119       1.3    phx 			poff = find_mbr_part(devp, sa_le32toh(p->mbrp_start),
    120       1.3    phx 			    buf, lp, off0, ptype, recursion);
    121       1.3    phx 			if (poff != 0) {
    122       1.3    phx 				recursion--;
    123       1.3    phx 				return poff;
    124       1.1    phx 			}
    125       1.1    phx 			if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
    126       1.1    phx 			    || read != DEV_BSIZE) {
    127       1.1    phx 				recursion--;
    128       1.1    phx 				return 0;
    129       1.1    phx 			}
    130       1.1    phx 		}
    131       1.1    phx 	}
    132       1.1    phx 
    133       1.3    phx 	return 0;
    134       1.3    phx }
    135       1.3    phx 
    136       1.3    phx static void
    137       1.3    phx make_dos_label(struct disklabel *lp, uint32_t poff)
    138       1.3    phx {
    139       1.3    phx 	int i;
    140       1.3    phx 
    141       1.3    phx 	/* clear all partitions */
    142       1.3    phx 	lp->d_npartitions = RAW_PART + 1;
    143       1.3    phx 	for (i = 0; i < MAXPARTITIONS; i++) {
    144       1.3    phx 		lp->d_partitions[i].p_size = 0;
    145       1.3    phx 		lp->d_partitions[i].p_offset = 0;
    146       1.3    phx 		lp->d_partitions[i].p_fstype = 0;
    147       1.3    phx 	}
    148       1.3    phx 
    149       1.3    phx 	/* set DOS partition as root partition */
    150       1.3    phx 	lp->d_partitions[0].p_offset = poff;
    151       1.3    phx 	lp->d_partitions[0].p_fstype = FS_MSDOS;
    152       1.3    phx 
    153       1.3    phx 	/* disklabel is valid */
    154       1.3    phx 	lp->d_magic = lp->d_magic2 = DISKMAGIC;
    155       1.3    phx 	lp->d_checksum = 0;
    156       1.3    phx 	lp->d_checksum = dkcksum(lp);
    157       1.1    phx }
    158