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