Source-Changes-HG archive

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

[src/netbsd-10]: src/sys/arch/i386/stand/bootxx Pull up following revision(s)...



details:   https://anonhg.NetBSD.org/src/rev/94af24dbdf13
branches:  netbsd-10
changeset: 377190:94af24dbdf13
user:      martin <martin%NetBSD.org@localhost>
date:      Fri Jun 30 17:20:28 2023 +0000

description:
Pull up following revision(s) (requested by manu in ticket #222):

        sys/arch/i386/stand/bootxx/boot1.c: revision 1.22

Primary bootstrap is now able to read a GPT inside RAIDframe.

Previously, primary bootstrap was able to boot on RAID-1 RAIDframe set
with the limitation that the FFS filesystem had to start at bloc 0 in the
RAID. That allowed inner RAID partitionning with a disklabel, but not with
a GPT.

When booting on a RAID-1 RAIDframe, primary bootstrap now first try a
filesystem at bloc 0 of the RAID as before. On failure, it tries to
read a GPT and load secondary bootstrap from, by priority;
1) the first partition with the bootme attribute set
2) the first partition of type FFS, LFS, CCD or CGD
3) the first partition present in the GPT

diffstat:

 sys/arch/i386/stand/bootxx/boot1.c |  163 ++++++++++++++++++++++++++++++++++++-
 1 files changed, 161 insertions(+), 2 deletions(-)

diffs (203 lines):

diff -r cd44b60e4310 -r 94af24dbdf13 sys/arch/i386/stand/bootxx/boot1.c
--- a/sys/arch/i386/stand/bootxx/boot1.c        Fri Jun 30 17:13:50 2023 +0000
+++ b/sys/arch/i386/stand/bootxx/boot1.c        Fri Jun 30 17:20:28 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: boot1.c,v 1.21 2021/06/24 01:23:16 gutteridge Exp $    */
+/*     $NetBSD: boot1.c,v 1.21.10.1 2023/06/30 17:20:28 martin Exp $   */
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -30,15 +30,17 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: boot1.c,v 1.21 2021/06/24 01:23:16 gutteridge Exp $");
+__RCSID("$NetBSD: boot1.c,v 1.21.10.1 2023/06/30 17:20:28 martin Exp $");
 
 #include <lib/libsa/stand.h>
 #include <lib/libkern/libkern.h>
 #include <biosdisk_ll.h>
 
 #include <sys/param.h>
+#include <sys/uuid.h>
 #include <sys/bootblock.h>
 #include <sys/disklabel.h>
+#include <sys/disklabel_gpt.h>
 #include <dev/raidframe/raidframevar.h>        /* For RF_PROTECTED_SECTORS */
 
 #define XSTR(x) #x
@@ -49,6 +51,9 @@ static daddr_t bios_sector;
 static struct biosdisk_ll d;
 
 const char *boot1(uint32_t, uint64_t *);
+#ifndef NO_GPT
+static daddr_t gpt_lookup(daddr_t);
+#endif
 extern void putstr(const char *);
 
 extern struct disklabel ptn_disklabel;
@@ -90,6 +95,17 @@ boot1(uint32_t biosdev, uint64_t *sector
        fd = ob();
        if (fd != -1)
                goto done;
+
+#ifndef NO_GPT
+       /*
+        * Test for a GPT inside the RAID
+        */
+       bios_sector += gpt_lookup(bios_sector);
+       fd = ob();
+       if (fd != -1)
+               goto done;
+#endif
+
        /*
         * Nothing at the start of the MBR partition, fallback on
         * partition 'a' from the disklabel in this MBR partition.
@@ -144,3 +160,146 @@ blkdevstrategy(void *devdata, int flag, 
 
        return 0;
 }
+
+#ifndef NO_GPT
+static int
+is_unused(struct gpt_ent *ent)
+{
+       const struct uuid unused = GPT_ENT_TYPE_UNUSED;
+
+       return (memcmp(ent->ent_type, &unused, sizeof(unused)) == 0);
+}
+
+static int
+is_bootable(struct gpt_ent *ent)
+{
+       /* GPT_ENT_TYPE_NETBSD_RAID omitted as we are already in a RAID */
+       const struct uuid bootable[] = {
+               GPT_ENT_TYPE_NETBSD_FFS,
+               GPT_ENT_TYPE_NETBSD_LFS,
+               GPT_ENT_TYPE_NETBSD_CCD,
+               GPT_ENT_TYPE_NETBSD_CGD,
+       };
+       int i;
+
+       for (i = 0; i < sizeof(bootable) / sizeof(*bootable); i++) {
+               if (memcmp(ent->ent_type, &bootable[i],
+                   sizeof(struct uuid)) == 0)
+                       return 1;
+       }
+
+       return 0;
+}
+
+static daddr_t
+gpt_lookup(daddr_t sector)
+{
+       char buf[BIOSDISK_DEFAULT_SECSIZE];
+       struct mbr_sector *pmbr;        
+       const char gpt_hdr_sig[] = GPT_HDR_SIG;
+       struct gpt_hdr *hdr;
+       struct gpt_ent *ent;
+       uint32_t nents;
+       uint32_t entsz;
+       uint32_t entries_per_sector;
+       uint32_t sectors_per_entry;
+       uint64_t firstpart_lba = 0;
+       uint64_t bootable_lba = 0;
+       uint64_t bootme_lba = 0;
+       int i, j;
+
+       /*
+        * Look for a PMBR
+        */
+       if (readsects(&d, sector, 1, buf, 1) != 0)
+               return 0;
+
+       pmbr = (struct mbr_sector *)buf;
+
+       if (pmbr->mbr_magic != htole16(MBR_MAGIC))
+               return 0;
+
+       if (pmbr->mbr_parts[0].mbrp_type != MBR_PTYPE_PMBR)
+               return 0;
+
+       sector++; /* skip PMBR */
+
+       /*
+        * Look for a GPT header
+        * Space is scarce, we do not check CRC.
+        */
+       if (readsects(&d, sector, 1, buf, 1) != 0)
+               return 0;
+
+       hdr = (struct gpt_hdr *)buf;
+
+       if (memcmp(gpt_hdr_sig, hdr->hdr_sig, sizeof(hdr->hdr_sig)) != 0)
+               return 0;
+
+       if (hdr->hdr_revision != htole32(GPT_HDR_REVISION))
+               return 0;
+
+       if (le32toh(hdr->hdr_size) > BIOSDISK_DEFAULT_SECSIZE)
+               return 0;
+
+       nents = le32toh(hdr->hdr_entries);
+       entsz = le32toh(hdr->hdr_entsz);
+
+       sector++; /* skip GPT header */
+
+       /*
+        * Read partition table
+        *
+        * According to UEFI specification section 5.3.2, entries
+        * are 128 * (2^n) bytes long. The most common scenario is
+        * 128 bytes (n = 0) where there are 4 entries per sector.
+        * If n > 2, then entries spans multiple sectors, but they
+        * remain sector-aligned.
+        */
+       entries_per_sector = BIOSDISK_DEFAULT_SECSIZE / entsz;
+       if (entries_per_sector == 0)
+               entries_per_sector = 1;
+
+       sectors_per_entry = entsz / BIOSDISK_DEFAULT_SECSIZE;
+       if (sectors_per_entry == 0)
+               sectors_per_entry = 1;
+
+       for (i = 0; i < nents; i += entries_per_sector) {
+               if (readsects(&d, sector, 1, buf, 1) != 0)
+                       return 0;
+
+               sector += sectors_per_entry;
+
+               for (j = 0; j < entries_per_sector; j++) {
+                       ent = (struct gpt_ent *)&buf[j * entsz];
+
+                       if (is_unused(ent))
+                               continue;
+
+                       /* First bootme wins, we can stop there */
+                       if (ent->ent_attr & GPT_ENT_ATTR_BOOTME) {
+                               bootme_lba = le64toh(ent->ent_lba_start);
+                               goto out;
+                       }
+
+                       if (firstpart_lba == 0)
+                               firstpart_lba = le64toh(ent->ent_lba_start);
+
+                       if (is_bootable(ent) && bootable_lba == 0)
+                               bootable_lba = le64toh(ent->ent_lba_start);
+               }
+       }
+
+out:
+       if (bootme_lba)
+               return bootme_lba;
+
+       if (bootable_lba)
+               return bootable_lba;
+
+       if (firstpart_lba)
+               return firstpart_lba;
+
+       return 0;
+}
+#endif /* ! NO_GPT */



Home | Main Index | Thread Index | Old Index