2008-02-19 Robert Millan <rmh@aybabtu.com>

* partmap/gpt.c: Include `<grub/gpt_partition.h>'.
        (grub_gpt_partition_type_empty): Redefine with macro from
        `<grub/gpt_partition.h>'.
        (gpt_partition_map_iterate): Adjust partition type comparison.

        Export `entry' as partmap-specific `part.data' struct.
        (grub_gpt_header, grub_gpt_partentry): Move from here ...

        * include/grub/gpt_partition.h (grub_gpt_header)
        (grub_gpt_partentry): ... to here (new file).

        * util/i386/pc/grub-setup.c: Include `<grub/gpt_partition.h>'.

        (grub_gpt_partition_type_bios_boot): New const variable, defined
        with macro from `<grub/gpt_partition.h>'.

        (setup): Replace `first_start' with `embed_region', which keeps
        track of the embed region (and is partmap-agnostic).

        Replace find_first_partition_start() with find_usable_region(),
        which finds a usable region for embedding using partmap-specific
        knowledge (supports PC/MSDOS and GPT).

        Fix all assumptions that the embed region start at sector 1, using
        `embed_region.start' from now on.  Similarly, use `embed_region.end'
        rather than `first_start' to calculate available size.

        In grub_util_info() message, replace "into after the MBR" with an
        indication of the specific sector our embed region starts at.
This commit is contained in:
robertmh 2008-02-19 14:00:11 +00:00
parent 66cb40f6c1
commit b93bdb0f6d
3 changed files with 72 additions and 50 deletions

View file

@ -1,3 +1,35 @@
2008-02-19 Robert Millan <rmh@aybabtu.com>
* partmap/gpt.c: Include `<grub/gpt_partition.h>'.
(grub_gpt_partition_type_empty): Redefine with macro from
`<grub/gpt_partition.h>'.
(gpt_partition_map_iterate): Adjust partition type comparison.
Export `entry' as partmap-specific `part.data' struct.
(grub_gpt_header, grub_gpt_partentry): Move from here ...
* include/grub/gpt_partition.h (grub_gpt_header)
(grub_gpt_partentry): ... to here (new file).
* util/i386/pc/grub-setup.c: Include `<grub/gpt_partition.h>'.
(grub_gpt_partition_type_bios_boot): New const variable, defined
with macro from `<grub/gpt_partition.h>'.
(setup): Replace `first_start' with `embed_region', which keeps
track of the embed region (and is partmap-agnostic).
Replace find_first_partition_start() with find_usable_region(),
which finds a usable region for embedding using partmap-specific
knowledge (supports PC/MSDOS and GPT).
Fix all assumptions that the embed region start at sector 1, using
`embed_region.start' from now on. Similarly, use `embed_region.end'
rather than `first_start' to calculate available size.
In grub_util_info() message, replace "into after the MBR" with an
indication of the specific sector our embed region starts at.
2008-02-19 Robert Millan <rmh@aybabtu.com> 2008-02-19 Robert Millan <rmh@aybabtu.com>
* DISTLIST: Replace `commands/ieee1275/halt.c' and * DISTLIST: Replace `commands/ieee1275/halt.c' and

View file

@ -1,7 +1,7 @@
/* gpt.c - Read GUID Partition Tables (GPT). */ /* gpt.c - Read GUID Partition Tables (GPT). */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2005,2006,2007 Free Software Foundation, Inc. * Copyright (C) 2002,2005,2006,2007,2008 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -23,41 +23,14 @@
#include <grub/partition.h> #include <grub/partition.h>
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/pc_partition.h> #include <grub/pc_partition.h>
#include <grub/gpt_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] = static grub_uint8_t grub_gpt_magic[8] =
{ {
45, 46, 49, 20, 50, 41, 52, 54 45, 46, 49, 20, 50, 41, 52, 54
}; };
static grub_uint8_t grub_gpt_partition_type_empty[16] = { 0 }; static const grub_gpt_part_type_t grub_gpt_partition_type_empty = GRUB_GPT_PARTITION_TYPE_EMPTY;
static struct grub_partition_map grub_gpt_partition_map; static struct grub_partition_map grub_gpt_partition_map;
@ -114,7 +87,7 @@ gpt_partition_map_iterate (grub_disk_t disk,
sizeof (entry), (char *) &entry)) sizeof (entry), (char *) &entry))
return grub_errno; return grub_errno;
if (grub_memcmp (grub_gpt_partition_type_empty, entry.type, if (grub_memcmp (&grub_gpt_partition_type_empty, &entry.type,
sizeof (grub_gpt_partition_type_empty))) sizeof (grub_gpt_partition_type_empty)))
{ {
/* Calculate the first block and the size of the partition. */ /* Calculate the first block and the size of the partition. */
@ -124,6 +97,7 @@ gpt_partition_map_iterate (grub_disk_t disk,
part.offset = entries; part.offset = entries;
part.index = partno; part.index = partno;
part.partmap = &grub_gpt_partition_map; part.partmap = &grub_gpt_partition_map;
part.data = &entry;
grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n",
partno, part.start, part.len); partno, part.start, part.len);

View file

@ -1,7 +1,7 @@
/* grub-setup.c - make GRUB usable */ /* grub-setup.c - make GRUB usable */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -26,6 +26,7 @@
#include <grub/fs.h> #include <grub/fs.h>
#include <grub/partition.h> #include <grub/partition.h>
#include <grub/pc_partition.h> #include <grub/pc_partition.h>
#include <grub/gpt_partition.h>
#include <grub/env.h> #include <grub/env.h>
#include <grub/util/biosdisk.h> #include <grub/util/biosdisk.h>
#include <grub/machine/boot.h> #include <grub/machine/boot.h>
@ -34,6 +35,8 @@
#include <grub/util/raid.h> #include <grub/util/raid.h>
#include <grub/util/lvm.h> #include <grub/util/lvm.h>
static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
#include <grub_setup_init.h> #include <grub_setup_init.h>
#include <stdio.h> #include <stdio.h>
@ -106,7 +109,8 @@ setup (const char *prefix, const char *dir,
grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE;
grub_file_t file; grub_file_t file;
FILE *fp; FILE *fp;
unsigned long first_start = ~0UL; struct { grub_uint64_t start; grub_uint64_t end; } embed_region;
embed_region.start = embed_region.end = ~0UL;
int able_to_embed = 1; int able_to_embed = 1;
auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset, auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset,
@ -114,25 +118,37 @@ setup (const char *prefix, const char *dir,
auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset, auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset,
unsigned length); unsigned length);
auto int find_first_partition_start (grub_disk_t disk, auto int find_usable_region (grub_disk_t disk,
const grub_partition_t p); const grub_partition_t p);
int find_usable_region (grub_disk_t disk __attribute__ ((unused)),
int find_first_partition_start (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p) const grub_partition_t p)
{ {
if (! strcmp (p->partmap->name, "pc_partition_map")) if (! strcmp (p->partmap->name, "pc_partition_map"))
{ {
struct grub_pc_partition *pcdata = p->data; struct grub_pc_partition *pcdata = p->data;
/* There's always an embed region, and it starts right after the MBR. */
embed_region.start = 1;
/* For its end offset, include as many dummy partitions as we can. */
if (! grub_pc_partition_is_empty (pcdata->dos_type) if (! grub_pc_partition_is_empty (pcdata->dos_type)
&& ! grub_pc_partition_is_bsd (pcdata->dos_type) && ! grub_pc_partition_is_bsd (pcdata->dos_type)
&& first_start > p->start) && embed_region.end > p->start)
first_start = p->start; embed_region.end = p->start;
} }
else else
/* In other partition maps, the region after MBR and before first {
partition is not reserved (on GPT, it contains the primary header). */ struct grub_gpt_partentry *gptdata = p->data;
first_start = 0;
/* If there's an embed region, it is in a dedicated partition. */
if (! memcmp (&gptdata->type, &grub_gpt_partition_type_bios_boot, 16))
{
embed_region.start = p->start;
embed_region.end = p->start + p->len;
return 1;
}
}
return 0; return 0;
} }
@ -262,15 +278,15 @@ setup (const char *prefix, const char *dir,
try to embed the core image into after the MBR. */ try to embed the core image into after the MBR. */
if (dest_dev->disk->has_partitions && ! dest_dev->disk->partition) if (dest_dev->disk->has_partitions && ! dest_dev->disk->partition)
{ {
grub_partition_iterate (dest_dev->disk, find_first_partition_start); grub_partition_iterate (dest_dev->disk, find_usable_region);
/* If there is enough space... */ /* If there is enough space... */
if ((unsigned long) core_sectors + 1 <= first_start) if ((unsigned long) core_sectors <= embed_region.end - embed_region.start)
{ {
grub_util_info ("will embed the core image into after the MBR"); grub_util_info ("will embed the core image at sector 0x%llx", embed_region.start);
/* The first blocklist contains the whole sectors. */ /* The first blocklist contains the whole sectors. */
first_block->start = grub_cpu_to_le64 (2); first_block->start = grub_cpu_to_le64 (embed_region.start + 1);
first_block->len = grub_cpu_to_le16 (core_sectors - 1); first_block->len = grub_cpu_to_le16 (core_sectors - 1);
first_block->segment first_block->segment
= grub_cpu_to_le16 (GRUB_BOOT_MACHINE_KERNEL_SEG = grub_cpu_to_le16 (GRUB_BOOT_MACHINE_KERNEL_SEG
@ -316,13 +332,13 @@ setup (const char *prefix, const char *dir,
strcpy (install_prefix, prefix); strcpy (install_prefix, prefix);
/* Write the core image onto the disk. */ /* Write the core image onto the disk. */
if (grub_disk_write (dest_dev->disk, 1, 0, core_size, core_img)) if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, core_img))
grub_util_error ("%s", grub_errmsg); grub_util_error ("%s", grub_errmsg);
/* The boot image and the core image are on the same drive, /* The boot image and the core image are on the same drive,
so there is no need to specify the boot drive explicitly. */ so there is no need to specify the boot drive explicitly. */
*boot_drive = 0xff; *boot_drive = 0xff;
*kernel_sector = grub_cpu_to_le64 (1); *kernel_sector = grub_cpu_to_le64 (embed_region.start);
/* If the root device is different from the destination device, /* If the root device is different from the destination device,
it is necessary to embed the root drive explicitly. */ it is necessary to embed the root drive explicitly. */