Author: ae
Date: Wed Jul 27 04:23:26 2011
New Revision: 224465
URL: http://svn.freebsd.org/changeset/base/224465

Log:
  MFC r216754:
    Make EBR probe method less strictly to be able detect EBRs with
    small non fatal inconsistency. EBR may contain boot loader and sometimes
    it just has some garbage data. Now this does not prevent FreeBSD to use
    extended partitions. But since we do not support bootcode for EBR we mark
    tables which have non empty boot area as corrupt. This does make them
    readonly and we can not damage this data.
  
  MFC r223594:
    EBR could contain an early stage of boot code. But we do not support it.
    Remove message about non empty bootcode, we can not break something
    while GEOM_PART_EBR_COMPAT is defined.
  
    But without GEOM_PART_EBR_COMPAT any changes in EBR are allowed and we
    can accidentally wipe the boot code. To do not break anything save
    the first EBR chunk and keep it untouched each time when we are
    changing EBR. Note that we are still not support boot code for EBR.
  
    PR:         kern/141235

Modified:
  stable/8/sys/geom/part/g_part_ebr.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/geom/label/   (props changed)

Modified: stable/8/sys/geom/part/g_part_ebr.c
==============================================================================
--- stable/8/sys/geom/part/g_part_ebr.c Wed Jul 27 04:10:32 2011        
(r224464)
+++ stable/8/sys/geom/part/g_part_ebr.c Wed Jul 27 04:23:26 2011        
(r224465)
@@ -51,6 +51,9 @@ __FBSDID("$FreeBSD$");
 
 struct g_part_ebr_table {
        struct g_part_table     base;
+#ifndef GEOM_PART_EBR_COMPAT
+       u_char          ebr[EBRSIZE];
+#endif
 };
 
 struct g_part_ebr_entry {
@@ -395,7 +398,7 @@ g_part_ebr_probe(struct g_part_table *ta
        char psn[8];
        struct g_provider *pp;
        u_char *buf, *p;
-       int error, index, res, sum;
+       int error, index, res;
        uint16_t magic;
 
        pp = cp->provider;
@@ -427,29 +430,11 @@ g_part_ebr_probe(struct g_part_table *ta
        if (magic != DOSMAGIC)
                goto out;
 
-       /*
-        * The sector is all zeroes, except for the partition entries,
-        * pseudo boot code and some signatures or disk serial number.
-        * The latter can be found in the 9 bytes immediately in front
-        * of the partition table.
-        */
-       sum = 0;
-       for (index = 96; index < DOSPARTOFF - 9; index++)
-               sum += buf[index];
-       if (sum != 0)
-               goto out;
-
-       for (index = 0; index < NDOSPART; index++) {
+       for (index = 0; index < 2; index++) {
                p = buf + DOSPARTOFF + index * DOSPARTSIZE;
                if (p[0] != 0 && p[0] != 0x80)
                        goto out;
-               if (index < 2)
-                       continue;
-               /* The 3rd & 4th entries are always zero. */
-               if ((le64dec(p+0) + le64dec(p+8)) != 0)
-                       goto out;
        }
-
        res = G_PART_PROBE_PRI_NORM;
 
  out:
@@ -483,6 +468,19 @@ g_part_ebr_read(struct g_part_table *bas
 
                ebr_entry_decode(buf + DOSPARTOFF + 0 * DOSPARTSIZE, ent + 0);
                ebr_entry_decode(buf + DOSPARTOFF + 1 * DOSPARTSIZE, ent + 1);
+
+               /* The 3rd & 4th entries should be zeroes. */
+               if (le64dec(buf + DOSPARTOFF + 2 * DOSPARTSIZE) +
+                   le64dec(buf + DOSPARTOFF + 3 * DOSPARTSIZE) != 0) {
+                       basetable->gpt_corrupt = 1;
+                       printf("GEOM: %s: invalid entries in the EBR 
ignored.\n",
+                           pp->name);
+               }
+#ifndef GEOM_PART_EBR_COMPAT
+               /* Save the first EBR, it can contain a boot code */
+               if (lba == 0)
+                       bcopy(buf, table->ebr, sizeof(table->ebr));
+#endif
                g_free(buf);
 
                if (ent[0].dp_typ == 0)
@@ -570,6 +568,9 @@ g_part_ebr_type(struct g_part_table *bas
 static int
 g_part_ebr_write(struct g_part_table *basetable, struct g_consumer *cp)
 {
+#ifndef GEOM_PART_EBR_COMPAT
+       struct g_part_ebr_table *table;
+#endif
        struct g_provider *pp;
        struct g_part_entry *baseentry, *next;
        struct g_part_ebr_entry *entry;
@@ -579,6 +580,10 @@ g_part_ebr_write(struct g_part_table *ba
 
        pp = cp->provider;
        buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO);
+#ifndef GEOM_PART_EBR_COMPAT
+       table = (struct g_part_ebr_table *)basetable;
+       bcopy(table->ebr, buf, DOSPARTOFF);
+#endif
        le16enc(buf + DOSMAGICOFFSET, DOSMAGIC);
 
        baseentry = LIST_FIRST(&basetable->gpt_entry);
@@ -631,7 +636,10 @@ g_part_ebr_write(struct g_part_table *ba
 
                error = g_write_data(cp, baseentry->gpe_start * pp->sectorsize,
                    buf, pp->sectorsize);
-
+#ifndef GEOM_PART_EBR_COMPAT
+               if (baseentry->gpe_start == 0)
+                       bzero(buf, DOSPARTOFF);
+#endif
                baseentry = next;
        } while (!error && baseentry != NULL);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to