sparc64: Add bios boot partition support
Add BIOS Boot Partition support for sparc64 platforms. This will work a little different than x86. With GPT, both the OBP "load" and "boot" commands are partition aware and neither command can see the partition table. Therefore the entire boot-loader is stored within the BIOS Boot Partition and nothing is stored within the bootstrap code area of MBR. To use it, the end user will issue the boot command with the path pointing to the BIOS Boot Partition. For example with the disk below: Model: Unknown (unknown) Disk /dev/nvme1n1: 1600GB Sector size (logical/physical): 512B/512B Partition Table: gpt Number Start End Size File system Name Flags 1 1049kB 1075MB 1074MB ext3 2 1075MB 1076MB 1049kB bios_grub 3 1076MB 1600GB 1599GB lvm To boot grub2 from OBP, you would use: boot /pci@302/pci@1/pci@0/pci@13/nvme@0/disk@1:b Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
parent
3434ddec0e
commit
9a0703b559
1 changed files with 72 additions and 9 deletions
81
util/setup.c
81
util/setup.c
|
@ -205,7 +205,6 @@ save_blocklists (grub_disk_addr_t sector, unsigned offset, unsigned length,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GRUB_SETUP_BIOS
|
|
||||||
/* Context for setup/identify_partmap. */
|
/* Context for setup/identify_partmap. */
|
||||||
struct identify_partmap_ctx
|
struct identify_partmap_ctx
|
||||||
{
|
{
|
||||||
|
@ -241,7 +240,6 @@ identify_partmap (grub_disk_t disk __attribute__ ((unused)),
|
||||||
ctx->multiple_partmaps = 1;
|
ctx->multiple_partmaps = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef GRUB_SETUP_BIOS
|
#ifdef GRUB_SETUP_BIOS
|
||||||
#define SETUP grub_util_bios_setup
|
#define SETUP grub_util_bios_setup
|
||||||
|
@ -262,9 +260,7 @@ SETUP (const char *dir,
|
||||||
char *boot_img, *core_img, *boot_path;
|
char *boot_img, *core_img, *boot_path;
|
||||||
char *root = 0;
|
char *root = 0;
|
||||||
size_t boot_size, core_size;
|
size_t boot_size, core_size;
|
||||||
#ifdef GRUB_SETUP_BIOS
|
|
||||||
grub_uint16_t core_sectors;
|
grub_uint16_t core_sectors;
|
||||||
#endif
|
|
||||||
grub_device_t root_dev = 0, dest_dev, core_dev;
|
grub_device_t root_dev = 0, dest_dev, core_dev;
|
||||||
grub_util_fd_t fp;
|
grub_util_fd_t fp;
|
||||||
struct blocklists bl;
|
struct blocklists bl;
|
||||||
|
@ -288,10 +284,8 @@ SETUP (const char *dir,
|
||||||
|
|
||||||
core_path = grub_util_get_path (dir, core_file);
|
core_path = grub_util_get_path (dir, core_file);
|
||||||
core_size = grub_util_get_image_size (core_path);
|
core_size = grub_util_get_image_size (core_path);
|
||||||
#ifdef GRUB_SETUP_BIOS
|
|
||||||
core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1)
|
core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1)
|
||||||
>> GRUB_DISK_SECTOR_BITS);
|
>> GRUB_DISK_SECTOR_BITS);
|
||||||
#endif
|
|
||||||
if (core_size < GRUB_DISK_SECTOR_SIZE)
|
if (core_size < GRUB_DISK_SECTOR_SIZE)
|
||||||
grub_util_error (_("the size of `%s' is too small"), core_path);
|
grub_util_error (_("the size of `%s' is too small"), core_path);
|
||||||
#ifdef GRUB_SETUP_BIOS
|
#ifdef GRUB_SETUP_BIOS
|
||||||
|
@ -372,8 +366,8 @@ SETUP (const char *dir,
|
||||||
if (grub_env_set ("root", root) != GRUB_ERR_NONE)
|
if (grub_env_set ("root", root) != GRUB_ERR_NONE)
|
||||||
grub_util_error ("%s", grub_errmsg);
|
grub_util_error ("%s", grub_errmsg);
|
||||||
|
|
||||||
#ifdef GRUB_SETUP_BIOS
|
|
||||||
{
|
{
|
||||||
|
#ifdef GRUB_SETUP_BIOS
|
||||||
char *tmp_img;
|
char *tmp_img;
|
||||||
grub_uint8_t *boot_drive_check;
|
grub_uint8_t *boot_drive_check;
|
||||||
|
|
||||||
|
@ -398,6 +392,7 @@ SETUP (const char *dir,
|
||||||
boot_drive_check[0] = 0x90;
|
boot_drive_check[0] = 0x90;
|
||||||
boot_drive_check[1] = 0x90;
|
boot_drive_check[1] = 0x90;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct identify_partmap_ctx ctx = {
|
struct identify_partmap_ctx ctx = {
|
||||||
.dest_partmap = NULL,
|
.dest_partmap = NULL,
|
||||||
|
@ -413,6 +408,7 @@ SETUP (const char *dir,
|
||||||
|
|
||||||
grub_partition_iterate (dest_dev->disk, identify_partmap, &ctx);
|
grub_partition_iterate (dest_dev->disk, identify_partmap, &ctx);
|
||||||
|
|
||||||
|
#ifdef GRUB_SETUP_BIOS
|
||||||
/* Copy the partition table. */
|
/* Copy the partition table. */
|
||||||
if (ctx.dest_partmap ||
|
if (ctx.dest_partmap ||
|
||||||
(!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk)))
|
(!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk)))
|
||||||
|
@ -421,6 +417,7 @@ SETUP (const char *dir,
|
||||||
GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC);
|
GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC);
|
||||||
|
|
||||||
free (tmp_img);
|
free (tmp_img);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ctx.container
|
if (ctx.container
|
||||||
&& grub_strcmp (ctx.container->partmap->name, "msdos") == 0
|
&& grub_strcmp (ctx.container->partmap->name, "msdos") == 0
|
||||||
|
@ -508,10 +505,22 @@ SETUP (const char *dir,
|
||||||
else
|
else
|
||||||
maxsec = core_sectors;
|
maxsec = core_sectors;
|
||||||
|
|
||||||
|
#ifdef GRUB_SETUP_BIOS
|
||||||
if (maxsec > ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR)
|
if (maxsec > ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR)
|
||||||
>> GRUB_DISK_SECTOR_BITS))
|
>> GRUB_DISK_SECTOR_BITS))
|
||||||
maxsec = ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR)
|
maxsec = ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR)
|
||||||
>> GRUB_DISK_SECTOR_BITS);
|
>> GRUB_DISK_SECTOR_BITS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GRUB_SETUP_SPARC64
|
||||||
|
/*
|
||||||
|
* On SPARC we need two extra. One is because we are combining the
|
||||||
|
* core.img with the boot.img. The other is because the boot sector
|
||||||
|
* starts at 1.
|
||||||
|
*/
|
||||||
|
nsec += 2;
|
||||||
|
maxsec += 2;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (is_ldm)
|
if (is_ldm)
|
||||||
err = grub_util_ldm_embed (dest_dev->disk, &nsec, maxsec,
|
err = grub_util_ldm_embed (dest_dev->disk, &nsec, maxsec,
|
||||||
|
@ -560,9 +569,39 @@ SETUP (const char *dir,
|
||||||
bl.block--;
|
bl.block--;
|
||||||
bl.block->start = 0;
|
bl.block->start = 0;
|
||||||
bl.block->len = 0;
|
bl.block->len = 0;
|
||||||
|
#ifdef GRUB_SETUP_BIOS
|
||||||
bl.block->segment = 0;
|
bl.block->segment = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GRUB_SETUP_SPARC64
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* On SPARC, the block-list entries need to be based off the beginning
|
||||||
|
* of the parition, not the beginning of the disk.
|
||||||
|
*/
|
||||||
|
struct grub_boot_blocklist *block;
|
||||||
|
block = bl.first_block;
|
||||||
|
|
||||||
|
while (block->len)
|
||||||
|
{
|
||||||
|
block->start -= bl.first_sector;
|
||||||
|
block--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reserve space for the boot block since it can not be in the
|
||||||
|
* Parition table on SPARC.
|
||||||
|
*/
|
||||||
|
assert (bl.first_block->len > 2);
|
||||||
|
bl.first_block->start += 2;
|
||||||
|
bl.first_block->len -= 2;
|
||||||
|
write_rootdev (root_dev, boot_img, sectors[BOOT_SECTOR + 1] - bl.first_sector);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GRUB_SETUP_BIOS
|
||||||
write_rootdev (root_dev, boot_img, bl.first_sector);
|
write_rootdev (root_dev, boot_img, bl.first_sector);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Round up to the nearest sector boundary, and zero the extra memory */
|
/* Round up to the nearest sector boundary, and zero the extra memory */
|
||||||
core_img = xrealloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE);
|
core_img = xrealloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE);
|
||||||
|
@ -572,7 +611,7 @@ SETUP (const char *dir,
|
||||||
bl.first_block = (struct grub_boot_blocklist *) (core_img
|
bl.first_block = (struct grub_boot_blocklist *) (core_img
|
||||||
+ GRUB_DISK_SECTOR_SIZE
|
+ GRUB_DISK_SECTOR_SIZE
|
||||||
- sizeof (*bl.block));
|
- sizeof (*bl.block));
|
||||||
|
#if GRUB_SETUP_BIOS
|
||||||
grub_size_t no_rs_length;
|
grub_size_t no_rs_length;
|
||||||
no_rs_length = grub_target_to_host16
|
no_rs_length = grub_target_to_host16
|
||||||
(grub_get_unaligned16 (core_img
|
(grub_get_unaligned16 (core_img
|
||||||
|
@ -603,14 +642,34 @@ SETUP (const char *dir,
|
||||||
grub_disk_write (dest_dev->disk, sectors[i], 0,
|
grub_disk_write (dest_dev->disk, sectors[i], 0,
|
||||||
GRUB_DISK_SECTOR_SIZE,
|
GRUB_DISK_SECTOR_SIZE,
|
||||||
core_img + i * GRUB_DISK_SECTOR_SIZE);
|
core_img + i * GRUB_DISK_SECTOR_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GRUB_SETUP_SPARC64
|
||||||
|
{
|
||||||
|
int isec = BOOT_SECTOR;
|
||||||
|
|
||||||
|
/* Write the boot image onto the disk. */
|
||||||
|
if (grub_disk_write (dest_dev->disk, sectors[isec++], 0,
|
||||||
|
GRUB_DISK_SECTOR_SIZE, boot_img))
|
||||||
|
grub_util_error ("%s", grub_errmsg);
|
||||||
|
|
||||||
|
/* Write the core image onto the disk. */
|
||||||
|
for (i = 0 ; isec < nsec; i++, isec++)
|
||||||
|
{
|
||||||
|
if (grub_disk_write (dest_dev->disk, sectors[isec], 0,
|
||||||
|
GRUB_DISK_SECTOR_SIZE,
|
||||||
|
core_img + i * GRUB_DISK_SECTOR_SIZE))
|
||||||
|
grub_util_error ("%s", grub_errmsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
grub_free (sectors);
|
grub_free (sectors);
|
||||||
|
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
unable_to_embed:
|
unable_to_embed:
|
||||||
#endif
|
|
||||||
|
|
||||||
if (dest_dev->disk->dev->id != root_dev->disk->dev->id)
|
if (dest_dev->disk->dev->id != root_dev->disk->dev->id)
|
||||||
grub_util_error ("%s", _("embedding is not possible, but this is required for "
|
grub_util_error ("%s", _("embedding is not possible, but this is required for "
|
||||||
|
@ -799,6 +858,10 @@ unable_to_embed:
|
||||||
0, GRUB_DISK_SECTOR_SIZE, boot_img))
|
0, GRUB_DISK_SECTOR_SIZE, boot_img))
|
||||||
grub_util_error ("%s", grub_errmsg);
|
grub_util_error ("%s", grub_errmsg);
|
||||||
|
|
||||||
|
#ifdef GRUB_SETUP_SPARC64
|
||||||
|
finish:
|
||||||
|
#endif
|
||||||
|
|
||||||
grub_util_biosdisk_flush (root_dev->disk);
|
grub_util_biosdisk_flush (root_dev->disk);
|
||||||
grub_util_biosdisk_flush (dest_dev->disk);
|
grub_util_biosdisk_flush (dest_dev->disk);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue