diff --git a/ChangeLog b/ChangeLog index cf0919780..5374621d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2008-02-19 Robert Millan + + * partmap/gpt.c: Include `'. + (grub_gpt_partition_type_empty): Redefine with macro from + `'. + (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_type_bios_boot): New const variable, defined + with macro from `'. + + (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 * DISTLIST: Replace `commands/ieee1275/halt.c' and diff --git a/partmap/gpt.c b/partmap/gpt.c index 0f38c7762..6bc87551d 100644 --- a/partmap/gpt.c +++ b/partmap/gpt.c @@ -1,7 +1,7 @@ /* gpt.c - Read GUID Partition Tables (GPT). */ /* * 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 * it under the terms of the GNU General Public License as published by @@ -23,41 +23,14 @@ #include #include #include - -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)); +#include static grub_uint8_t grub_gpt_magic[8] = { 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; @@ -114,7 +87,7 @@ gpt_partition_map_iterate (grub_disk_t disk, sizeof (entry), (char *) &entry)) 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))) { /* 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.index = partno; part.partmap = &grub_gpt_partition_map; + part.data = &entry; grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", partno, part.start, part.len); diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index 647d46e41..8fbe3e710 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -1,7 +1,7 @@ /* grub-setup.c - make GRUB usable */ /* * 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 * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,8 @@ #include #include +static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; + #include #include @@ -106,7 +109,8 @@ setup (const char *prefix, const char *dir, grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; grub_file_t file; 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; 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, unsigned length); - auto int find_first_partition_start (grub_disk_t disk, - const grub_partition_t p); - - int find_first_partition_start (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) + auto int find_usable_region (grub_disk_t disk, + const grub_partition_t p); + int find_usable_region (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) { if (! strcmp (p->partmap->name, "pc_partition_map")) { 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) && ! grub_pc_partition_is_bsd (pcdata->dos_type) - && first_start > p->start) - first_start = p->start; + && embed_region.end > p->start) + embed_region.end = p->start; } else - /* In other partition maps, the region after MBR and before first - partition is not reserved (on GPT, it contains the primary header). */ - first_start = 0; + { + struct grub_gpt_partentry *gptdata = p->data; + + /* 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; } @@ -262,15 +278,15 @@ setup (const char *prefix, const char *dir, try to embed the core image into after the MBR. */ 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 ((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. */ - 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->segment = grub_cpu_to_le16 (GRUB_BOOT_MACHINE_KERNEL_SEG @@ -316,13 +332,13 @@ setup (const char *prefix, const char *dir, strcpy (install_prefix, prefix); /* 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); /* The boot image and the core image are on the same drive, so there is no need to specify the boot drive explicitly. */ *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, it is necessary to embed the root drive explicitly. */