Move embedding routines to partmap sources files.
* grub-core/partmap/gpt.c (grub_gpt_partition_type_bios_boot) [GRUB_UTIL]: New variable. (gpt_partition_map_iterate): Set part.parent. (gpt_partition_map_embed) [GRUB_UTIL]: New function. (grub_gpt_partition_map) [GRUB_UTIL]: Set .embed. * grub-core/partmap/msdos.c (pc_partition_map_embed) [GRUB_UTIL]: New function. (grub_msdos_partition_map) [GRUB_UTIL]: Set .embed. * include/grub/partition.h (grub_embed_type_t) [GRUB_UTIL]: New type. (grub_partition_map) [GRUB_UTIL]: New field embed. * util/grub-setup.c (grub_gpt_partition_type_bios_boot): Removed. (setup): Use ->embed.
This commit is contained in:
parent
e9fc4da271
commit
e50fca4a4c
5 changed files with 295 additions and 112 deletions
|
@ -133,12 +133,128 @@ pc_partition_map_iterate (grub_disk_t disk,
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
static grub_err_t
|
||||
pc_partition_map_embed (struct grub_disk *disk, unsigned int nsectors,
|
||||
grub_embed_type_t embed_type,
|
||||
grub_disk_addr_t *sectors)
|
||||
{
|
||||
grub_disk_addr_t end = ~0ULL;
|
||||
struct grub_msdos_partition_mbr mbr;
|
||||
int labeln = 0;
|
||||
/* Any value different than `p.offset' will satisfy the check during
|
||||
first loop. */
|
||||
grub_disk_addr_t lastaddr = 1;
|
||||
grub_disk_addr_t ext_offset = 0;
|
||||
grub_disk_addr_t offset = 0;
|
||||
|
||||
if (embed_type != GRUB_EMBED_PCBIOS)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"PC-style partitions curently support "
|
||||
"only PC-BIOS embedding");
|
||||
|
||||
if (disk->partition)
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
"Embedding on MSDOS subpartition isn't supported");
|
||||
|
||||
while (1)
|
||||
{
|
||||
int i;
|
||||
struct grub_msdos_partition_entry *e;
|
||||
grub_err_t err;
|
||||
|
||||
/* Read the MBR. */
|
||||
err = grub_disk_read (disk, offset, 0, sizeof (mbr), &mbr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* This is our loop-detection algorithm. It works the following way:
|
||||
It saves last position which was a power of two. Then it compares the
|
||||
saved value with a current one. This way it's guaranteed that the loop
|
||||
will be broken by at most third walk.
|
||||
*/
|
||||
if (labeln && lastaddr == offset)
|
||||
return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected");
|
||||
|
||||
labeln++;
|
||||
if ((labeln & (labeln - 1)) == 0)
|
||||
lastaddr = offset;
|
||||
|
||||
/* Check if it is valid. */
|
||||
if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
|
||||
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
if (mbr.entries[i].flag & 0x7f)
|
||||
return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag");
|
||||
|
||||
/* Analyze DOS partitions. */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
e = mbr.entries + i;
|
||||
|
||||
if (!grub_msdos_partition_is_empty (e->type)
|
||||
&& end > offset + grub_le_to_cpu32 (e->start))
|
||||
end = offset + grub_le_to_cpu32 (e->start);
|
||||
|
||||
/* If this is a GPT partition, this MBR is just a dummy. */
|
||||
if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0)
|
||||
return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr");
|
||||
}
|
||||
|
||||
/* Find an extended partition. */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
e = mbr.entries + i;
|
||||
|
||||
if (grub_msdos_partition_is_extended (e->type))
|
||||
{
|
||||
offset = ext_offset + grub_le_to_cpu32 (e->start);
|
||||
if (! ext_offset)
|
||||
ext_offset = offset;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no extended partition, the end. */
|
||||
if (i == 4)
|
||||
break;
|
||||
}
|
||||
|
||||
if (end >= nsectors + 1)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nsectors; i++)
|
||||
sectors[i] = 1 + i;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (end <= 1)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND,
|
||||
"This msdos-style partition label has no "
|
||||
"post-MBR gap; embedding won't be possible!");
|
||||
|
||||
if (nsectors > 62)
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
"Your core.img is unusually large. "
|
||||
"It won't fit in the embedding area.");
|
||||
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
"Your embedding area is unusually small. "
|
||||
"core.img won't fit in it.");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Partition map type. */
|
||||
static struct grub_partition_map grub_msdos_partition_map =
|
||||
{
|
||||
.name = "msdos",
|
||||
.iterate = pc_partition_map_iterate,
|
||||
#ifdef GRUB_UTIL
|
||||
.embed = pc_partition_map_embed
|
||||
#endif
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(part_msdos)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue