[2201] 2009-05-09 Vladimir Serbinenko <[email protected]>

Vladimir Serbinenko <[email protected]>
Newsgroups gmane.comp.boot-loaders.grub.cvs
Message-ID <[email protected]>
Revision: 2201
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=2201
Author:   phcoder
Date:     2009-05-09 11:04:08 +0000 (Sat, 09 May 2009)
Log Message:
-----------
2009-05-09  Vladimir Serbinenko <[email protected]>

	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

Modified Paths:
--------------
    trunk/grub2/ChangeLog
    trunk/grub2/conf/common.rmk
    trunk/grub2/conf/i386-coreboot.rmk
    trunk/grub2/conf/i386-ieee1275.rmk
    trunk/grub2/conf/i386-pc.rmk
    trunk/grub2/conf/powerpc-ieee1275.rmk
    trunk/grub2/include/grub/pc_partition.h

Added Paths:
-----------
    trunk/grub2/commands/gptsync.c

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog	2009-05-09 10:58:43 UTC (rev 2200)
+++ trunk/grub2/ChangeLog	2009-05-09 11:04:08 UTC (rev 2201)
@@ -1,3 +1,20 @@
+2009-05-09  Vladimir Serbinenko <[email protected]>
+
+	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-05-09  Vladimir Serbinenko  <[email protected]>
 
 	Fixed grub-emu

Added: trunk/grub2/commands/gptsync.c
===================================================================
--- trunk/grub2/commands/gptsync.c	                        (rev 0)
+++ trunk/grub2/commands/gptsync.c	2009-05-09 11:04:08 UTC (rev 2201)
@@ -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])] = ')';
+    }
+  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);
+}

Modified: trunk/grub2/conf/common.rmk
===================================================================
--- trunk/grub2/conf/common.rmk	2009-05-09 10:58:43 UTC (rev 2200)
+++ trunk/grub2/conf/common.rmk	2009-05-09 11:04:08 UTC (rev 2201)
@@ -343,8 +343,13 @@
 	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 normal.mod sh.mod
+	pcpart.mod memrw.mod boot.mod normal.mod sh.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
 boot_mod_CFLAGS = $(COMMON_CFLAGS)

Modified: trunk/grub2/conf/i386-coreboot.rmk
===================================================================
--- trunk/grub2/conf/i386-coreboot.rmk	2009-05-09 10:58:43 UTC (rev 2200)
+++ trunk/grub2/conf/i386-coreboot.rmk	2009-05-09 11:04:08 UTC (rev 2201)
@@ -61,6 +61,7 @@
 	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					\
 	\

Modified: trunk/grub2/conf/i386-ieee1275.rmk
===================================================================
--- trunk/grub2/conf/i386-ieee1275.rmk	2009-05-09 10:58:43 UTC (rev 2200)
+++ trunk/grub2/conf/i386-ieee1275.rmk	2009-05-09 11:04:08 UTC (rev 2201)
@@ -61,7 +61,7 @@
 	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			\

Modified: trunk/grub2/conf/i386-pc.rmk
===================================================================
--- trunk/grub2/conf/i386-pc.rmk	2009-05-09 10:58:43 UTC (rev 2200)
+++ trunk/grub2/conf/i386-pc.rmk	2009-05-09 11:04:08 UTC (rev 2201)
@@ -125,7 +125,7 @@
 	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 	\
 	\

Modified: trunk/grub2/conf/powerpc-ieee1275.rmk
===================================================================
--- trunk/grub2/conf/powerpc-ieee1275.rmk	2009-05-09 10:58:43 UTC (rev 2200)
+++ trunk/grub2/conf/powerpc-ieee1275.rmk	2009-05-09 11:04:08 UTC (rev 2201)
@@ -44,7 +44,8 @@
 	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			\

Modified: trunk/grub2/include/grub/pc_partition.h
===================================================================
--- trunk/grub2/include/grub/pc_partition.h	2009-05-09 10:58:43 UTC (rev 2200)
+++ trunk/grub2/include/grub/pc_partition.h	2009-05-09 11:04:08 UTC (rev 2201)
@@ -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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.