HFS autodetect added. With changelog this time. Should already be suitable
for inclusion

On Wed, Apr 22, 2009 at 12:03 AM, Vladimir Serbinenko <phco...@gmail.com>wrote:

>
>
> On Tue, Apr 21, 2009 at 9:49 PM, Isaac Dupree <
> m...@isaac.cedarswampstudios.org> wrote:
>
>> Peter Cros wrote:
>> > I don't think it is compatible with current MBR/GPT hybrid ?partitioning
>> on
>> > intel macs for grub-pc booting.
>>
>> well, it doesn't necessarily order the partitions in the same way as e.g.
>> rEFIt gptsync does, but that's because this GRUB implementation gives you
>> more
>> control!  You can even pick different MBR-partition-configurations, before
>> booting different OSes.
>
> Yes it was written with such possibility in mind. I don't see why grub2
> will enforce mbr partitions to be sorted since mbr doesn't require such
> thing. If you ask grub2 to put partitions in reverse order it does it. As to
> partition in zeroth slot it spans across  the space before the first MBR
> partition and is so called protective partition and is required for some
> tools including grub2 itself to recognise gpt disk as such.
> About compatibiliy: hybrid MBR is against specifications - it's a trick to
> boot legacy OS. So the only compatibility you can speak about is the ability
> to boot a legacy OS of your choice.
>
>>
>>
>> Vladimir Serbinenko wrote:
>> > Here there are 2 differences. First partition type for hfs+ isn't
>> > autodetected, I will fix this, just I thought it ws unnecessary AFAIK
>> every
>> > OS which understands HFS+ understands GPT.
>>
>> At least Mac OS X 10.3 and earlier don't understand GPT, and it actually
>> makes
>> a difference with Apple's "target disk mode"!  And there may be a few
>> other
>> combinations.
>>
> Ok
>
>>
>> -Isaac
>>
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>>
>
>
diff --git a/ChangeLog b/ChangeLog
index ca0ab43..2a2ba20 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2009-04-21  Vladimir Serbinenko <phco...@gmail.com>
+
+	gptsync
+
+	* commands/gptsync.c: new file
+	* conf/common.rmk (pkglib_MODULES): add gptsync.mod
+	(gptsync_mod_SOURCES): new variable
+	(gptsync_mod_CFLAGS): likewise
+	(gptsync_mod_LDFLAGS): likewise
+	* include/grub/pc_partition.h (GRUB_PC_PARTITION_TYPE_NTFS): 
+	new definition
+	(GRUB_PC_PARTITION_TYPE_HFS): likewise
+	* conf/i386-coreboot.rmk (grub_emu_SOURCES): add commands/gptsync.c
+	* conf/i386-ieee1275.rmk: likewise
+	* conf/i386-pc.rmk: likewise
+	* conf/powerpc-ieee1275.rmk: likewise
+
+
 2009-04-19  Vladimir Serbinenko <phco...@gmail.com>
 
 	Correct GPT definition
diff --git a/commands/gptsync.c b/commands/gptsync.c
new file mode 100644
index 0000000..cbedf45
--- /dev/null
+++ b/commands/gptsync.c
@@ -0,0 +1,255 @@
+/* gptsync.c - fill the mbr based on gpt entries  */
+/* XXX: I don't know what to do if sector size isn't 512 bytes */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/command.h>
+#include <grub/dl.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/pc_partition.h>
+#include <grub/partition.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/fs.h>
+
+/* Convert a LBA address to a CHS address in the INT 13 format.  */
+/* Taken from grub1. */
+/* XXX: use hardcoded geometry of C = 1024, H = 255, S = 63. 
+   Is it a problem?
+*/
+static void 
+lba_to_chs (int lba, grub_uint8_t *cl, grub_uint8_t *ch, 
+	    grub_uint8_t *dh)
+{
+  int cylinder, head, sector;
+  int sectors = 63, heads = 255, cylinders = 1024;
+  
+  sector = lba % sectors + 1;
+  head = (lba / sectors) % heads;
+  cylinder = lba / (sectors * heads);
+  
+  if (cylinder >= cylinders)
+    {
+      *cl = *ch = *dh = 0xff;
+      return;
+    }
+  
+  *cl = sector | ((cylinder & 0x300) >> 2);
+  *ch = cylinder & 0xFF;
+  *dh = head;
+}
+
+static grub_err_t
+grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)), 
+		  int argc, char **args)
+{
+  grub_device_t dev;
+  struct grub_pc_partition_mbr mbr;
+  struct grub_partition *partition;
+  grub_disk_addr_t first_sector;
+  int numactive = 0;
+
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
+  if (argc > 4)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "only 3 partitions can be "
+		       "in hybrid MBR");
+
+  if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
+    {
+      args[0][grub_strlen (args[0]) - 1] = 0;
+      dev = grub_device_open (args[0] + 1); 
+      args[0][grub_strlen (args[0]) - 1] = ')';
+    }
+  else
+    dev = grub_device_open (args[0]); 
+
+  if (! dev)
+    return grub_errno;
+
+  if (! dev->disk)
+    {
+      grub_device_close (dev);
+      return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a disk");
+    }
+
+  /* Read the protective MBR.  */
+  if (grub_disk_read (dev->disk, 0, 0, sizeof (mbr), (char *) &mbr))
+    {
+      grub_device_close (dev);
+      return grub_errno;
+    }
+
+  /* Check if it is valid.  */
+  if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
+    {
+      grub_device_close (dev);    
+      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)
+    {
+      grub_device_close (dev);
+      return grub_error (GRUB_ERR_BAD_PART_TABLE, "no GPT partition map found");
+    }
+  
+  int i;
+  first_sector = dev->disk->total_sectors;
+  for (i = 1; i < argc; i++)
+    {
+      char *separator, csep = 0;
+      grub_uint8_t type;
+      separator = grub_strchr (args[i], '+');
+      if (! separator)
+	separator = grub_strchr (args[i], '-');
+      if (separator)
+	{
+	  csep = *separator;
+	  *separator = 0;
+	}
+      partition = grub_partition_probe (dev->disk, args[i]);
+      if (separator)
+	*separator = csep;
+      if (! partition)
+	{  
+	  grub_device_close (dev);
+	  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such partition");
+	}
+
+      if (partition->start + partition->len > 0xffffffff)
+	{  
+	  grub_device_close (dev);
+	  return grub_error (GRUB_ERR_OUT_OF_RANGE, 
+			     "only partitions resding in the first 2TB "
+			     "can be presen in hybrid MBR");
+	}
+	
+
+      if (first_sector > partition->start)
+	first_sector = partition->start;
+
+      if (separator && *(separator + 1))
+	type = grub_strtoul (separator + 1, 0, 0);
+      else
+	{
+	  grub_fs_t fs = 0;
+	  dev->disk->partition = partition;
+	  fs = grub_fs_probe (dev);
+
+	  /* Unknown filesystem isn't fatal. */
+	  if (grub_errno == GRUB_ERR_UNKNOWN_FS)
+	    {
+	      fs = 0;
+	      grub_errno = GRUB_ERR_NONE;
+	    }
+
+	  if (fs && grub_strcmp (fs->name, "ntfs") == 0)
+	    type = GRUB_PC_PARTITION_TYPE_NTFS;
+	  else if (fs && grub_strcmp (fs->name, "fat") == 0)
+	    /* FIXME: detect FAT16. */
+	    type = GRUB_PC_PARTITION_TYPE_FAT32_LBA;
+	  else if (fs && (grub_strcmp (fs->name, "hfsplus") == 0
+			  || grub_strcmp (fs->name, "hfs") == 0))
+	    type = GRUB_PC_PARTITION_TYPE_HFS;
+	  else
+	    /* FIXME: detect more types. */
+	    type = GRUB_PC_PARTITION_TYPE_EXT2FS;
+
+	  dev->disk->partition = 0;
+	}
+
+      mbr.entries[i].flag = (csep == '+') ? 0x80 : 0;
+      if (csep == '+')
+	{
+	  numactive++;
+	  if (numactive == 2)
+	    {
+	      grub_device_close (dev);
+	      return grub_error (GRUB_ERR_BAD_ARGUMENT, 
+				 "only one partition can be active");
+	    }
+	}
+      mbr.entries[i].type = type;
+      mbr.entries[i].start = grub_cpu_to_le32 (partition->start);
+      lba_to_chs (partition->start, 
+		  &(mbr.entries[i].start_sector),
+		  &(mbr.entries[i].start_cylinder),
+		  &(mbr.entries[i].start_head));
+      lba_to_chs (partition->start + partition->len - 1, 
+		  &(mbr.entries[i].end_sector),
+		  &(mbr.entries[i].end_cylinder),
+		  &(mbr.entries[i].end_head));
+      mbr.entries[i].length = grub_cpu_to_le32 (partition->len);
+      grub_free (partition);
+    }
+  for (; i < 4; i++)
+    grub_memset (&(mbr.entries[i]), 0, sizeof (mbr.entries[i]));
+
+  /* The protective partition. */
+  if (first_sector > 0xffffffff)
+    first_sector = 0xffffffff;
+  else
+    first_sector--;
+  mbr.entries[0].flag = 0;
+  mbr.entries[0].type = GRUB_PC_PARTITION_TYPE_GPT_DISK;
+  mbr.entries[0].start = grub_cpu_to_le32 (1);
+  lba_to_chs (1, 
+	      &(mbr.entries[0].start_sector),
+	      &(mbr.entries[0].start_cylinder),
+	      &(mbr.entries[0].start_head));
+  lba_to_chs (first_sector, 
+	      &(mbr.entries[0].end_sector),
+	      &(mbr.entries[0].end_cylinder),
+	      &(mbr.entries[0].end_head));
+  mbr.entries[0].length = grub_cpu_to_le32 (first_sector);
+
+  mbr.signature = grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE);
+
+  if (grub_disk_write (dev->disk, 0, 0, sizeof (mbr), (char *) &mbr))
+    {
+      grub_device_close (dev);
+      return grub_errno;
+    }
+
+  grub_printf ("New MBR is written to '%s'\n", args[0]);
+
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_command_t cmd;
+
+GRUB_MOD_INIT(gptsync)
+{
+  (void) mod;			/* To stop warning. */
+  cmd = grub_register_command ("gptsync", grub_cmd_gptsync, 
+			       "gptsync DEVICE [PARTITION[+/-[TYPE]]] ...", 
+			       "Fill hybrid MBR of GPT drive DEVICE. "
+			       "specified partitions will be a part "
+			       "of hybrid mbr. Up to 3 partitions are "
+			       "allowed. TYPE is an MBR type. "
+			       "+ means that partition is active. "
+			       "Only one partition can be active");
+}
+
+GRUB_MOD_FINI(gptsync)
+{
+  grub_unregister_command (cmd);
+}
diff --git a/conf/common.rmk b/conf/common.rmk
index 0e63da6..c77dce9 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -343,7 +343,12 @@ pkglib_MODULES += minicmd.mod extcmd.mod hello.mod handler.mod	\
 	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
 	terminfo.mod test.mod blocklist.mod hexdump.mod		\
 	read.mod sleep.mod loadenv.mod crc.mod parttool.mod	\
-	pcpart.mod memrw.mod boot.mod
+	pcpart.mod memrw.mod boot.mod gptsync.mod
+
+# For gptsync.mod.
+gptsync_mod_SOURCES = commands/gptsync.c
+gptsync_mod_CFLAGS = $(COMMON_CFLAGS)
+gptsync_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 # For boot.mod.
 boot_mod_SOURCES = commands/boot.c
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index f7cb58d..f899f2c 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -59,6 +59,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	commands/configfile.c commands/echo.c commands/help.c		\
 	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c commands/hexdump.c	\
+	commands/gptsync.c						\
 	lib/hexdump.c commands/i386/cpuid.c				\
 	disk/host.c disk/loopback.c					\
 	\
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index cb41cce..fb50c66 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -59,7 +59,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c commands/hexdump.c	\
 	lib/hexdump.c commands/halt.c commands/reboot.c			\
-	commands/i386/cpuid.c						\
+	commands/gptsync.c commands/i386/cpuid.c			\
 	disk/host.c disk/loopback.c					\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 265b250..ab06d59 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -123,7 +123,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c	\
 	commands/handler.c commands/ls.c commands/test.c 		\
 	commands/search.c commands/blocklist.c commands/hexdump.c	\
 	lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c		\
-	commands/i386/cpuid.c						\
+	commands/gptsync.c commands/i386/cpuid.c			\
 	disk/host.c disk/loopback.c disk/scsi.c				\
 	fs/fshelp.c 	\
 	\
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index d8d35d5..9d0c137 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -43,7 +43,8 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c 	\
 	commands/configfile.c commands/help.c				\
 	commands/search.c commands/handler.c commands/test.c 		\
 	commands/ls.c commands/blocklist.c commands/hexdump.c		\
-	lib/hexdump.c commands/halt.c commands/reboot.c			\
+	lib/hexdump.c commands/halt.c commands/reboot.c 		\
+	commands/gptsync.c 			\
 	disk/loopback.c							\
 	\
 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c			\
diff --git a/include/grub/pc_partition.h b/include/grub/pc_partition.h
index 6a815c3..67c312e 100644
--- a/include/grub/pc_partition.h
+++ b/include/grub/pc_partition.h
@@ -35,6 +35,7 @@
 #define GRUB_PC_PARTITION_TYPE_FAT16_LT32M	4
 #define GRUB_PC_PARTITION_TYPE_EXTENDED		5
 #define GRUB_PC_PARTITION_TYPE_FAT16_GT32M	6
+#define GRUB_PC_PARTITION_TYPE_NTFS	        7
 #define GRUB_PC_PARTITION_TYPE_FAT32		0xb
 #define GRUB_PC_PARTITION_TYPE_FAT32_LBA	0xc
 #define GRUB_PC_PARTITION_TYPE_FAT16_LBA	0xe
@@ -48,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_HFS		0xaf
 #define GRUB_PC_PARTITION_TYPE_GPT_DISK		0xee
 #define GRUB_PC_PARTITION_TYPE_LINUX_RAID	0xfd
 
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to