From d2ea45514111f866432b8acabdabd1277ee19f98 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 21:07:39 +0200 Subject: [PATCH] * grub-core/partmap/sun.c (sun_partition_map_iterate): Don't needlesly allocate p. --- ChangeLog | 5 + Makefile.util.def | 9 +- grub-core/fs/ext2.c | 19 +- grub-core/partmap/sun.c | 35 +- include/grub/sparc64/ieee1275/boot.h | 9 + util/{i386/pc => }/grub-setup.c | 690 ++++++++++++++++----------- util/sparc64/ieee1275/grub-setup.c | 644 ------------------------- 7 files changed, 450 insertions(+), 961 deletions(-) rename util/{i386/pc => }/grub-setup.c (60%) delete mode 100644 util/sparc64/ieee1275/grub-setup.c diff --git a/ChangeLog b/ChangeLog index f300c84ab..d3e7c31c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-14 Vladimir Serbinenko + + * grub-core/partmap/sun.c (sun_partition_map_iterate): Don't needlesly + allocate p. + 2010-09-14 Vladimir Serbinenko * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Add diff --git a/Makefile.util.def b/Makefile.util.def index 4bbcd2b07..f56eab339 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -232,14 +232,11 @@ program = { name = grub-setup; installdir = sbin; mansection = 8; - i386_pc = util/i386/pc/grub-setup.c; - i386_pc = util/raid.c; - i386_pc = util/lvm.c; + common = util/grub-setup.c; + common = util/raid.c; + common = util/lvm.c; sparc64_ieee1275 = util/ieee1275/ofpath.c; - sparc64_ieee1275 = util/sparc64/ieee1275/grub-setup.c; - sparc64_ieee1275 = util/raid.c; - sparc64_ieee1275 = util/lvm.c; ldadd = libgrub.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL)'; diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c index f2fec828a..dfc75c625 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -728,22 +728,27 @@ grub_ext2_open (struct grub_file *file, const char *name) { struct grub_ext2_data *data; struct grub_fshelp_node *fdiro = 0; + grub_err_t err; grub_dl_ref (my_mod); data = grub_ext2_mount (file->device->disk); if (! data) - goto fail; + { + err = grub_errno; + goto fail; + } - grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_ext2_iterate_dir, - grub_ext2_read_symlink, GRUB_FSHELP_REG); - if (grub_errno) + err = grub_fshelp_find_file (name, &data->diropen, &fdiro, + grub_ext2_iterate_dir, + grub_ext2_read_symlink, GRUB_FSHELP_REG); + if (err) goto fail; if (! fdiro->inode_read) { - grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode); - if (grub_errno) + err = grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode); + if (err) goto fail; } @@ -763,7 +768,7 @@ grub_ext2_open (struct grub_file *file, const char *name) grub_dl_unref (my_mod); - return grub_errno; + return err; } static grub_err_t diff --git a/grub-core/partmap/sun.c b/grub-core/partmap/sun.c index 7a7eaef27..7af95c939 100644 --- a/grub-core/partmap/sun.c +++ b/grub-core/partmap/sun.c @@ -87,36 +87,23 @@ sun_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, const grub_partition_t partition)) { - grub_partition_t p; + struct grub_partition p; struct grub_sun_block block; int partnum; grub_err_t err; - p = (grub_partition_t) grub_zalloc (sizeof (struct grub_partition)); - if (! p) - return grub_errno; - - p->partmap = &grub_sun_partition_map; + p.partmap = &grub_sun_partition_map; err = grub_disk_read (disk, 0, 0, sizeof (struct grub_sun_block), &block); if (err) - { - grub_free (p); - return err; - } + return err; if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) - { - grub_free (p); - return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); - } + return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); if (! grub_sun_is_valid (&block)) - { - grub_free (p); return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); - } - + /* Maybe another error value would be better, because partition table _is_ recognized but invalid. */ for (partnum = 0; partnum < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++) @@ -128,20 +115,18 @@ sun_partition_map_iterate (grub_disk_t disk, continue; desc = &block.partitions[partnum]; - p->start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) + p.start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) * grub_be_to_cpu16 (block.ntrks) * grub_be_to_cpu16 (block.nsect)); - p->len = grub_be_to_cpu32 (desc->num_sectors); - p->number = p->index = partnum; - if (p->len) + p.len = grub_be_to_cpu32 (desc->num_sectors); + p.number = p.index = partnum; + if (p.len) { - if (hook (disk, p)) + if (hook (disk, &p)) partnum = GRUB_PARTMAP_SUN_MAX_PARTS; } } - grub_free (p); - return grub_errno; } diff --git a/include/grub/sparc64/ieee1275/boot.h b/include/grub/sparc64/ieee1275/boot.h index bd0a7bf3c..112d19bc7 100644 --- a/include/grub/sparc64/ieee1275/boot.h +++ b/include/grub/sparc64/ieee1275/boot.h @@ -52,4 +52,13 @@ #define GRUB_BOOT_MACHINE_KERNEL_ADDR 0x4200 +#ifndef ASM_FILE +/* This is the blocklist used in the diskboot image. */ +struct grub_boot_blocklist +{ + grub_uint64_t start; + grub_uint32_t len; +} __attribute__ ((packed)); +#endif + #endif /* ! BOOT_MACHINE_HEADER */ diff --git a/util/i386/pc/grub-setup.c b/util/grub-setup.c similarity index 60% rename from util/i386/pc/grub-setup.c rename to util/grub-setup.c index b9abfb0c6..55d740f09 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/grub-setup.c @@ -36,9 +36,9 @@ #include #include #include -#include - -static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; +#ifdef GRUB_MACHINE_IEEE1275 +#include +#endif #include #include @@ -48,59 +48,312 @@ static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_P #include #include #include +#include #include "progname.h" #define _GNU_SOURCE 1 #include +/* On SPARC this program fills in various fields inside of the 'boot' and 'core' + * image files. + * + * The 'boot' image needs to know the OBP path name of the root + * device. It also needs to know the initial block number of + * 'core' (which is 'diskboot' concatenated with 'kernel' and + * all the modules, this is created by grub-mkimage). This resulting + * 'boot' image is 512 bytes in size and is placed in the second block + * of a partition. + * + * The initial 'diskboot' block acts as a loader for the actual GRUB + * kernel. It contains the loading code and then a block list. + * + * The block list of 'core' starts at the end of the 'diskboot' image + * and works it's way backwards towards the end of the code of 'diskboot'. + * + * We patch up the images with the necessary values and write out the + * result. + */ + +#ifdef GRUB_MACHINE_PCBIOS +static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; +#endif + #define DEFAULT_BOOT_FILE "boot.img" #define DEFAULT_CORE_FILE "core.img" +#ifdef GRUB_MACHINE_SPARC64 +#define grub_target_to_host16(x) grub_be_to_cpu16(x) +#define grub_target_to_host32(x) grub_be_to_cpu32(x) +#define grub_target_to_host64(x) grub_be_to_cpu64(x) +#define grub_host_to_target16(x) grub_cpu_to_be16(x) +#define grub_host_to_target32(x) grub_cpu_to_be32(x) +#define grub_host_to_target64(x) grub_cpu_to_be64(x) +#elif defined (GRUB_MACHINE_PCBIOS) #define grub_target_to_host16(x) grub_le_to_cpu16(x) #define grub_target_to_host32(x) grub_le_to_cpu32(x) #define grub_target_to_host64(x) grub_le_to_cpu64(x) #define grub_host_to_target16(x) grub_cpu_to_le16(x) #define grub_host_to_target32(x) grub_cpu_to_le32(x) #define grub_host_to_target64(x) grub_cpu_to_le64(x) +#else +#error Complete this +#endif + +static void +write_rootdev (char *core_img, grub_device_t root_dev, + char *boot_img, grub_uint64_t first_sector) +{ +#ifdef GRUB_MACHINE_PCBIOS + { + grub_int32_t *install_dos_part, *install_bsd_part; + grub_int32_t dos_part, bsd_part; + grub_uint8_t *boot_drive; + grub_disk_addr_t *kernel_sector; + boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); + kernel_sector = (grub_disk_addr_t *) (boot_img + + GRUB_BOOT_MACHINE_KERNEL_SECTOR); + + + install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); + install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); + + /* If we hardcoded drive as part of prefix, we don't want to + override the current setting. */ + if (*install_dos_part != -2) + { + /* Embed information about the installed location. */ + if (root_dev->disk->partition) + { + if (root_dev->disk->partition->parent) + { + if (root_dev->disk->partition->parent->parent) + grub_util_error ("Installing on doubly nested partitions is " + "not supported"); + dos_part = root_dev->disk->partition->parent->number; + bsd_part = root_dev->disk->partition->number; + } + else + { + dos_part = root_dev->disk->partition->number; + bsd_part = -1; + } + } + else + dos_part = bsd_part = -1; + } + else + { + dos_part = grub_le_to_cpu32 (*install_dos_part); + bsd_part = grub_le_to_cpu32 (*install_bsd_part); + } + + grub_util_info ("dos partition is %d, bsd partition is %d", + dos_part, bsd_part); + + *install_dos_part = grub_cpu_to_le32 (dos_part); + *install_bsd_part = grub_cpu_to_le32 (bsd_part); + + /* FIXME: can this be skipped? */ + *boot_drive = 0xFF; + + *kernel_sector = grub_cpu_to_le64 (first_sector); + } +#endif +#ifdef GRUB_MACHINE_IEEE1275 + { + grub_disk_addr_t *kernel_byte; + kernel_byte = (grub_disk_addr_t *) (boot_img + + GRUB_BOOT_AOUT_HEADER_SIZE + + GRUB_BOOT_MACHINE_KERNEL_BYTE); + *kernel_byte = grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS); + } +#endif +} + +#ifdef GRUB_MACHINE_IEEE1275 +#define BOOT_SECTOR 1 +#else +#define BOOT_SECTOR 0 +#endif static void setup (const char *dir, const char *boot_file, const char *core_file, - const char *root, const char *dest, int must_embed, int force, int fs_probe) + const char *root, const char *dest, int must_embed, int force, + int fs_probe) { char *boot_path, *core_path, *core_path_dev, *core_path_dev_full; char *boot_img, *core_img; size_t boot_size, core_size; grub_uint16_t core_sectors; grub_device_t root_dev, dest_dev; - const char *dest_partmap; - int multiple_partmaps; - grub_uint8_t *boot_drive; - grub_disk_addr_t *kernel_sector; - grub_uint16_t *boot_drive_check; struct grub_boot_blocklist *first_block, *block; - grub_int32_t *install_dos_part, *install_bsd_part; - grub_int32_t dos_part, bsd_part; char *tmp_img; int i; grub_disk_addr_t first_sector; +#ifdef GRUB_MACHINE_PCBIOS grub_uint16_t current_segment = GRUB_BOOT_MACHINE_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4); +#endif grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; grub_file_t file; FILE *fp; struct { grub_uint64_t start; grub_uint64_t end; } embed_region; embed_region.start = embed_region.end = ~0UL; - auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset, - unsigned length); - auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset, - unsigned length); + auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, + unsigned offset, + unsigned length); + auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, + unsigned offset, + unsigned length); - auto int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) + void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, + unsigned offset, + unsigned length) + { + grub_util_info ("the first sector is <%llu,%u,%u>", + sector, offset, length); + + if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the first sector of the core file is not sector-aligned")); + + first_sector = sector; + } + + void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, + unsigned offset, + unsigned length) + { + struct grub_boot_blocklist *prev = block + 1; + + grub_util_info ("saving <%llu,%u,%u>", sector, offset, length); + + if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("non-sector-aligned data is found in the core file")); + + if (block != first_block + && (grub_target_to_host64 (prev->start) + + grub_target_to_host16 (prev->len)) == sector) + prev->len = grub_host_to_target16 (grub_target_to_host16 (prev->len) + 1); + else + { + block->start = grub_host_to_target64 (sector); + block->len = grub_host_to_target16 (1); +#ifdef GRUB_MACHINE_PCBIOS + block->segment = grub_host_to_target16 (current_segment); +#endif + + block--; + if (block->len) + grub_util_error (_("the sectors of the core file are too fragmented")); + } + + last_length = length; +#ifdef GRUB_MACHINE_PCBIOS + current_segment += GRUB_DISK_SECTOR_SIZE >> 4; +#endif + } + + /* Read the boot image by the OS service. */ + boot_path = grub_util_get_path (dir, boot_file); + boot_size = grub_util_get_image_size (boot_path); + if (boot_size != GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is not %u"), + boot_path, GRUB_DISK_SECTOR_SIZE); + boot_img = grub_util_read_image (boot_path); + free (boot_path); + + core_path = grub_util_get_path (dir, core_file); + core_size = grub_util_get_image_size (core_path); + core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) + >> GRUB_DISK_SECTOR_BITS); + if (core_size < GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is too small"), core_path); +#ifdef GRUB_MACHINE_PCBIOS + if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is too large"), core_path); +#endif + + core_img = grub_util_read_image (core_path); + + /* Have FIRST_BLOCK to point to the first blocklist. */ + first_block = (struct grub_boot_blocklist *) (core_img + + GRUB_DISK_SECTOR_SIZE + - sizeof (*block)); + + grub_util_info ("root is `%s', dest is `%s'", root, dest); + + /* Open the root device and the destination device. */ + grub_util_info ("Opening root"); + root_dev = grub_device_open (root); + if (! root_dev) + grub_util_error ("%s", grub_errmsg); + + grub_util_info ("Opening dest"); + dest_dev = grub_device_open (dest); + if (! dest_dev) + grub_util_error ("%s", grub_errmsg); + + grub_util_info ("setting the root device to `%s'", root); + if (grub_env_set ("root", root) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); + +#ifdef GRUB_MACHINE_PCBIOS + /* Read the original sector from the disk. */ + tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE); + if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) + grub_util_error ("%s", grub_errmsg); +#endif + +#ifdef GRUB_MACHINE_PCBIOS + if (dest_dev->disk->partition && fs_probe) + { + grub_fs_t fs; + fs = grub_fs_probe (dest_dev); + if (! fs) + grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), + dest_dev->disk->name); + + if (! fs->reserved_first_sector) + grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " + "reserve space for DOS-style boot. Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), dest_dev->disk->name, fs->name); + } +#endif + +#ifdef GRUB_MACHINE_PCBIOS + { + grub_uint16_t *boot_drive_check; + boot_drive_check = (grub_uint16_t *) (boot_img + + GRUB_BOOT_MACHINE_DRIVE_CHECK); + /* Copy the possible DOS BPB. */ + memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START, + tmp_img + GRUB_BOOT_MACHINE_BPB_START, + GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START); + + /* If DEST_DRIVE is a hard disk, enable the workaround, which is + for buggy BIOSes which don't pass boot drive correctly. Instead, + they pass 0x00 or 0x01 even when booted from 0x80. */ + if (dest_dev->disk->id & 0x80) + /* Replace the jmp (2 bytes) with double nop's. */ + *boot_drive_check = 0x9090; + } +#endif + +#ifdef GRUB_MACHINE_PCBIOS + { + const char *dest_partmap; + int multiple_partmaps; + + auto int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) { /* There's always an embed region, and it starts right after the MBR. */ embed_region.start = 1; @@ -111,10 +364,10 @@ setup (const char *dir, return 0; } - auto int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) + auto int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) { struct grub_gpt_partentry gptdata; @@ -134,176 +387,18 @@ setup (const char *dir, return 0; } - void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset, - unsigned length) - { - grub_util_info ("the first sector is <%llu,%u,%u>", - sector, offset, length); + if (dest_dev->disk->partition) + { + grub_util_warn (_("Attempting to install GRUB to a partition instead of the MBR. This is a BAD idea.")); + goto unable_to_embed; + } - if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the first sector of the core file is not sector-aligned")); - - first_sector = sector; - } - - void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset, - unsigned length) - { - struct grub_boot_blocklist *prev = block + 1; - - grub_util_info ("saving <%llu,%u,%u> with the segment 0x%x", - sector, offset, length, (unsigned) current_segment); - - if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("non-sector-aligned data is found in the core file")); - - if (block != first_block - && (grub_le_to_cpu64 (prev->start) - + grub_le_to_cpu16 (prev->len)) == sector) - prev->len = grub_cpu_to_le16 (grub_le_to_cpu16 (prev->len) + 1); - else - { - block->start = grub_cpu_to_le64 (sector); - block->len = grub_cpu_to_le16 (1); - block->segment = grub_cpu_to_le16 (current_segment); - - block--; - if (block->len) - grub_util_error (_("the sectors of the core file are too fragmented")); - } - - last_length = length; - current_segment += GRUB_DISK_SECTOR_SIZE >> 4; - } - - /* Read the boot image by the OS service. */ - boot_path = grub_util_get_path (dir, boot_file); - boot_size = grub_util_get_image_size (boot_path); - if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is not %u"), - boot_path, GRUB_DISK_SECTOR_SIZE); - boot_img = grub_util_read_image (boot_path); - free (boot_path); - - /* Set the addresses of variables in the boot image. */ - boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); - kernel_sector = (grub_disk_addr_t *) (boot_img - + GRUB_BOOT_MACHINE_KERNEL_SECTOR); - boot_drive_check = (grub_uint16_t *) (boot_img - + GRUB_BOOT_MACHINE_DRIVE_CHECK); - - core_path = grub_util_get_path (dir, core_file); - core_size = grub_util_get_image_size (core_path); - core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS); - if (core_size < GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is too small"), core_path); - else if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is too large"), core_path); - - core_img = grub_util_read_image (core_path); - - /* Have FIRST_BLOCK to point to the first blocklist. */ - first_block = (struct grub_boot_blocklist *) (core_img - + GRUB_DISK_SECTOR_SIZE - - sizeof (*block)); - - install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); - install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); - - /* Open the root device and the destination device. */ - root_dev = grub_device_open (root); - if (! root_dev) - grub_util_error ("%s", grub_errmsg); - - dest_dev = grub_device_open (dest); - if (! dest_dev) - grub_util_error ("%s", grub_errmsg); - - grub_util_info ("setting the root device to `%s'", root); - if (grub_env_set ("root", root) != GRUB_ERR_NONE) - grub_util_error ("%s", grub_errmsg); - - /* Read the original sector from the disk. */ - tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE); - if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) - grub_util_error ("%s", grub_errmsg); - - if (dest_dev->disk->partition && fs_probe) - { - grub_fs_t fs; - fs = grub_fs_probe (dest_dev); - if (! fs) - grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), - dest_dev->disk->name); - - if (! fs->reserved_first_sector) - grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " - "reserve space for DOS-style boot. Installing GRUB there could " - "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " - "by grub-setup (--skip-fs-probe disables this " - "check, use at your own risk)"), dest_dev->disk->name, fs->name); - } - - /* Copy the possible DOS BPB. */ - memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START, - tmp_img + GRUB_BOOT_MACHINE_BPB_START, - GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START); - - /* If DEST_DRIVE is a hard disk, enable the workaround, which is - for buggy BIOSes which don't pass boot drive correctly. Instead, - they pass 0x00 or 0x01 even when booted from 0x80. */ - if (dest_dev->disk->id & 0x80) - /* Replace the jmp (2 bytes) with double nop's. */ - *boot_drive_check = 0x9090; - - /* If we hardcoded drive as part of prefix, we don't want to - override the current setting. */ - if (*install_dos_part != -2) - { - /* Embed information about the installed location. */ - if (root_dev->disk->partition) - { - if (root_dev->disk->partition->parent) - { - if (root_dev->disk->partition->parent->parent) - grub_util_error ("Installing on doubly nested partitions is " - "not supported"); - dos_part = root_dev->disk->partition->parent->number; - bsd_part = root_dev->disk->partition->number; - } - else - { - dos_part = root_dev->disk->partition->number; - bsd_part = -1; - } - } - else - dos_part = bsd_part = -1; - } - else - { - dos_part = grub_le_to_cpu32 (*install_dos_part); - bsd_part = grub_le_to_cpu32 (*install_bsd_part); - } - - grub_util_info ("dos partition is %d, bsd partition is %d", - dos_part, bsd_part); - - if (dest_dev->disk->partition) - { - grub_util_warn (_("Attempting to install GRUB to a partition instead of the MBR. This is a BAD idea.")); - goto unable_to_embed; - } - - /* Unlike root_dev, with dest_dev we're interested in the partition map even - if dest_dev itself is a whole disk. */ - auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) + /* Unlike root_dev, with dest_dev we're interested in the partition map even + if dest_dev itself is a whole disk. */ + auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) { if (p->parent) return 0; @@ -316,89 +411,85 @@ setup (const char *dir, } return 0; } - dest_partmap = 0; - multiple_partmaps = 0; - grub_partition_iterate (dest_dev->disk, identify_partmap); + dest_partmap = 0; + multiple_partmaps = 0; + grub_partition_iterate (dest_dev->disk, identify_partmap); - if (! dest_partmap) - { - grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea.")); - goto unable_to_embed; - } - if (multiple_partmaps) - { - grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet.")); - goto unable_to_embed; - } + if (! dest_partmap) + { + grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea.")); + goto unable_to_embed; + } + if (multiple_partmaps) + { + grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet.")); + goto unable_to_embed; + } - /* Copy the partition table. */ - if (dest_partmap) - memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); + /* Copy the partition table. */ + if (dest_partmap) + memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); - free (tmp_img); + free (tmp_img); - if (strcmp (dest_partmap, "msdos") == 0) - grub_partition_iterate (dest_dev->disk, find_usable_region_msdos); - else if (strcmp (dest_partmap, "gpt") == 0) - grub_partition_iterate (dest_dev->disk, find_usable_region_gpt); - else - grub_util_error (_("No DOS-style partitions found")); + if (strcmp (dest_partmap, "msdos") == 0) + grub_partition_iterate (dest_dev->disk, find_usable_region_msdos); + else if (strcmp (dest_partmap, "gpt") == 0) + grub_partition_iterate (dest_dev->disk, find_usable_region_gpt); + else + grub_util_error (_("No DOS-style partitions found")); - if (embed_region.end <= embed_region.start) - { - if (! strcmp (dest_partmap, "msdos")) - grub_util_warn (_("This msdos-style partition label has no post-MBR gap; embedding won't be possible!")); - else - grub_util_warn (_("This GPT partition label has no BIOS Boot Partition; embedding won't be possible!")); - goto unable_to_embed; - } + if (embed_region.end <= embed_region.start) + { + if (! strcmp (dest_partmap, "msdos")) + grub_util_warn (_("This msdos-style partition label has no post-MBR gap; embedding won't be possible!")); + else + grub_util_warn (_("This GPT partition label has no BIOS Boot Partition; embedding won't be possible!")); + goto unable_to_embed; + } - if ((unsigned long) core_sectors > embed_region.end - embed_region.start) - { - if (core_sectors > 62) - grub_util_warn (_("Your core.img is unusually large. It won't fit in the embedding area.")); - else /* embed_region.end - embed_region.start < 62 */ - grub_util_warn (_("Your embedding area is unusually small. core.img won't fit in it.")); - goto unable_to_embed; - } + if ((unsigned long) core_sectors > embed_region.end - embed_region.start) + { + if (core_sectors > 62) + grub_util_warn (_("Your core.img is unusually large. It won't fit in the embedding area.")); + else /* embed_region.end - embed_region.start < 62 */ + grub_util_warn (_("Your embedding area is unusually small. core.img won't fit in it.")); + goto unable_to_embed; + } + write_rootdev (core_img, root_dev, + boot_img, embed_region.start); - grub_util_info ("the core image will be embedded at sector 0x%llx", embed_region.start); + grub_util_info ("the core image will be embedded at sector 0x%llx", embed_region.start); - *install_dos_part = grub_cpu_to_le32 (dos_part); - *install_bsd_part = grub_cpu_to_le32 (bsd_part); + /* The first blocklist contains the whole sectors. */ + first_block->start = grub_cpu_to_le64 (embed_region.start + 1); - /* The first blocklist contains the whole sectors. */ - first_block->start = grub_cpu_to_le64 (embed_region.start + 1); + /* These are filled elsewhere. Verify them just in case. */ + assert (first_block->len == grub_host_to_target16 (core_sectors - 1)); + assert (first_block->segment == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG + + (GRUB_DISK_SECTOR_SIZE >> 4))); - /* These are filled elsewhere. Verify them just in case. */ - assert (first_block->len == grub_host_to_target16 (core_sectors - 1)); - assert (first_block->segment == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG - + (GRUB_DISK_SECTOR_SIZE >> 4))); + /* Make sure that the second blocklist is a terminator. */ + block = first_block - 1; + block->start = 0; + block->len = 0; + block->segment = 0; - /* Make sure that the second blocklist is a terminator. */ - block = first_block - 1; - block->start = 0; - block->len = 0; - block->segment = 0; + /* Write the core image onto the disk. */ + if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, core_img)) + grub_util_error ("%s", grub_errmsg); - /* Write the core image onto the disk. */ - if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, core_img)) - grub_util_error ("%s", grub_errmsg); + /* Write the boot image onto the disk. */ + if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, + boot_img)) + grub_util_error ("%s", grub_errmsg); - /* FIXME: can this be skipped? */ - *boot_drive = 0xFF; - - *kernel_sector = grub_cpu_to_le64 (embed_region.start); - - /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, - boot_img)) - grub_util_error ("%s", grub_errmsg); - - goto finish; + goto finish; + } +#endif unable_to_embed: @@ -412,6 +503,9 @@ unable_to_embed: if (! force) grub_util_error (_("if you really want blocklists, use --force")); + /* The core image must be put on a filesystem unfortunately. */ + grub_util_info ("will leave the core image on the filesystem"); + /* Make sure that GRUB reads the identical image as the OS. */ tmp_img = xmalloc (core_size); core_path_dev_full = grub_util_get_path (dir, core_file); @@ -494,7 +588,9 @@ unable_to_embed: { block->start = 0; block->len = 0; +#ifdef GRUB_MACHINE_PCBIOS block->segment = 0; +#endif block--; @@ -519,18 +615,39 @@ unable_to_embed: != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) grub_util_error (_("failed to read the rest sectors of the core image")); +#ifdef GRUB_MACHINE_IEEE1275 + { + char *boot_devpath; + boot_devpath = (char *) (boot_img + + GRUB_BOOT_AOUT_HEADER_SIZE + + GRUB_BOOT_MACHINE_BOOT_DEVPATH); + if (file->device->disk->id != dest_dev->disk->id) + { + const char *dest_ofpath; + dest_ofpath + = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (file->device->disk)); + grub_util_info ("dest_ofpath is `%s'", dest_ofpath); + strncpy (boot_devpath, dest_ofpath, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1); + boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0; + } + else + { + grub_util_info ("non cross-disk install"); + memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH); + } + grub_util_info ("boot device path %s", boot_devpath); + } +#endif + grub_file_close (file); free (core_path_dev); free (tmp_img); - *kernel_sector = grub_cpu_to_le64 (first_sector); - - /* FIXME: can this be skipped? */ - *boot_drive = 0xFF; - - *install_dos_part = grub_cpu_to_le32 (dos_part); - *install_bsd_part = grub_cpu_to_le32 (bsd_part); + write_rootdev (core_img, root_dev, boot_img, first_sector); /* Write the first two sectors of the core image onto the disk. */ grub_util_info ("opening the core image `%s'", core_path); @@ -542,7 +659,8 @@ unable_to_embed: fclose (fp); /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, boot_img)) + if (grub_disk_write (dest_dev->disk, BOOT_SECTOR, + 0, GRUB_DISK_SECTOR_SIZE, boot_img)) grub_util_error ("%s", grub_errmsg); finish: @@ -621,14 +739,18 @@ get_device_name (char *dev) int main (int argc, char *argv[]) { - char *boot_file = 0; - char *core_file = 0; - char *dir = 0; - char *dev_map = 0; - char *root_dev = 0; - char *dest_dev; + char *boot_file = NULL; + char *core_file = NULL; + char *dir = NULL; + char *dev_map = NULL; + char *root_dev = NULL; + char *dest_dev = NULL; int must_embed = 0, force = 0, fs_probe = 1; +#ifdef GRUB_MACHINE_IEEE1275 + force = 1; +#endif + set_program_name (argv[0]); grub_util_init_nls (); @@ -743,10 +865,15 @@ main (int argc, char *argv[]) fprintf (stderr, _("Invalid device `%s'.\n"), argv[optind]); usage (1); } + grub_util_info ("transformed OS device `%s' into GRUB device `%s'", + argv[optind], dest_dev); } else - /* For simplicity. */ - dest_dev = xstrdup (dest_dev); + { + /* For simplicity. */ + dest_dev = xstrdup (dest_dev); + grub_util_info ("Using `%s' as GRUB device", dest_dev); + } if (root_dev) { @@ -761,13 +888,18 @@ main (int argc, char *argv[]) } else { - root_dev = grub_util_get_grub_dev (grub_guess_root_device (dir ? : DEFAULT_DIRECTORY)); + char *root_device = grub_guess_root_device (dir ? : DEFAULT_DIRECTORY); + + root_dev = grub_util_get_grub_dev (root_device); if (! root_dev) { grub_util_info ("guessing the root device failed, because of `%s'", grub_errmsg); grub_util_error (_("cannot guess the root device. Specify the option `--root-device'")); } + grub_util_info ("guessed root device `%s' and root_dev `%s' from " + "dir `%s'", root_device, root_dev, + dir ? : DEFAULT_DIRECTORY); } #ifdef __linux__ @@ -799,7 +931,7 @@ main (int argc, char *argv[]) } else #endif - /* Do the real work. */ + /* Do the real work. */ setup (dir ? : DEFAULT_DIRECTORY, boot_file ? : DEFAULT_BOOT_FILE, core_file ? : DEFAULT_CORE_FILE, diff --git a/util/sparc64/ieee1275/grub-setup.c b/util/sparc64/ieee1275/grub-setup.c deleted file mode 100644 index 1b1a80911..000000000 --- a/util/sparc64/ieee1275/grub-setup.c +++ /dev/null @@ -1,644 +0,0 @@ -/* grub-setup.c - make GRUB usable */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 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 . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define _GNU_SOURCE 1 -#include - -#include "progname.h" - -/* This program fills in various fields inside of the 'boot' and 'core' - * image files. - * - * The 'boot' image needs to know the OBP path name of the root - * device. It also needs to know the initial block number of - * 'core' (which is 'diskboot' concatenated with 'kernel' and - * all the modules, this is created by grub-mkimage). This resulting - * 'boot' image is 512 bytes in size and is placed in the second block - * of a partition. - * - * The initial 'diskboot' block acts as a loader for the actual GRUB - * kernel. It contains the loading code and then a block list. - * - * The block list of 'core' starts at the end of the 'diskboot' image - * and works it's way backwards towards the end of the code of 'diskboot'. - * - * We patch up the images with the necessary values and write out the - * result. - */ - -#define DEFAULT_BOOT_FILE "boot.img" -#define DEFAULT_CORE_FILE "core.img" - -#define grub_target_to_host16(x) grub_be_to_cpu16(x) -#define grub_target_to_host32(x) grub_be_to_cpu32(x) -#define grub_target_to_host64(x) grub_be_to_cpu64(x) -#define grub_host_to_target16(x) grub_cpu_to_be16(x) -#define grub_host_to_target32(x) grub_cpu_to_be32(x) -#define grub_host_to_target64(x) grub_cpu_to_be64(x) - -/* This is the blocklist used in the diskboot image. */ -struct boot_blocklist -{ - grub_uint64_t start; - grub_uint32_t len; -} __attribute__ ((packed)); - -static void -setup (const char *prefix, const char *dir, - const char *boot_file, const char *core_file, - const char *root, const char *dest) -{ - char *boot_path, *core_path; - char *boot_img, *core_img; - size_t boot_size, core_size; - grub_uint16_t core_sectors; - grub_device_t root_dev, dest_dev; - char *boot_devpath; - grub_disk_addr_t *kernel_byte; - struct boot_blocklist *first_block, *block; - char *tmp_img; - int i; - grub_disk_addr_t first_sector; - grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; - grub_file_t file; - FILE *fp; - struct { grub_uint64_t start; grub_uint64_t end; } embed_region; - embed_region.start = embed_region.end = ~0UL; - - auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length); - auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length); - - void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length) - { - grub_util_info ("first sector is <%llu,%u,%u>", sector, offset, length); - - if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the first sector of the core file " - "is not sector-aligned"); - - first_sector = sector; - } - - void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length) - { - struct boot_blocklist *prev = block + 1; - - grub_util_info ("saving <%llu,%u,%u>", sector, offset, length); - - if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("non-sector-aligned data is found in the core file"); - - if (block != first_block - && (grub_be_to_cpu64 (prev->start) - + grub_be_to_cpu16 (prev->len)) == sector) - prev->len = grub_cpu_to_be16 (grub_be_to_cpu16 (prev->len) + 1); - else - { - block->start = grub_cpu_to_be64 (sector); - block->len = grub_cpu_to_be16 (1); - - block--; - if (block->len) - grub_util_error ("the sectors of the core file are too fragmented"); - } - - last_length = length; - } - - /* Read the boot image by the OS service. */ - boot_path = grub_util_get_path (dir, boot_file); - boot_size = grub_util_get_image_size (boot_path); - if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the size of `%s' is not %d", - boot_path, GRUB_DISK_SECTOR_SIZE); - boot_img = grub_util_read_image (boot_path); - free (boot_path); - - /* Set the addresses of variables in the boot image. */ - boot_devpath = (char *) (boot_img - + GRUB_BOOT_AOUT_HEADER_SIZE - + GRUB_BOOT_MACHINE_BOOT_DEVPATH); - kernel_byte = (grub_disk_addr_t *) (boot_img - + GRUB_BOOT_AOUT_HEADER_SIZE - + GRUB_BOOT_MACHINE_KERNEL_BYTE); - - core_path = grub_util_get_path (dir, core_file); - core_size = grub_util_get_image_size (core_path); - core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS); - if (core_size < GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the size of `%s' is too small", core_path); - - core_img = grub_util_read_image (core_path); - free (core_path); - - /* Have FIRST_BLOCK to point to the first blocklist. */ - first_block = (struct boot_blocklist *) (core_img - + GRUB_DISK_SECTOR_SIZE - - sizeof (*block)); - - grub_util_info ("root is `%s', dest is `%s'", root, dest); - - /* Open the root device and the destination device. */ - grub_util_info ("Opening root"); - root_dev = grub_device_open (root); - if (! root_dev) - grub_util_error ("%s", grub_errmsg); - - grub_util_info ("Opening dest"); - dest_dev = grub_device_open (dest); - if (! dest_dev) - grub_util_error ("%s", grub_errmsg); - - grub_util_info ("setting the root device to `%s'", root); - if (grub_env_set ("root", root) != GRUB_ERR_NONE) - grub_util_error ("%s", grub_errmsg); - - /* The core image must be put on a filesystem unfortunately. */ - grub_util_info ("will leave the core image on the filesystem"); - - /* Make sure that GRUB reads the identical image as the OS. */ - tmp_img = xmalloc (core_size); - core_path = grub_util_get_path (prefix, core_file); - - /* It is a Good Thing to sync two times. */ - sync (); - sync (); - -#define MAX_TRIES 5 - - for (i = 0; i < MAX_TRIES; i++) - { - grub_util_info ("attempting to read the core image `%s' from GRUB%s", - core_path, (i == 0) ? "" : " again"); - - grub_disk_cache_invalidate_all (); - - grub_file_filter_disable_compression (); - file = grub_file_open (core_path); - if (file) - { - if (grub_file_size (file) != core_size) - grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)", - (int) grub_file_size (file), (int) core_size); - else if (grub_file_read (file, tmp_img, core_size) - != (grub_ssize_t) core_size) - grub_util_info ("succeeded in opening the core image but cannot read %d bytes", - (int) core_size); - else if (memcmp (core_img, tmp_img, core_size) != 0) - { -#if 0 - FILE *dump; - FILE *dump2; - - dump = fopen ("dump.img", "wb"); - if (dump) - { - fwrite (tmp_img, 1, core_size, dump); - fclose (dump); - } - - dump2 = fopen ("dump2.img", "wb"); - if (dump2) - { - fwrite (core_img, 1, core_size, dump2); - fclose (dump2); - } - -#endif - grub_util_info ("succeeded in opening the core image but the data is different"); - } - else - { - grub_file_close (file); - break; - } - - grub_file_close (file); - } - else - grub_util_info ("couldn't open the core image"); - - if (grub_errno) - grub_util_info ("error message = %s", grub_errmsg); - - grub_errno = GRUB_ERR_NONE; - sync (); - sleep (1); - } - - if (i == MAX_TRIES) - grub_util_error ("cannot read `%s' correctly", core_path); - - /* Clean out the blocklists. */ - block = first_block; - while (block->len) - { - block->start = 0; - block->len = 0; - - block--; - - if ((char *) block <= core_img) - grub_util_error ("no terminator in the core image"); - } - - /* Now read the core image to determine where the sectors are. */ - grub_file_filter_disable_compression (); - file = grub_file_open (core_path); - if (! file) - grub_util_error ("%s", grub_errmsg); - - file->read_hook = save_first_sector; - if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) - != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("failed to read the first sector of the core image"); - - block = first_block; - file->read_hook = save_blocklists; - if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) - != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) - grub_util_error ("failed to read the rest sectors of the core image"); - - if (file->device->disk->id != dest_dev->disk->id) - { - const char *dest_ofpath; - dest_ofpath - = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (file->device->disk)); - grub_util_info ("dest_ofpath is `%s'", dest_ofpath); - strncpy (boot_devpath, dest_ofpath, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1); - boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0; - } - else - { - grub_util_info ("non cross-disk install"); - memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH); - } - - grub_file_close (file); - - free (core_path); - free (tmp_img); - - *kernel_byte = grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS); - - grub_util_info ("boot device path %s, prefix is %s, dest is %s", - boot_devpath, prefix, dest); - - /* Write the first two sectors of the core image onto the disk. */ - core_path = grub_util_get_path (dir, core_file); - grub_util_info ("opening the core image `%s'", core_path); - fp = fopen (core_path, "r+b"); - if (! fp) - grub_util_error ("cannot open `%s'", core_path); - - grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE, fp); - fclose (fp); - free (core_path); - - /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 1, 0, GRUB_DISK_SECTOR_SIZE, boot_img)) - grub_util_error ("%s", grub_errmsg); - - /* Sync is a Good Thing. */ - sync (); - - free (core_img); - free (boot_img); - grub_device_close (dest_dev); - grub_device_close (root_dev); -} - -static struct option options[] = - { - {"boot-image", required_argument, 0, 'b'}, - {"core-image", required_argument, 0, 'c'}, - {"directory", required_argument, 0, 'd'}, - {"device-map", required_argument, 0, 'm'}, - {"root-device", required_argument, 0, 'r'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - -static void -usage (int status) -{ - if (status) - fprintf (stderr, "Try `%s --help' for more information.\n", program_name); - else - printf ("\ -Usage: %s [OPTION]... DEVICE\n\ -\n\ -Set up images to boot from DEVICE.\n\ -DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ -\n\ -You should not normally run %s directly. Use grub-install instead.\n\ -\n\ - -b, --boot-image=FILE use FILE as the boot image [default=%s]\n\ - -c, --core-image=FILE use FILE as the core image [default=%s]\n\ - -d, --directory=DIR use GRUB files in the directory DIR [default=%s]\n\ - -m, --device-map=FILE use FILE as the device map [default=%s]\n\ - -r, --root-device=DEV use DEV as the root device [default=guessed]\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ -\n\ -Report bugs to <%s>.\n\ -", program_name, program_name, - DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY, - DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); - - exit (status); -} - -struct grub_setup_info -{ - char *boot_file; - char *core_file; - char *dir; - char *dev_map; - char *root_dev; - char *prefix; - char *dest_dev; -}; - -static void -init_info (struct grub_setup_info *gp) -{ - gp->boot_file = NULL; - gp->core_file = NULL; - gp->dir = NULL; - gp->dev_map = NULL; - gp->root_dev = NULL; - gp->prefix = NULL; - gp->dest_dev = NULL; -} - -static int -parse_options (struct grub_setup_info *gp, int argc, char *argv[]) -{ - while (1) - { - int c = getopt_long (argc, argv, "b:c:d:m:r:hVv", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'b': - if (gp->boot_file) - free (gp->boot_file); - - gp->boot_file = xstrdup (optarg); - break; - - case 'c': - if (gp->core_file) - free (gp->core_file); - - gp->core_file = xstrdup (optarg); - break; - - case 'd': - if (gp->dir) - free (gp->dir); - - gp->dir = xstrdup (optarg); - break; - - case 'm': - if (gp->dev_map) - free (gp->dev_map); - - gp->dev_map = xstrdup (optarg); - break; - - case 'r': - if (gp->root_dev) - free (gp->root_dev); - - gp->root_dev = xstrdup (optarg); - break; - - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } - } - - if (verbosity > 1) - grub_env_set ("debug", "all"); - - if (optind >= argc) - { - fprintf (stderr, "No device is specified.\n"); - usage (1); - } - - if (optind + 1 != argc) - { - fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]); - usage (1); - } - return 1; -} - -static char * -get_device_name (char *dev) -{ - size_t len = strlen (dev); - - if (dev[0] != '(' || dev[len - 1] != ')') - return 0; - - dev[len - 1] = '\0'; - return dev + 1; -} - -static void -find_dest_dev (struct grub_setup_info *gp, char *argv[]) -{ - gp->dest_dev = get_device_name (argv[optind]); - if (! gp->dest_dev) - { - /* Possibly, the user specified an OS device file. */ - gp->dest_dev = grub_util_get_grub_dev (argv[optind]); - if (! gp->dest_dev) - { - fprintf (stderr, "Invalid device `%s'.\n", argv[optind]); - usage (1); - } - grub_util_info ("transformed OS device `%s' into GRUB device `%s'", - argv[optind], gp->dest_dev); - } - else - { - /* For simplicity. */ - gp->dest_dev = xstrdup (gp->dest_dev); - grub_util_info ("Using `%s' as GRUB device", gp->dest_dev); - } -} - -static void -check_root_dev (struct grub_setup_info *gp) -{ - if (gp->root_dev) - { - char *tmp = get_device_name (gp->root_dev); - - if (! tmp) - grub_util_error ("invalid root device `%s'", gp->root_dev); - - tmp = xstrdup (tmp); - free (gp->root_dev); - gp->root_dev = tmp; - } - else - { - char *dir = gp->dir ? gp->dir : DEFAULT_DIRECTORY; - char *root_device = grub_guess_root_device (dir); - - gp->root_dev = grub_util_get_grub_dev (root_device); - if (! gp->root_dev) - { - grub_util_info ("guessing the root device failed, because of `%s'", - grub_errmsg); - grub_util_error ("cannot guess the root device. " - "Specify the option `--root-device'"); - } - grub_util_info ("guessed root device `%s' and root_dev `%s' from " - "dir `%s'", root_device, gp->root_dev, dir); - } -} - -static void -free_memory (struct grub_setup_info *gp) -{ - free (gp->boot_file); - free (gp->core_file); - free (gp->dir); - free (gp->dev_map); - free (gp->root_dev); - free (gp->prefix); - free (gp->dest_dev); -} - -int -main (int argc, char *argv[]) -{ - struct grub_setup_info ginfo; - - set_program_name (argv[0]); - - grub_util_init_nls (); - - init_info (&ginfo); - if (!parse_options (&ginfo, argc, argv)) - return 0; - - /* Initialize the emulated biosdisk driver. */ - grub_util_biosdisk_init (ginfo.dev_map ? ginfo.dev_map : DEFAULT_DEVICE_MAP); - - /* Initialize all modules. */ - grub_init_all (); - - grub_lvm_fini (); - grub_mdraid_fini (); - grub_raid_fini (); - grub_raid_init (); - grub_mdraid_init (); - grub_lvm_init (); - - find_dest_dev (&ginfo, argv); - - ginfo.prefix = grub_make_system_path_relative_to_its_root (ginfo.dir ? - : DEFAULT_DIRECTORY); - - check_root_dev (&ginfo); - - /* Do the real work. */ - setup (ginfo.prefix, - ginfo.dir ? ginfo.dir : DEFAULT_DIRECTORY, - ginfo.boot_file ? ginfo.boot_file : DEFAULT_BOOT_FILE, - ginfo.core_file ? ginfo.core_file : DEFAULT_CORE_FILE, - ginfo.root_dev, ginfo.dest_dev); - - /* Free resources. */ - grub_fini_all (); - - free_memory (&ginfo); - - return 0; -}