grub-devel
[Top][All Lists]
Advanced

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

Support for GPT


From: Marco Gerards
Subject: Support for GPT
Date: Wed, 30 Nov 2005 23:27:58 +0100
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

[cc to John, he might be interested in this]

Hi,

Here is a patch which adds support for GPT and it also fixes building
GRUB.  I will commit this patch on Friday if there are no serious
concerns (I don't expect any).

The most important change is the one to partmap/pc.c.  GPT uses some
dummy MBR to make sure some partitioning programs don't overwrite the
GPT.  Even when this happens, it can restore a backup.  But this
change hopefully prevents GRUB from installing on such partition and
overwriting the partition data (which is directly after the MBR).

The next step would be figuring out how booting works on such box.  I
assume we full need support for EFI to do that.

A bit more important is the change of my email address.  At some time
my old email (address@hidden) address will expire, I am not
studying there anymore.  I am still reachable on that address, but
please remove that address from your address book.  All of my other
addresses still work.

Thanks,
Marco


2005-11-30  Marco Gerards  <address@hidden>

        * conf/common.rmk (grub_modules_init.lst): Use `-printf "%P\n"'
        and `cd' to make sure the filename is not prefixed with a
        directory name.
        (pkgdata_MODULES): Add `gpt.mod'.
        (gpt_mod_SOURCES): New variable.
        (gpt_mod_CFLAGS): Likewise.
        (gpt_mod_LDFLAGS): Likewise.

        * conf/i386-pc.rmk (grub_emu_SOURCES): Add `partmap/gpt.c'.

        * include/grub/pc_partition.h (GRUB_PC_PARTITION_TYPE_GPT_DISK):
        New macro.

        * partmap/gpt.c: New file.

        * partmap/pc.c (pc_partition_map_iterate): Don't continue when a
        GPT partition map is detected.


Index: conf/common.rmk
===================================================================
RCS file: /cvsroot/grub/grub2/conf/common.rmk,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 common.rmk
--- conf/common.rmk     23 Nov 2005 02:23:08 -0000      1.2
+++ conf/common.rmk     30 Nov 2005 22:22:12 -0000
@@ -6,7 +6,7 @@ grub_script.tab.c grub_script.tab.h: nor
 
 # For grub-emu.
 grub_modules_init.lst: geninit.sh
-       (find $(srcdir) -name '*.c' | xargs grep GRUB_MOD_INIT) > $@
+       (cd $(srcdir); find . -name '*.c' -printf "%P\n" | xargs grep 
GRUB_MOD_INIT) > $@
 
 grub_modules_init.h: $(filter-out grub_emu_init.c,$(grub_emu_SOURCES)) 
geninitheader.sh grub_modules_init.lst
        sh $(srcdir)/geninitheader.sh > $@
@@ -75,10 +75,9 @@ affs_mod_LDFLAGS = $(COMMON_LDFLAGS)
 sfs_mod_SOURCES = fs/sfs.c
 sfs_mod_CFLAGS = $(COMMON_CFLAGS)
 sfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
- 
 
-# Partiton maps.
-pkgdata_MODULES += amiga.mod apple.mod pc.mod sun.mod acorn.mod
+# Partition maps.
+pkgdata_MODULES += amiga.mod apple.mod pc.mod sun.mod acorn.mod gpt.mod
 
 # For amiga.mod
 amiga_mod_SOURCES = partmap/amiga.c
@@ -104,6 +103,11 @@ sun_mod_LDFLAGS = $(COMMON_LDFLAGS)
 acorn_mod_SOURCES = partmap/acorn.c
 acorn_mod_CFLAGS = $(COMMON_CFLAGS)
 acorn_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gpt.mod
+gpt_mod_SOURCES = partmap/gpt.c
+gpt_mod_CFLAGS = $(COMMON_CFLAGS)
+gpt_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 
 # Commands.
Index: conf/i386-pc.rmk
===================================================================
RCS file: /cvsroot/grub/grub2/conf/i386-pc.rmk,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 i386-pc.rmk
--- conf/i386-pc.rmk    18 Nov 2005 14:56:55 -0000      1.55
+++ conf/i386-pc.rmk    30 Nov 2005 22:22:12 -0000
@@ -95,7 +95,7 @@ grub_emu_SOURCES = commands/boot.c comma
        normal/completion.c normal/context.c normal/main.c              \
        normal/menu.c normal/menu_entry.c normal/misc.c normal/script.c \
        partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
-       partmap/acorn.c                                                 \
+       partmap/acorn.c partmap/gpt.c                                   \
        util/console.c util/grub-emu.c util/misc.c                      \
        util/i386/pc/biosdisk.c util/i386/pc/getroot.c                  \
        util/i386/pc/misc.c grub_emu_init.c
Index: include/grub/pc_partition.h
===================================================================
RCS file: /cvsroot/grub/grub2/include/grub/pc_partition.h,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 pc_partition.h
--- include/grub/pc_partition.h 4 Dec 2004 18:45:45 -0000       1.1
+++ include/grub/pc_partition.h 30 Nov 2005 22:22:12 -0000
@@ -49,6 +49,7 @@
 #define GRUB_PC_PARTITION_TYPE_FREEBSD         0xa5
 #define GRUB_PC_PARTITION_TYPE_OPENBSD         0xa6
 #define GRUB_PC_PARTITION_TYPE_NETBSD          0xa9
+#define GRUB_PC_PARTITION_TYPE_GPT_DISK                0xee
 #define GRUB_PC_PARTITION_TYPE_LINUX_RAID      0xfd
 
 /* Constants for BSD disk label.  */
Index: partmap/gpt.c
===================================================================
RCS file: partmap/gpt.c
diff -N partmap/gpt.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ partmap/gpt.c       30 Nov 2005 22:22:12 -0000
@@ -0,0 +1,227 @@
+/* gpt.c - Read GUID Partition Tables (GPT).  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002, 2005  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/partition.h>
+#include <grub/dl.h>
+#include <grub/pc_partition.h>
+
+struct grub_gpt_header
+{
+  grub_uint8_t magic[8];
+  grub_uint32_t version;
+  grub_uint32_t headersize;
+  grub_uint32_t crc32;
+  grub_uint32_t unused1;
+  grub_uint64_t primary;
+  grub_uint64_t backup;
+  grub_uint64_t start;
+  grub_uint64_t end;
+  grub_uint8_t guid[16];
+  grub_uint64_t partitions;
+  grub_uint32_t maxpart;
+  grub_uint32_t partentry_size;
+  grub_uint32_t partentry_crc32;
+} __attribute__ ((packed));
+
+struct grub_gpt_partentry
+{
+  grub_uint8_t type[16];
+  grub_uint8_t guid[16];
+  grub_uint64_t start;
+  grub_uint64_t end;
+  grub_uint8_t attrib;
+  char name[72];
+} __attribute__ ((packed));
+
+static grub_uint8_t grub_gpt_magic[8] =
+  {
+    45, 46, 49, 20, 50, 41, 52, 54
+  };
+
+static grub_uint8_t grub_gpt_partition_type_empty[16] = { 0 };
+
+static struct grub_partition_map grub_gpt_partition_map;
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+
+
+static grub_err_t
+gpt_partition_map_iterate (grub_disk_t disk,
+                          int (*hook) (grub_disk_t disk,
+                                       const grub_partition_t partition))
+{
+  struct grub_partition part;
+  struct grub_gpt_header gpt;
+  struct grub_gpt_partentry entry;
+  struct grub_disk raw;
+  struct grub_pc_partition_mbr mbr;
+  grub_uint64_t entries;
+  int partno = 1;
+  unsigned int i;
+  int last_offset = 0;
+
+  /* Enforce raw disk access.  */
+  raw = *disk;
+  raw.partition = 0;
+
+  /* Read the protective MBR.  */
+  if (grub_disk_read (&raw, 0, 0, sizeof (mbr), (char *) &mbr))
+    return grub_errno;
+
+  /* Check if it is valid.  */
+  if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
+    return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+
+  /* Make sure the MBR is a protective MBR and not a normal MBR.  */
+  if (mbr.entries[0].type != GRUB_PC_PARTITION_TYPE_GPT_DISK)
+    return grub_error (GRUB_ERR_BAD_PART_TABLE, "no GPT partition map found");
+
+  /* Read the GPT header.  */
+  if (grub_disk_read (&raw, 1, 0, sizeof (gpt), (char *) &gpt))
+    return grub_errno;
+
+  if (! grub_memcmp (gpt.magic, grub_gpt_magic, sizeof (grub_gpt_magic)))
+    return grub_error (GRUB_ERR_BAD_PART_TABLE, "no valid GPT header");
+
+  grub_dprintf ("gpt", "Read a valid GPT header\n");
+
+  entries = grub_le_to_cpu64 (gpt.partitions);
+  for (i = 0; i < grub_le_to_cpu32 (gpt.maxpart); i++)
+    {
+      if (grub_disk_read (&raw, entries, last_offset,
+                         sizeof (entry), (char *) &entry))
+       return grub_errno;
+
+      if (grub_memcmp (grub_gpt_partition_type_empty, entry.type,
+                      sizeof (grub_gpt_partition_type_empty)))
+       {
+         /* Calculate the first block and the size of the partition.  */
+         part.start = grub_le_to_cpu64 (entry.start);
+         part.len = (grub_le_to_cpu64 (entry.end)
+                     - grub_le_to_cpu64 (entry.start));
+         part.offset = entries;
+         part.index = partno;
+         part.partmap = &grub_gpt_partition_map;
+
+         grub_dprintf ("gpt", "GPT entry %d: start=%ld, length=%ld\n",
+                       partno, part.start, part.len);
+
+         if (hook (disk, &part))
+           return grub_errno;
+       }
+
+      partno++;
+      last_offset += grub_le_to_cpu32 (gpt.partentry_size);
+      if (last_offset == GRUB_DISK_SECTOR_SIZE)
+       {
+         last_offset = 0;
+         entries++;
+       }
+    }
+
+  return 0;
+}
+
+
+static grub_partition_t
+gpt_partition_map_probe (grub_disk_t disk, const char *str)
+{
+  grub_partition_t p = 0;
+  int partnum = 0;
+  char *s = (char *) str;
+
+  auto int find_func (grub_disk_t d, const grub_partition_t partition);
+    
+  int find_func (grub_disk_t d __attribute__ ((unused)),
+                const grub_partition_t partition)
+      {
+      if (partnum == partition->index)
+       {
+         p = (grub_partition_t) grub_malloc (sizeof (*p));
+         if (! p)
+           return 1;
+         
+         grub_memcpy (p, partition, sizeof (*p));
+         return 1;
+       }
+      
+      return 0;
+    }
+  
+  /* Get the partition number.  */
+  partnum = grub_strtoul (s, 0, 10);
+  if (grub_errno)
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
+      return 0;
+    }
+
+  if (gpt_partition_map_iterate (disk, find_func))
+    goto fail;
+
+  return p;
+
+ fail:
+  grub_free (p);
+  return 0;
+}
+
+
+static char *
+gpt_partition_map_get_name (const grub_partition_t p)
+{
+  char *name;
+
+  name = grub_malloc (13);
+  if (! name)
+    return 0;
+
+  grub_sprintf (name, "%d", p->index);
+  return name;
+}
+
+
+/* Partition map type.  */
+static struct grub_partition_map grub_gpt_partition_map =
+  {
+    .name = "gpt_partition_map",
+    .iterate = gpt_partition_map_iterate,
+    .probe = gpt_partition_map_probe,
+    .get_name = gpt_partition_map_get_name
+  };
+
+GRUB_MOD_INIT(gpt_partition_map)
+{
+  grub_partition_map_register (&grub_gpt_partition_map);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(gpt_partition_map)
+{
+  grub_partition_map_unregister (&grub_gpt_partition_map);
+}
Index: partmap/pc.c
===================================================================
RCS file: /cvsroot/grub/grub2/partmap/pc.c,v
retrieving revision 1.6
diff -u -p -u -p -r1.6 pc.c
--- partmap/pc.c        13 Nov 2005 15:47:09 -0000      1.6
+++ partmap/pc.c        30 Nov 2005 22:22:12 -0000
@@ -140,6 +140,10 @@ pc_partition_map_iterate (grub_disk_t di
                        "partition %d: flag 0x%x, type 0x%x, start 0x%lx, len 
0x%lx\n",
                        p.index, e->flag, pcdata.dos_type, p.start, p.len);
 
+         /* If this is a GPT partition, this MBR is just a dummy.  */
+         if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && p.index == 0)
+           return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr");
+
          /* If this partition is a normal one, call the hook.  */
          if (! grub_pc_partition_is_empty (e->type)
              && ! grub_pc_partition_is_extended (e->type))






reply via email to

[Prev in Thread] Current Thread [Next in Thread]