Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/ofppc/stand/ofwboot When there is no NetBSD MBR par...



details:   https://anonhg.NetBSD.org/src/rev/c7dbf390fee7
branches:  trunk
changeset: 768580:c7dbf390fee7
user:      phx <phx%NetBSD.org@localhost>
date:      Sun Aug 21 13:08:57 2011 +0000

description:
When there is no NetBSD MBR partition with a valid disklabel, look for
the first FAT partition and construct a disklabel with an MSDOS filesystem
in partition 'a'.

diffstat:

 sys/arch/ofppc/stand/ofwboot/mbr.c |  128 +++++++++++++++++++++++++-----------
 1 files changed, 87 insertions(+), 41 deletions(-)

diffs (169 lines):

diff -r 4b4eb43e2aa7 -r c7dbf390fee7 sys/arch/ofppc/stand/ofwboot/mbr.c
--- a/sys/arch/ofppc/stand/ofwboot/mbr.c        Sun Aug 21 11:04:21 2011 +0000
+++ b/sys/arch/ofppc/stand/ofwboot/mbr.c        Sun Aug 21 13:08:57 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mbr.c,v 1.2 2011/08/18 09:03:28 phx Exp $      */
+/*     $NetBSD: mbr.c,v 1.3 2011/08/21 13:08:57 phx Exp $      */
 
 /*
  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -39,14 +39,9 @@
 
 #include "mbr.h"
 
-
-static u_long
-get_long(const void *p)
-{
-       const unsigned char *cp = p;
-
-       return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
-}
+static int find_mbr_part(struct of_dev *, uint32_t, char *,
+    struct disklabel *, uint32_t, uint8_t, int);
+static void make_dos_label(struct disklabel *, uint32_t);
 
 /*
  * Find a valid MBR disklabel.
@@ -55,58 +50,109 @@
 search_mbr_label(struct of_dev *devp, u_long off, char *buf,
     struct disklabel *lp, u_long off0)
 {
+       static uint8_t fat_types[] = {
+               MBR_PTYPE_FAT12, MBR_PTYPE_FAT16S, MBR_PTYPE_FAT16B,
+               MBR_PTYPE_FAT32, MBR_PTYPE_FAT32L, MBR_PTYPE_FAT16L
+       };
+       size_t read;
+       uint32_t poff;
+       int i;
+
+       /* Find a disklabel in a NetBSD or 386BSD partition. */
+       poff = find_mbr_part(devp, off, buf, lp, 0, MBR_PTYPE_NETBSD, 0);
+#ifdef COMPAT_386BSD_MBRPART
+       if (poff == 0) {
+               poff = find_mbr_part(devp, off, buf, lp, 0,
+                   MBR_PTYPE_386BSD, 0);
+               if (poff != 0)
+                       printf("WARNING: old BSD partition ID!\n");
+       }
+#endif
+       if (poff != 0) {
+               if (strategy(devp, F_READ, poff + MBR_LABELSECTOR, DEV_BSIZE,
+                   buf, &read) == 0 && read == DEV_BSIZE)
+                       if (getdisklabel(buf, lp) == NULL)
+                               return 0;
+       }
+
+       /*
+        * No BSD partition with a valid disklabel found, so try to
+        * construct a label from a DOS partition.
+        */
+       for (i = 0; i < sizeof(fat_types); i++) {
+               poff = find_mbr_part(devp, off, buf, lp, 0, fat_types[i], 0);
+               if (poff != 0) {
+                       make_dos_label(lp, poff);
+                       return 0;
+               }
+       }
+
+       return ERDLAB;
+}
+
+static int
+find_mbr_part(struct of_dev *devp, uint32_t off, char *buf,
+    struct disklabel *lp, uint32_t off0, uint8_t ptype, int recursion)
+{
        size_t read;
        struct mbr_partition *p;
        int i;
-       u_long poff;
-       static int recursion;
+       uint32_t poff;
 
        if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
            || read != DEV_BSIZE)
-               return ERDLAB;
+               return 0;
 
-       if (*(u_int16_t *)&buf[MBR_MAGIC_OFFSET] != sa_htole16(MBR_MAGIC))
-               return ERDLAB;
+       if (*(uint16_t *)&buf[MBR_MAGIC_OFFSET] != sa_htole16(MBR_MAGIC))
+               return 0;
 
        if (recursion++ <= 1)
                off0 += off;
+
        for (p = (struct mbr_partition *)(buf + MBR_PART_OFFSET), i = 0;
             i < MBR_PART_COUNT; i++, p++) {
-               if (p->mbrp_type == MBR_PTYPE_NETBSD
-#ifdef COMPAT_386BSD_MBRPART
-                   || (p->mbrp_type == MBR_PTYPE_386BSD &&
-                       (printf("WARNING: old BSD partition ID!\n"), 1)
-                       /* XXX XXX - libsa printf() is void */ )
-#endif
-                   ) {
-                       poff = get_long(&p->mbrp_start) + off0;
-                       if (strategy(devp, F_READ, poff + MBR_LABELSECTOR,
-                                    DEV_BSIZE, buf, &read) == 0
-                           && read == DEV_BSIZE) {
-                               if (getdisklabel(buf, lp) == NULL) {
-                                       recursion--;
-                                       return 0;
-                               }
+               if (p->mbrp_type == ptype) {
+                       recursion--;
+                       return sa_le32toh(p->mbrp_start) + off0;
+               }
+               else if (p->mbrp_type == MBR_PTYPE_EXT) {
+                       poff = find_mbr_part(devp, sa_le32toh(p->mbrp_start),
+                           buf, lp, off0, ptype, recursion);
+                       if (poff != 0) {
+                               recursion--;
+                               return poff;
                        }
                        if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
                            || read != DEV_BSIZE) {
                                recursion--;
-                               return ERDLAB;
-                       }
-               } else if (p->mbrp_type == MBR_PTYPE_EXT) {
-                       poff = get_long(&p->mbrp_start);
-                       if (!search_mbr_label(devp, poff, buf, lp, off0)) {
-                               recursion--;
                                return 0;
                        }
-                       if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
-                           || read != DEV_BSIZE) {
-                               recursion--;
-                               return ERDLAB;
-                       }
                }
        }
 
        recursion--;
-       return ERDLAB;
+       return 0;
 }
+
+static void
+make_dos_label(struct disklabel *lp, uint32_t poff)
+{
+       int i;
+
+       /* clear all partitions */
+       lp->d_npartitions = RAW_PART + 1;
+       for (i = 0; i < MAXPARTITIONS; i++) {
+               lp->d_partitions[i].p_size = 0;
+               lp->d_partitions[i].p_offset = 0;
+               lp->d_partitions[i].p_fstype = 0;
+       }
+
+       /* set DOS partition as root partition */
+       lp->d_partitions[0].p_offset = poff;
+       lp->d_partitions[0].p_fstype = FS_MSDOS;
+
+       /* disklabel is valid */
+       lp->d_magic = lp->d_magic2 = DISKMAGIC;
+       lp->d_checksum = 0;
+       lp->d_checksum = dkcksum(lp);
+}



Home | Main Index | Thread Index | Old Index