/* $NetBSD: mbrlabel.c,v 1.2 1998/12/03 11:20:50 fair Exp $ */ /* * Copyright (C) 1998 Wolfgang Solfrank. * Copyright (C) 1998 TooLs GmbH. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by TooLs GmbH. * 4. The name of TooLs GmbH may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #ifndef lint __RCSID("$NetBSD: mbrlabel.c,v 1.2 1998/12/03 11:20:50 fair Exp $"); #endif /* not lint */ #include #include #include #include #include #include #include #include #include "mbrlabel.h" #include "dkcksum.h" #define FIRSTPART 0 int main __P((int, char **)); void usage __P((void)); void getlabel __P((int)); void setlabel __P((int)); int getparts __P((int, int, u_int32_t)); int nbsdtype __P((int)); u_int32_t getlong __P((void *p)); struct disklabel label; void getlabel(sd) int sd; { struct partition save; if (ioctl(sd, DIOCGDINFO, &label) < 0) { perror("get label"); exit(1); } save = label.d_partitions[RAW_PART]; memset(label.d_partitions, 0, sizeof label.d_partitions); label.d_partitions[RAW_PART] = save; /* * Some ports seem to not set the number of partitions * correctly, albeit they seem to set the raw partiton ok! */ if (label.d_npartitions <= RAW_PART) label.d_npartitions = RAW_PART + 1; } void setlabel(sd) int sd; { label.d_checksum = 0; label.d_checksum = dkcksum(&label); if (ioctl(sd, DIOCSDINFO, &label) < 0) { perror("set label"); exit(1); } } static struct typetab { int mbrtype; int nbsdtype; } typetable[] = { { MBR_NETBSD, FS_BSDFFS }, { MBR_386BSD, FS_BSDFFS }, { MBR_FAT12, FS_MSDOS }, { MBR_FAT16S, FS_MSDOS }, { MBR_FAT16B, FS_MSDOS }, { MBR_FAT32, FS_MSDOS }, { MBR_FAT32L, FS_MSDOS }, { MBR_FAT16L, FS_MSDOS }, { MBR_LNXEXT2, FS_EX2FS }, { 0, 0 } }; int nbsdtype(type) int type; { struct typetab *tt; for (tt = typetable; tt->mbrtype; tt++) if (tt->mbrtype == type) return tt->nbsdtype; return FS_OTHER; } u_int32_t getlong(p) void *p; { unsigned char *cp = p; return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24); } int getparts(sd, np, off) int sd; int np; u_int32_t off; { unsigned char buf[DEV_BSIZE]; struct mbr_partition *mpart, *epart; off_t loff = 0; /* XXX this nonsense shuts up GCC 2.7.2.2 */ loff = (off_t)off * DEV_BSIZE; if (lseek(sd, loff, SEEK_SET) != loff) { perror("seek label"); exit(1); } if (read(sd, buf, DEV_BSIZE) != DEV_BSIZE) { perror("read label"); exit(1); } if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) return np; mpart = (void *)(buf + MBRPARTOFF); for (epart = mpart + NMBRPART; mpart < epart; mpart++) { switch (mpart->mp_typ) { case 0: /* Nothing to do */ break; case MBR_EXT: case MBR_EXT_LBA: /* Will be handled below */ break; default: label.d_partitions[np].p_size = getlong(&mpart->mp_size); label.d_partitions[np].p_offset = getlong(&mpart->mp_start) + off; label.d_partitions[np].p_fstype = nbsdtype(mpart->mp_typ); switch (label.d_partitions[np].p_fstype) { case FS_BSDFFS: label.d_partitions[np].p_size = 16384; label.d_partitions[np].p_fsize = 1024; label.d_partitions[np].p_frag = 8; label.d_partitions[np].p_cpg = 16; break; #ifdef __does_not_happen__ case FS_BSDLFS: label.d_partitions[np].p_size = 16384; label.d_partitions[np].p_fsize = 1024; label.d_partitions[np].p_frag = 8; label.d_partitions[np].p_sgs = XXX; break; #endif } np++; break; } if (np >MAXPARTITIONS) return np; if (np == RAW_PART) np++; } mpart = (void *)(buf + MBRPARTOFF); for (epart = mpart + NMBRPART; mpart < epart; mpart++) { switch (mpart->mp_typ) { case MBR_EXT: case MBR_EXT_LBA: np = getparts(sd, np, getlong(&mpart->mp_start) + off); break; default: break; } if (np >MAXPARTITIONS) return np; } return np; } void usage() { fprintf(stderr, "Usage: mbrlabel { rawdisk }\n"); exit(1); } int main(argc, argv) int argc; char **argv; { int sd; int np; char name[MAXPATHLEN]; if (argc != 2) usage(); if ((sd = opendisk(*++argv, O_RDWR, name, MAXPATHLEN, 0)) < 0) { perror(*argv); exit(1); } getlabel(sd); np = getparts(sd, FIRSTPART, MBRSECTOR); if (np > label.d_npartitions) label.d_npartitions = np; setlabel(sd); close(sd); return 0; }