2009-05-09 Vladimir Serbinenko <phcoder@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
This commit is contained in:
parent
b4ba690abd
commit
2eac4c1611
8 changed files with 285 additions and 4 deletions
17
ChangeLog
17
ChangeLog
|
@ -1,3 +1,20 @@
|
|||
2009-05-09 Vladimir Serbinenko <phcoder@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-05-09 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Fixed grub-emu
|
||||
|
|
255
commands/gptsync.c
Normal file
255
commands/gptsync.c
Normal file
|
@ -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);
|
||||
}
|
|
@ -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 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
|
||||
|
|
|
@ -61,6 +61,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 \
|
||||
\
|
||||
|
|
|
@ -61,7 +61,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 \
|
||||
|
|
|
@ -125,7 +125,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 \
|
||||
\
|
||||
|
|
|
@ -44,7 +44,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 \
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue