2004-04-04 13:46:03 +00:00
/* grub-setup.c - make GRUB usable */
2003-01-02 20:12:33 +00:00
/*
2004-04-04 13:46:03 +00:00
* GRUB - - GRand Unified Bootloader
2011-10-09 19:13:00 +00:00
* Copyright ( C ) 1999 , 2000 , 2001 , 2002 , 2003 , 2004 , 2005 , 2006 , 2007 , 2008 , 2009 , 2010 , 2011 Free Software Foundation , Inc .
2003-01-02 20:12:33 +00:00
*
2007-07-21 23:32:33 +00:00
* GRUB is free software : you can redistribute it and / or modify
2003-01-02 20:12:33 +00:00
* it under the terms of the GNU General Public License as published by
2007-07-21 23:32:33 +00:00
* the Free Software Foundation , either version 3 of the License , or
2003-01-02 20:12:33 +00:00
* ( at your option ) any later version .
*
2007-07-21 23:32:33 +00:00
* GRUB is distributed in the hope that it will be useful ,
2003-01-02 20:12:33 +00:00
* 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
2007-07-21 23:32:33 +00:00
* along with GRUB . If not , see < http : //www.gnu.org/licenses/>.
2003-01-02 20:12:33 +00:00
*/
# include <config.h>
2004-04-04 13:46:03 +00:00
# include <grub/types.h>
2010-05-06 06:04:04 +00:00
# include <grub/emu/misc.h>
2004-04-04 13:46:03 +00:00
# include <grub/util/misc.h>
# include <grub/device.h>
# include <grub/disk.h>
# include <grub/file.h>
# include <grub/fs.h>
2004-12-04 Marco Gerards <metgerards@student.han.nl>
Modulize the partition map support and add support for the amiga
partition map.
* commands/ls.c: Include <grub/partition.h> instead of
<grub/machine/partition.h>.
* kern/disk.c: Likewise.
* kern/rescue.c: Likewise.
* loader/i386/pc/chainloader.c: Likewise.
* normal/cmdline.c: Likewise.
* kern/powerpc/ieee1275/init.c: Likewise.
(grub_machine_init): Call `grub_pc_partition_map_init',
`grub_amiga_partition_map_init' and
`grub_apple_partition_map_init'.
* conf/i386-pc.rmk (kernel_img_SOURCES): Remove
`disk/i386/pc/partition.c'. Add `kern/partition.c'.
(kernel_img_HEADERS): Remove `machine/partition.h'. Add
`partition.h' and `pc_partition.h'.
(grub_setup_SOURCES): Remove
`disk/i386/pc/partition.c'. Add `kern/partition.c',
`partmap/amiga.c', `partmap/apple.c' and `partmap/pc.c'.
(grub_emu_SOURCES): Likewise.
(pkgdata_MODULES): Add `amiga.mod', `apple.mod' and `pc.mod'.
(amiga_mod_SOURCES, amiga_mod_CFLAGS, apple_mod_SOURCES)
(apple_mod_CFLAGS, pc_mod_SOURCES, pc_mod_CFLAGS): New variables.
* conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Remove
`disk/powerpc/ieee1275/partition.c'. Add `kern/partition.c',
`partmap/amiga.c', `partmap/apple.c' and `partmap/pc.c'.
(grubof_SOURCES): Likewise.
* disk/i386/pc/partition.c: File removed.
* disk/powerpc/ieee1275/partition.c: Likewise.
* include/grub/powerpc/ieee1275/partition.h: Likewise.
* include/grub/i386/pc/partition.h: Likewise.
* kern/partition.c: New file.
* partmap/amiga.c: Likewise.
* partmap/apple.c: Likewise.
* partmap/pc.c: Likewise.
* include/grub/partition.h: Likewise..
* include/grub/pc_partition.h: Likewise.
* util/grub-emu.c: Include <grub/partition.h> instead of
<grub/machine/partition.h>.
(main): Call `grub_pc_partition_map_init',
`grub_amiga_partition_map_init' and
`grub_apple_partition_map_init' and deinitialize afterwards.
* util/i386/pc/biosdisk.c: Include `#include
<grub/partition.h>' and `include <grub/pc_partition.h>' instead of
`<grub/machine/partition.h>'.
* util/i386/pc/grub-setup.c: Likewise.
* util/i386/pc/biosdisk.c: Likewise.
(grub_util_biosdisk_get_grub_dev): Only access the PC specific
partition information in case of a PC partition.
* util/i386/pc/grub-setup.c: Include `#include
<grub/partition.h>' and `include <grub/pc_partition.h>' instead of
`<grub/machine/partition.h>'.
(setup): Only access the PC specific partition information in case
of a PC partition.
2004-12-04 18:45:46 +00:00
# include <grub/partition.h>
2005-07-20 20:30:46 +00:00
# include <grub/env.h>
2010-05-06 06:04:04 +00:00
# include <grub/emu/hostdisk.h>
2006-04-23 13:37:36 +00:00
# include <grub/term.h>
2009-11-18 23:20:22 +00:00
# include <grub/i18n.h>
2006-10-14 Yoshinori K. Okuji <okuji@enbug.org>
* DISTLIST: Added commands/echo.c, disk/lvm.c, disk/raid.c,
include/grub/bitmap.h, include/grub/lvm.h, include/grub/raid.h,
include/grub/i386/pc/vbeutil.h, include/grub/util/lvm.h,
include/grub/util/raid.h, util/lvm.c, util/raid.c, video/bitmap.c,
video/readers/tga.c and video/i386/pc/vbeutil.c.
2006-10-14 Jeroen Dekkers <jeroen@dekkers.cx>
Added support for RAID and LVM.
* disk/lvm.c: New file.
* disk/raid.c: Likewise.
* include/grub/lvm.h: Likewise.
* include/grub/raid.h: Likewise.
* include/grub/util/lvm.h: Likewise.
* include/grub/util/raid.h: Likewise.
* util/lvm.c: Likewise.
* util/raid.c: Likewise.
* include/grub/disk.h (grub_disk_dev_id): Add
GRUB_DISK_DEVICE_RAID_ID and GRUB_DISK_DEVICE_LVM_ID.
(grub_disk_get_size): New prototype.
* kern/disk.c (grub_disk_open): Check whether grub_partition_probe()
returns a partition.
(grub_disk_get_size): New function.
* kern/i386/pc/init.c (make_install_device): Copy the prefix
verbatim if grub_install_dos_part is -2.
* util/i386/pc/getroot.c (grub_guess_root_device): Support RAID
and LVM devices.
* util/i386/pc/grub-setup.c (setup): New argument
MUST_EMBED. Force embedding of GRUB when the argument is
true. Close FILE before returning.
(main): Add support for RAID and LVM.
* conf/common.rmk: Add RAID and LVM modules.
* conf/i386-pc.rmk (grub_setup_SOURCES): Add util/raid.c and
util/lvm.c.
(grub_emu_SOURCES): Add disk/raid.c and disk/lvm.c.
* kern/misc.c (grub_strstr): New function.
* include/grub/misc.h (grub_strstr): New prototype.
2006-10-14 15:24:53 +00:00
# include <grub/util/lvm.h>
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_SPARC64
2010-09-14 19:07:39 +00:00
# include <grub/util/ofpath.h>
2012-02-27 13:24:22 +00:00
# include <grub/sparc64/ieee1275/boot.h>
# include <grub/sparc64/ieee1275/kernel.h>
# else
# include <grub/i386/pc/boot.h>
# include <grub/i386/pc/kernel.h>
2010-09-14 19:07:39 +00:00
# endif
2008-02-19 14:00:11 +00:00
2003-01-02 20:12:33 +00:00
# include <stdio.h>
# include <unistd.h>
# include <string.h>
# include <stdlib.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <dirent.h>
2010-01-03 22:34:03 +00:00
# include <assert.h>
2010-09-14 19:07:39 +00:00
# include <grub/emu/getroot.h>
2009-11-18 23:20:22 +00:00
# include "progname.h"
2010-09-24 12:05:47 +00:00
# include <grub/reed_solomon.h>
2011-01-07 12:27:34 +00:00
# include <grub/msdos_partition.h>
2011-10-23 21:22:38 +00:00
# include <include/grub/crypto.h>
2003-01-02 20:12:33 +00:00
2012-02-27 20:36:58 +00:00
# ifdef __linux__
# include <sys/ioctl.h>
# include <linux/fs.h>
# include <linux/fiemap.h>
# endif
2003-01-02 20:12:33 +00:00
# define _GNU_SOURCE 1
2010-09-20 10:37:37 +00:00
# include <argp.h>
2003-01-02 20:12:33 +00:00
2010-09-14 19:07:39 +00:00
/* 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 .
*/
2003-01-02 20:12:33 +00:00
# define DEFAULT_BOOT_FILE "boot.img"
# define DEFAULT_CORE_FILE "core.img"
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_SPARC64
2010-09-14 19:07:39 +00:00
# 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)
2012-02-27 13:24:22 +00:00
# elif defined (GRUB_SETUP_BIOS)
2010-04-26 19:11:16 +00:00
# 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)
2010-09-14 19:07:39 +00:00
# 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 )
{
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2010-09-14 19:07:39 +00:00
{
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 ) ;
/* FIXME: can this be skipped? */
* boot_drive = 0xFF ;
* kernel_sector = grub_cpu_to_le64 ( first_sector ) ;
}
# endif
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_SPARC64
2010-09-14 19:07:39 +00:00
{
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
}
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_SPARC64
2010-09-14 19:07:39 +00:00
# define BOOT_SECTOR 1
# else
# define BOOT_SECTOR 0
# endif
2010-04-26 19:11:16 +00:00
2003-01-02 20:12:33 +00:00
static void
2008-06-18 17:35:26 +00:00
setup ( const char * dir ,
2003-01-02 20:12:33 +00:00
const char * boot_file , const char * core_file ,
2012-02-03 09:35:28 +00:00
const char * dest , int force ,
2010-10-16 22:35:14 +00:00
int fs_probe , int allow_floppy )
2003-01-02 20:12:33 +00:00
{
2009-11-11 20:10:58 +00:00
char * boot_path , * core_path , * core_path_dev , * core_path_dev_full ;
2003-01-02 20:12:33 +00:00
char * boot_img , * core_img ;
2012-02-03 09:35:28 +00:00
char * root = 0 ;
2003-01-02 20:12:33 +00:00
size_t boot_size , core_size ;
2004-04-04 13:46:03 +00:00
grub_uint16_t core_sectors ;
2012-04-13 14:58:02 +00:00
grub_device_t root_dev = 0 , dest_dev , core_dev ;
2012-02-10 12:49:24 +00:00
struct grub_boot_blocklist * first_block , * block ;
2003-01-02 20:12:33 +00:00
char * tmp_img ;
2006-06-04 Yoshinori K. Okuji <okuji@enbug.org>
Clean up the code to support 64-bit addressing in disks and
files. This change is not enough for filesystems yet.
* util/i386/pc/grub-setup.c (struct boot_blocklist): Change the
type of "start" to grub_uint64_t.
(setup): Change the types of KERNEL_SECTOR and FIRST_SECTOR to
grub_disk_addr_t * and grub_disk_addr_t. Fix the format string in
save_first_sector and save_blocklists. Use grub_le_to_cpu64 to
convert addresses.
* util/i386/pc/biosdisk.c (open_device): Change the type of SECTOR
to grub_disk_addr_t.
* partmap/gpt.c (gpt_partition_map_iterate): Fix the format
string.
* partmap/pc.c (pc_partition_map_iterate): Likewise.
* partmap/amiga.c (amiga_partition_map_iterate): Cast RDSK.MAGIC
to char *.
* normal/script.c (grub_script_parse): Remove unused MEMFREE.
* normal/parser.y (YYLTYPE_IS_TRIVIAL): New macro.
* normal/lexer.c (grub_script_yyerror): Specify unused to LEX.
* loader/i386/pc/multiboot.c (grub_multiboot_load_elf64): Cast -1
to grub_off_t, to detect an error from grub_file_seek.
(grub_multiboot_load_elf32): Likewise.
* kern/misc.c (grub_strtoul): Use grub_strtoull. Return the
maximum unsigned long value when an overflow is detected.
(grub_strtoull): New function.
(grub_divmod64): Likewise.
(grub_lltoa): use grub_divmod64.
* kern/fs.c (struct grub_fs_block): Change the type of "offset" to
grub_disk_addr_t.
(grub_fs_blocklist_open): Increase P if P is not NULL to advance
the pointer to next character. Use grub_strtoull instead of
grub_strtoul.
(grub_fs_blocklist_read): Change the types of SECTOR, OFFSET and
SIZE to grub_disk_addr_t, grub_off_t and grub_size_t,
respectively.
* kern/file.c (grub_file_read): Prevent an oveflow of LEN, as the
return value is signed.
(grub_file_seek): Change the type of OLD to grub_off_t. Do not
test if OFFSET is less than zero, as OFFSET is unsigned now.
* kern/disk.c (struct grub_disk_cache): Change the type of
"sector" to grub_disk_addr_t.
(grub_disk_cache_get_index): Change the type of SECTOR to
grub_disk_addr_t. Calculate the hash with SECTOR casted to
unsigned after shifting.
(grub_disk_cache_invalidate): Change the type of SECTOR to
grub_disk_addr_t.
(grub_disk_cache_unlock): Likewise.
(grub_disk_cache_store): Likewise.
(grub_disk_check_range): Change the types of SECTOR, OFFSET, SIZE,
START and LEN to grub_disk_addr_t *, grub_off_t *, grub_size_t,
grub_disk_addr_t and grub_uint64_t, respectively.
(grub_disk_read): Use an unsigned variable REAL_OFFSET for the
body, as the value of OFFSET is tweaked by
grub_disk_check_range. Change the types of START_SECTOR, LEN and
POS to grub_disk_addr_t, grub_size_t and grub_size_t,
respectively.
(grub_disk_write): Use an unsigned variable REAL_OFFSET for the
body, as the value of OFFSET is tweaked by
grub_disk_check_range. Change the types of LEN and N to
grub_size_t.
* io/gzio.c (struct grub_gzio): Change the types of "data_offset"
and "saved_offset" to grub_off_t.
(test_header): Cast BUF to char *.
(get_byte): Cast GZIO->DATA_OFFSET to grub_off_t. Cast GZIO->INBUF
to char *.
(grub_gzio_read): Change the types of OFFSET and SIZE to
grub_off_t and grub_size_t, respectively.
* include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_FORCE_LBA):
Removed.
(GRUB_BOOT_MACHINE_BOOT_DRIVE): Changed to 0x4c.
(GRUB_BOOT_MACHINE_KERNEL_ADDRESS): Changed to 0x40.
(GRUB_BOOT_MACHINE_KERNEL_SEGMENT): Changed to 0x42.
(GRUB_BOOT_MACHINE_DRIVE_CHECK): Changed to 0x4e.
(GRUB_BOOT_MACHINE_LIST_SIZE): Increased to 12.
* include/grub/types.h (grub_off_t): Unconditionally set to
grub_uint64_t.
(grub_disk_addr_t): Changed to grub_uint64_t.
* include/grub/partition.h (struct grub_partition): Change the
types of "start", "len" and "offset" to grub_disk_addr_t,
grub_uint64_t and grub_disk_addr_t, respectively.
(grub_partition_get_start): Return grub_disk_addr_t.
(grub_partition_get_len): Return grub_uint64_t.
* include/grub/misc.h (grub_strtoull): New prototype.
(grub_divmod64): Likewise.
* include/grub/fshelp.h (grub_fshelp_read_file): Change the types
of SECTOR, LEN and FILESIZE to grub_disk_addr_t, grub_size_t and
grub_off_t, respectively.
All callers and references changed.
* include/grub/fs.h (struct grub_fs): Change the type of LEN to
grub_size_t in "read".
All callers and references changed.
* include/grub/file.h (struct grub_file): Change the types of
"offset" and "size" to grub_off_t and grub_off_t,
respectively. Change the type of SECTOR to grub_disk_addr_t in
"read_hook".
(grub_file_read): Change the type of LEN to grub_size_t.
(grub_file_seek): Return grub_off_t. Change the type of OFFSET to
grub_off_t.
(grub_file_size): Return grub_off_t.
(grub_file_tell): Likewise.
All callers and references changed.
* include/grub/disk.h (struct grub_disk_dev): Change the types of
SECTOR and SIZE to grub_disk_addr_t and grub_size_t in "read" and
"write".
(struct grub_disk): Change the type of "total_sectors" to
grub_uint64_t. Change the type of SECTOR to grub_disk_addr_t in
"read_hook".
(grub_disk_read): Change the types of SECTOR, OFFSET and SIZE to
grub_disk_addr_t, grub_off_t and grub_size_t, respectively.
(grub_disk_write): Likewise.
All callers and references changed.
* fs/iso9660.c (grub_iso9660_susp_iterate): Cast parameters to
char * for grub_strncmp to silence gcc.
(grub_iso9660_mount): Likewise.
(grub_iso9660_mount): Likewise.
(grub_iso9660_read_symlink): Likewise. Also, remove the nonsense
return statement.
(grub_iso9660_iterate_dir): Likewise.
(grub_iso9660_label): Cast DATA->VOLDESC.VOLNAME to char *.
* fs/hfs.c (grub_hfs_read_file): Change the types of SECTOR and
LEN to grub_disk_addr_t and grub_size_t, respectively.
* fs/hfsplus.c (grub_hfsplus_read_file): Likewise.
* fs/jfs.c (grub_jfs_read_file): Likewise.
* fs/minix.c (grub_jfs_read_file): Likewise.
* fs/sfs.c (grub_jfs_read_file): Likewise.
* fs/ufs.c (grub_jfs_read_file): Likewise.
* fs/xfs.c (grub_jfs_read_file): Likewise.
* fs/fat.c (grub_fat_read_data): Change the types of SECTOR, LEN
and SIZE to grub_disk_addr_t, grub_size_t and grub_size_t,
respectively.
* fs/ext2.c (grub_ext2_read_block): When an error happens, set
BLKNR to -1 instead of returning GRUB_ERRNO.
(grub_ext2_read_file): Change the types of SECTOR and
LEN to grub_disk_addr_t and grub_size_t, respectively.
* fs/affs.c (grub_affs_read_file): Change the types of SECTOR and
LEN to grub_disk_addr_t and grub_size_t, respectively.
* font/manager.c (grub_font_get_glyph): Cast BITMAP to char * for
grub_file_read.
* disk/ieee1275/ofdisk.c (grub_ofdisk_read): Fix the format
string. Do not cast SECTOR explicitly.
* disk/i386/pc/biosdisk.c (grub_biosdisk_open): Change the type of
TOTAL_SECTORS to grub_uint64_t. Do not mask DRP->TOTAL_SECTORS.
(grub_biosdisk_rw): Change the types of SECTOR and SIZE to
grub_disk_addr_t and grub_size_t, respectively. If the sector is
over 2TB and LBA mode is not supported, raise an error.
(get_safe_sectors): New function.
(grub_biosdisk_read): Use get_safe_sectors.
(grub_biosdisk_write): Likewise.
* disk/efi/efidisk.c (grub_efidisk_read): Fix the format string.
(grub_efidisk_write): Likewise.
* disk/loopback.c (delete_loopback): Cosmetic changes.
(grub_cmd_loopback): Likewise. Also, test NEWDEV->FILENAME
correctly.
(grub_loopback_open): Likewise.
(grub_loopback_read): Likewise. Also, change the type of POS to
grub_off_t, and fix the usage of grub_memset.
* commands/i386/pc/play.c: Include grub/machine/time.h.
* commands/ls.c (grub_ls_list_files): Use "llu" instead of "d" to
print FILE->SIZE.
* commands/configfile.c: Include grub/env.h.
* commands/cmp.c (grub_cmd_cmp): Do not use ERR, but use
GRUB_ERRNO directly instead. Change the type of POS to
grub_off_t. Follow the coding standard.
* commands/blocklist.c: Include grub/partition.h.
(grub_cmd_blocklist): Return an error if the underlying device is
not a disk. Take the starting sector of a partition into account,
if a partition is used.
* boot/i386/pc/diskboot.S (bootloop): Adapted to the new offset of
a length field.
(lba_mode): Support 64-bit addresses.
(chs_mode): Likewise.
(copy_buffer): Adapted to the new offsets of a length field and a
segment field.
(blocklist_default_start): Allocate 64-bit space.
* boot/i386/pc/boot.S (force_lba): Removed.
(boot_drive): Moved to under KERNEL_SECTOR.
(kernel_sector): Moved to under KENREL_SEGMENT. Allocate 64-bit
space.
(real_start): Set %si earlier. Remove code for FORCE_LBA, since it
is useless.
(lba_mode): Refactored to support a 64-bit address. More size
optimization.
(setup_sectors): Likewise.
2006-06-04 15:56:55 +00:00
grub_disk_addr_t first_sector ;
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2004-04-04 13:46:03 +00:00
grub_uint16_t current_segment
2012-02-27 13:24:22 +00:00
= GRUB_BOOT_I386_PC_KERNEL_SEG + ( GRUB_DISK_SECTOR_SIZE > > 4 ) ;
2010-09-14 19:07:39 +00:00
# endif
2004-04-04 13:46:03 +00:00
grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE ;
2003-01-02 20:12:33 +00:00
FILE * fp ;
2009-06-10 21:04:23 +00:00
2010-09-14 19:07:39 +00:00
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 ) ;
2003-01-02 20:12:33 +00:00
2010-09-14 19:07:39 +00:00
void NESTED_FUNC_ATTR save_first_sector ( grub_disk_addr_t sector ,
unsigned offset ,
unsigned length )
2003-01-02 20:12:33 +00:00
{
2012-02-10 12:49:24 +00:00
grub_util_info ( " the first sector is <% " PRIuGRUB_UINT64_T " ,%u,%u> " ,
2003-01-02 20:12:33 +00:00
sector , offset , length ) ;
2009-06-10 21:04:23 +00:00
2004-04-04 13:46:03 +00:00
if ( offset ! = 0 | | length ! = GRUB_DISK_SECTOR_SIZE )
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , _ ( " the first sector of the core file is not sector-aligned " ) ) ;
2003-01-02 20:12:33 +00:00
first_sector = sector ;
}
2010-09-14 19:07:39 +00:00
void NESTED_FUNC_ATTR save_blocklists ( grub_disk_addr_t sector ,
unsigned offset ,
unsigned length )
2003-01-02 20:12:33 +00:00
{
2010-01-03 22:34:03 +00:00
struct grub_boot_blocklist * prev = block + 1 ;
2003-01-02 20:12:33 +00:00
2012-02-10 12:49:24 +00:00
grub_util_info ( " saving <% " PRIuGRUB_UINT64_T " ,%u,%u> " ,
sector , offset , length ) ;
2009-06-10 21:04:23 +00:00
2004-04-04 13:46:03 +00:00
if ( offset ! = 0 | | last_length ! = GRUB_DISK_SECTOR_SIZE )
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , _ ( " non-sector-aligned data is found in the core file " ) ) ;
2003-01-02 20:12:33 +00:00
if ( block ! = first_block
2010-09-14 19:07:39 +00:00
& & ( grub_target_to_host64 ( prev - > start )
+ grub_target_to_host16 ( prev - > len ) ) = = sector )
2012-02-10 12:49:24 +00:00
{
grub_uint16_t t = grub_target_to_host16 ( prev - > len ) + 1 ;
prev - > len = grub_host_to_target16 ( t ) ;
}
2003-01-02 20:12:33 +00:00
else
{
2010-09-14 19:07:39 +00:00
block - > start = grub_host_to_target64 ( sector ) ;
block - > len = grub_host_to_target16 ( 1 ) ;
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2010-09-14 19:07:39 +00:00
block - > segment = grub_host_to_target16 ( current_segment ) ;
# endif
2003-01-02 20:12:33 +00:00
block - - ;
if ( block - > len )
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , _ ( " the sectors of the core file are too fragmented " ) ) ;
2003-01-02 20:12:33 +00:00
}
2009-06-10 21:04:23 +00:00
2003-01-02 20:12:33 +00:00
last_length = length ;
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2004-04-04 13:46:03 +00:00
current_segment + = GRUB_DISK_SECTOR_SIZE > > 4 ;
2010-09-14 19:07:39 +00:00
# endif
2003-01-02 20:12:33 +00:00
}
2009-06-10 21:04:23 +00:00
2003-01-02 20:12:33 +00:00
/* Read the boot image by the OS service. */
2004-04-04 13:46:03 +00:00
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 )
2010-01-16 00:26:52 +00:00
grub_util_error ( _ ( " the size of `%s' is not %u " ) ,
2004-04-04 13:46:03 +00:00
boot_path , GRUB_DISK_SECTOR_SIZE ) ;
boot_img = grub_util_read_image ( boot_path ) ;
2003-01-02 20:12:33 +00:00
free ( boot_path ) ;
2004-04-04 13:46:03 +00:00
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 )
2010-01-16 00:26:52 +00:00
grub_util_error ( _ ( " the size of `%s' is too small " ) , core_path ) ;
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2010-09-14 19:07:39 +00:00
if ( core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE )
2010-01-16 00:26:52 +00:00
grub_util_error ( _ ( " the size of `%s' is too large " ) , core_path ) ;
2010-09-14 19:07:39 +00:00
# endif
2009-06-10 21:04:23 +00:00
2004-04-04 13:46:03 +00:00
core_img = grub_util_read_image ( core_path ) ;
2003-01-02 20:12:33 +00:00
/* Have FIRST_BLOCK to point to the first blocklist. */
2010-01-03 22:34:03 +00:00
first_block = ( struct grub_boot_blocklist * ) ( core_img
+ GRUB_DISK_SECTOR_SIZE
- sizeof ( * block ) ) ;
2010-09-14 19:07:39 +00:00
grub_util_info ( " root is `%s', dest is `%s' " , root , dest ) ;
2003-01-06 00:01:35 +00:00
2010-09-14 19:07:39 +00:00
grub_util_info ( " Opening dest " ) ;
2004-04-04 13:46:03 +00:00
dest_dev = grub_device_open ( dest ) ;
2003-01-02 20:12:33 +00:00
if ( ! dest_dev )
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , grub_errmsg ) ;
2003-01-02 20:12:33 +00:00
2012-04-13 14:58:02 +00:00
core_dev = dest_dev ;
2012-02-03 09:35:28 +00:00
{
char * * root_devices = grub_guess_root_devices ( dir ) ;
char * * cur ;
int found = 0 ;
for ( cur = root_devices ; * cur ; cur + + )
{
char * drive ;
grub_device_t try_dev ;
drive = grub_util_get_grub_dev ( * cur ) ;
if ( ! drive )
continue ;
try_dev = grub_device_open ( drive ) ;
if ( ! try_dev )
continue ;
if ( ! found & & try_dev - > disk - > id = = dest_dev - > disk - > id
& & try_dev - > disk - > dev - > id = = dest_dev - > disk - > dev - > id )
{
if ( root_dev )
grub_device_close ( root_dev ) ;
free ( root ) ;
root_dev = try_dev ;
root = drive ;
found = 1 ;
continue ;
}
if ( ! root_dev )
{
root_dev = try_dev ;
root = drive ;
continue ;
}
grub_device_close ( try_dev ) ;
free ( drive ) ;
}
if ( ! root_dev )
{
grub_util_error ( " guessing the root device failed, because of `%s' " ,
grub_errmsg ) ;
}
grub_util_info ( " guessed root_dev `%s' from "
" dir `%s' " , root_dev - > disk - > name , dir ) ;
}
2009-11-22 10:20:14 +00:00
grub_util_info ( " setting the root device to `%s' " , root ) ;
2005-07-20 20:30:46 +00:00
if ( grub_env_set ( " root " , root ) ! = GRUB_ERR_NONE )
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , grub_errmsg ) ;
2003-01-02 20:12:33 +00:00
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2003-01-02 20:12:33 +00:00
/* Read the original sector from the disk. */
2004-04-04 13:46:03 +00:00
tmp_img = xmalloc ( GRUB_DISK_SECTOR_SIZE ) ;
if ( grub_disk_read ( dest_dev - > disk , 0 , 0 , GRUB_DISK_SECTOR_SIZE , tmp_img ) )
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , grub_errmsg ) ;
2010-09-14 19:07:39 +00:00
# endif
2003-01-02 20:12:33 +00:00
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2010-09-14 19:07:39 +00:00
{
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 . */
2010-10-16 22:35:14 +00:00
if ( ! allow_floppy & & ! grub_util_biosdisk_is_floppy ( dest_dev - > disk ) )
2010-09-15 13:30:43 +00:00
/* Replace the jmp (2 bytes) with double nop's. */
2010-09-14 19:07:39 +00:00
* boot_drive_check = 0x9090 ;
}
# endif
2008-06-18 17:35:26 +00:00
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2010-09-15 19:36:57 +00:00
{
grub_partition_map_t dest_partmap = NULL ;
2010-09-15 22:27:06 +00:00
grub_partition_t container = dest_dev - > disk - > partition ;
2010-09-15 19:36:57 +00:00
int multiple_partmaps = 0 ;
2012-01-29 13:28:01 +00:00
int is_ldm ;
2010-09-15 19:36:57 +00:00
grub_err_t err ;
2010-09-24 12:05:47 +00:00
grub_disk_addr_t * sectors ;
2010-09-15 19:36:57 +00:00
int i ;
grub_fs_t fs ;
2012-02-27 21:25:39 +00:00
unsigned int nsec , maxsec ;
2010-09-14 19:07:39 +00:00
/* 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 )
2009-05-13 21:01:26 +00:00
{
2010-09-15 19:36:57 +00:00
if ( p - > parent ! = container )
2010-02-06 17:43:37 +00:00
return 0 ;
2011-01-07 12:27:34 +00:00
/* NetBSD and OpenBSD subpartitions have metadata inside a partition,
so they are safe to ignore .
*/
if ( grub_strcmp ( p - > partmap - > name , " netbsd " ) = = 0
| | grub_strcmp ( p - > partmap - > name , " openbsd " ) = = 0 )
return 0 ;
2010-07-04 09:13:31 +00:00
if ( dest_partmap = = NULL )
{
2010-09-15 19:36:57 +00:00
dest_partmap = p - > partmap ;
return 0 ;
2010-07-04 09:13:31 +00:00
}
2010-09-15 19:36:57 +00:00
if ( dest_partmap = = p - > partmap )
return 0 ;
multiple_partmaps = 1 ;
return 1 ;
2009-05-13 21:01:26 +00:00
}
2010-09-15 19:36:57 +00:00
2010-09-14 19:07:39 +00:00
grub_partition_iterate ( dest_dev - > disk , identify_partmap ) ;
2011-01-07 12:27:34 +00:00
if ( container & & grub_strcmp ( container - > partmap - > name , " msdos " ) = = 0
& & dest_partmap
& & ( container - > msdostype = = GRUB_PC_PARTITION_TYPE_NETBSD
| | container - > msdostype = = GRUB_PC_PARTITION_TYPE_OPENBSD ) )
{
2012-02-10 12:49:24 +00:00
grub_util_warn ( " %s " , _ ( " Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet. " ) ) ;
2011-01-07 12:27:34 +00:00
goto unable_to_embed ;
}
2010-09-15 19:36:57 +00:00
fs = grub_fs_probe ( dest_dev ) ;
if ( ! fs )
grub_errno = GRUB_ERR_NONE ;
2012-01-29 13:28:01 +00:00
is_ldm = grub_util_is_ldm ( dest_dev - > disk ) ;
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2010-09-15 19:36:57 +00:00
if ( fs_probe )
{
if ( ! fs & & ! dest_partmap )
grub_util_error ( _ ( " unable to identify a filesystem in %s; safety check can't be performed " ) ,
dest_dev - > disk - > name ) ;
if ( fs & & ! fs - > reserved_first_sector )
2012-02-26 16:28:05 +00:00
/* TRANSLATORS: Filesystem may reserve the space just GRUB isn't sure about it. */
2010-09-15 19:36:57 +00:00
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 ) ;
if ( dest_partmap & & strcmp ( dest_partmap - > name , " msdos " ) ! = 0
& & strcmp ( dest_partmap - > name , " gpt " ) ! = 0
& & strcmp ( dest_partmap - > name , " bsd " ) ! = 0
& & strcmp ( dest_partmap - > name , " netbsd " ) ! = 0
& & strcmp ( dest_partmap - > name , " openbsd " ) ! = 0
& & strcmp ( dest_partmap - > name , " sunpc " ) ! = 0 )
2012-02-26 16:28:05 +00:00
/* TRANSLATORS: Partition map may reserve the space just GRUB isn't sure about it. */
2010-09-15 19:36:57 +00:00
grub_util_error ( _ ( " %s appears to contain a %s partition map 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 , dest_partmap - > name ) ;
2012-01-29 13:28:01 +00:00
if ( is_ldm & & dest_partmap & & strcmp ( dest_partmap - > name , " msdos " ) ! = 0
& & strcmp ( dest_partmap - > name , " gpt " ) ! = 0 )
grub_util_error ( _ ( " %s appears to contain a %s partition map and "
" LDM which isn't known to be a safe combination. "
" 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 , dest_partmap - > name ) ;
2010-09-15 19:36:57 +00:00
}
# endif
2011-03-29 00:20:52 +00:00
/* Copy the partition table. */
if ( dest_partmap | |
( ! allow_floppy & & ! grub_util_biosdisk_is_floppy ( dest_dev - > disk ) ) )
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 ) ;
2012-01-29 13:28:01 +00:00
if ( ! dest_partmap & & ! fs & & ! is_ldm )
2010-09-14 19:07:39 +00:00
{
2012-02-10 12:49:24 +00:00
grub_util_warn ( " %s " , _ ( " Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea. " ) ) ;
2010-09-14 19:07:39 +00:00
goto unable_to_embed ;
}
2012-01-29 13:28:01 +00:00
if ( multiple_partmaps | | ( dest_partmap & & fs ) | | ( is_ldm & & fs ) )
2010-09-14 19:07:39 +00:00
{
2012-02-10 12:49:24 +00:00
grub_util_warn ( " %s " , _ ( " Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet. " ) ) ;
2010-09-14 19:07:39 +00:00
goto unable_to_embed ;
}
2011-11-05 13:47:25 +00:00
if ( dest_partmap & & ! dest_partmap - > embed )
2010-09-14 19:07:39 +00:00
{
2012-03-03 12:05:08 +00:00
grub_util_warn ( _ ( " Partition style `%s' doesn't support embedding " ) ,
2010-09-15 19:36:57 +00:00
dest_partmap - > name ) ;
2010-09-14 19:07:39 +00:00
goto unable_to_embed ;
}
2011-11-05 13:47:25 +00:00
if ( fs & & ! fs - > embed )
{
2012-03-03 12:05:08 +00:00
grub_util_warn ( _ ( " File system `%s' doesn't support embedding " ) ,
2011-11-05 13:47:25 +00:00
fs - > name ) ;
goto unable_to_embed ;
}
2010-09-24 12:05:47 +00:00
nsec = core_sectors ;
2012-02-27 21:25:39 +00:00
maxsec = 2 * core_sectors ;
if ( maxsec > ( ( 0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR )
> > GRUB_DISK_SECTOR_BITS ) )
maxsec = ( ( 0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR )
> > GRUB_DISK_SECTOR_BITS ) ;
2012-01-29 13:28:01 +00:00
if ( is_ldm )
2012-02-27 21:25:39 +00:00
err = grub_util_ldm_embed ( dest_dev - > disk , & nsec , maxsec ,
2012-01-29 13:28:01 +00:00
GRUB_EMBED_PCBIOS , & sectors ) ;
else if ( dest_partmap )
2012-02-27 21:25:39 +00:00
err = dest_partmap - > embed ( dest_dev - > disk , & nsec , maxsec ,
2011-11-05 13:47:25 +00:00
GRUB_EMBED_PCBIOS , & sectors ) ;
else
2012-02-27 21:25:39 +00:00
err = fs - > embed ( dest_dev , & nsec , maxsec ,
2011-11-05 13:47:25 +00:00
GRUB_EMBED_PCBIOS , & sectors ) ;
if ( ! err & & nsec < core_sectors )
{
err = grub_error ( GRUB_ERR_OUT_OF_RANGE ,
2011-11-11 23:34:14 +00:00
N_ ( " Your embedding area is unusually small. "
" core.img won't fit in it. " ) ) ;
2011-11-05 13:47:25 +00:00
}
2012-02-27 21:25:39 +00:00
err = dest_partmap - > embed ( dest_dev - > disk , & nsec , maxsec ,
2010-09-24 12:05:47 +00:00
GRUB_EMBED_PCBIOS , & sectors ) ;
2010-09-15 19:36:57 +00:00
if ( err )
2010-09-14 19:07:39 +00:00
{
2012-02-10 12:49:24 +00:00
grub_util_warn ( " %s " , grub_errmsg ) ;
2010-09-15 19:36:57 +00:00
grub_errno = GRUB_ERR_NONE ;
2010-09-14 19:07:39 +00:00
goto unable_to_embed ;
}
2012-02-27 21:25:39 +00:00
assert ( nsec < = maxsec ) ;
2011-11-05 13:47:25 +00:00
2010-10-16 22:25:23 +00:00
/* Clean out the blocklists. */
block = first_block ;
while ( block - > len )
{
grub_memset ( block , 0 , sizeof ( block ) ) ;
block - - ;
if ( ( char * ) block < = core_img )
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , _ ( " no terminator in the core image " ) ) ;
2010-10-16 22:25:23 +00:00
}
2010-09-15 19:36:57 +00:00
save_first_sector ( sectors [ 0 ] + grub_partition_get_start ( container ) ,
0 , GRUB_DISK_SECTOR_SIZE ) ;
2010-09-14 19:07:39 +00:00
2010-09-15 19:36:57 +00:00
block = first_block ;
2010-09-25 18:40:26 +00:00
for ( i = 1 ; i < nsec ; i + + )
2010-09-15 19:36:57 +00:00
save_blocklists ( sectors [ i ] + grub_partition_get_start ( container ) ,
0 , GRUB_DISK_SECTOR_SIZE ) ;
2010-09-14 19:07:39 +00:00
2010-11-22 22:33:55 +00:00
/* Make sure that the last blocklist is a terminator. */
if ( block = = first_block )
block - - ;
block - > start = 0 ;
block - > len = 0 ;
block - > segment = 0 ;
2010-09-15 19:36:57 +00:00
write_rootdev ( core_img , root_dev , boot_img , first_sector ) ;
2010-09-14 19:07:39 +00:00
2010-09-24 12:05:47 +00:00
core_img = realloc ( core_img , nsec * GRUB_DISK_SECTOR_SIZE ) ;
first_block = ( struct grub_boot_blocklist * ) ( core_img
+ GRUB_DISK_SECTOR_SIZE
- sizeof ( * block ) ) ;
2012-01-24 13:39:29 +00:00
grub_size_t no_rs_length ;
2010-09-24 12:05:47 +00:00
* ( grub_uint32_t * ) ( core_img + GRUB_DISK_SECTOR_SIZE
+ GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY )
= grub_host_to_target32 ( nsec * GRUB_DISK_SECTOR_SIZE - core_size ) ;
2012-01-24 13:39:29 +00:00
no_rs_length = grub_target_to_host16
( * ( grub_uint16_t * ) ( core_img
+ GRUB_DISK_SECTOR_SIZE
+ GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH ) ) ;
if ( no_rs_length = = 0xffff )
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , _ ( " core.img version mismatch " ) ) ;
2010-09-24 12:05:47 +00:00
2011-12-23 09:23:41 +00:00
void * tmp = xmalloc ( core_size ) ;
grub_memcpy ( tmp , core_img , core_size ) ;
2012-01-24 13:39:29 +00:00
grub_reed_solomon_add_redundancy ( core_img + no_rs_length + GRUB_DISK_SECTOR_SIZE ,
core_size - no_rs_length - GRUB_DISK_SECTOR_SIZE ,
2010-09-24 12:05:47 +00:00
nsec * GRUB_DISK_SECTOR_SIZE
- core_size ) ;
2011-12-23 09:23:41 +00:00
assert ( grub_memcmp ( tmp , core_img , core_size ) = = 0 ) ;
free ( tmp ) ;
2010-09-24 12:05:47 +00:00
2010-09-14 19:07:39 +00:00
/* Write the core image onto the disk. */
2010-09-24 12:05:47 +00:00
for ( i = 0 ; i < nsec ; i + + )
2010-09-15 19:36:57 +00:00
grub_disk_write ( dest_dev - > disk , sectors [ i ] , 0 ,
2010-09-24 12:05:47 +00:00
GRUB_DISK_SECTOR_SIZE ,
2010-09-15 19:36:57 +00:00
core_img + i * GRUB_DISK_SECTOR_SIZE ) ;
2010-09-14 19:07:39 +00:00
2010-09-24 12:05:47 +00:00
grub_free ( sectors ) ;
2010-09-14 19:07:39 +00:00
goto finish ;
}
2009-06-10 21:04:23 +00:00
2009-05-13 20:59:45 +00:00
unable_to_embed :
2012-02-10 12:49:24 +00:00
# endif
2009-06-10 21:04:23 +00:00
2012-01-29 13:28:01 +00:00
if ( dest_dev - > disk - > dev - > id ! = root_dev - > disk - > dev - > id )
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , _ ( " embedding is not possible, but this is required for "
" RAID and LVM install " ) ) ;
2012-01-29 13:28:01 +00:00
2012-02-27 20:36:58 +00:00
{
grub_fs_t fs ;
fs = grub_fs_probe ( root_dev ) ;
if ( ! fs )
grub_util_error ( _ ( " can't determine filesystem on %s " ) , root ) ;
if ( ! fs - > blocklist_install )
grub_util_error ( _ ( " filesystem `%s' doesn't support blocklists " ) ,
fs - > name ) ;
}
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2012-02-08 18:26:01 +00:00
if ( dest_dev - > disk - > id ! = root_dev - > disk - > id
| | dest_dev - > disk - > dev - > id ! = root_dev - > disk - > dev - > id )
/* TRANSLATORS: cross-disk refers to /boot being on one disk
but MBR on another . */
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , _ ( " embedding is not possible, but this is required for "
" cross-disk install " ) ) ;
2012-04-13 14:58:02 +00:00
# else
core_dev = root_dev ;
2010-10-26 10:40:35 +00:00
# endif
2012-02-10 12:49:24 +00:00
grub_util_warn ( " %s " , _ ( " Embedding is not possible. GRUB can only be installed in this "
" setup by using blocklists. However, blocklists are UNRELIABLE and "
" their use is discouraged. " ) ) ;
2009-05-04 16:16:03 +00:00
if ( ! force )
2012-03-05 15:42:26 +00:00
/* TRANSLATORS: Here GRUB refuses to continue with blocklist install. */
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , _ ( " will not proceed with blocklists " ) ) ;
2009-06-10 21:04:23 +00:00
2010-09-14 19:07:39 +00:00
/* The core image must be put on a filesystem unfortunately. */
grub_util_info ( " will leave the core image on the filesystem " ) ;
2004-04-04 13:46:03 +00:00
/* Make sure that GRUB reads the identical image as the OS. */
2003-01-02 20:12:33 +00:00
tmp_img = xmalloc ( core_size ) ;
2009-11-11 20:10:58 +00:00
core_path_dev_full = grub_util_get_path ( dir , core_file ) ;
2010-05-06 06:04:04 +00:00
core_path_dev = grub_make_system_path_relative_to_its_root ( core_path_dev_full ) ;
2009-11-11 20:10:58 +00:00
free ( core_path_dev_full ) ;
2009-06-10 21:04:23 +00:00
2011-04-19 20:39:14 +00:00
grub_util_biosdisk_flush ( root_dev - > disk ) ;
2003-01-02 20:12:33 +00:00
2012-02-27 20:36:58 +00:00
# ifndef __linux__
2003-01-02 20:12:33 +00:00
# define MAX_TRIES 5
2012-02-10 12:49:24 +00:00
{
int i ;
for ( i = 0 ; i < MAX_TRIES ; i + + )
{
2012-02-27 20:36:58 +00:00
grub_file_t file ;
2012-02-10 12:49:24 +00:00
grub_util_info ( ( i = = 0 ) ? _ ( " attempting to read the core image `%s' from GRUB " )
: _ ( " attempting to read the core image `%s' from GRUB again " ) ,
core_path_dev ) ;
2009-06-10 21:04:23 +00:00
2012-02-10 12:49:24 +00:00
grub_disk_cache_invalidate_all ( ) ;
2009-06-10 21:04:23 +00:00
2012-02-10 12:49:24 +00:00
grub_file_filter_disable_compression ( ) ;
file = grub_file_open ( core_path_dev ) ;
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 )
{
2003-01-02 23:46:21 +00:00
#if 0
2012-02-10 12:49:24 +00:00
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 ) ;
}
2009-06-10 21:04:23 +00:00
# endif
2012-02-10 12:49:24 +00:00
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 " ) ;
2003-01-02 23:46:21 +00:00
2012-02-10 12:49:24 +00:00
if ( grub_errno )
grub_util_info ( " error message = %s " , grub_errmsg ) ;
2009-06-10 21:04:23 +00:00
2012-02-10 12:49:24 +00:00
grub_errno = GRUB_ERR_NONE ;
grub_util_biosdisk_flush ( root_dev - > disk ) ;
sleep ( 1 ) ;
}
2003-01-02 20:12:33 +00:00
2012-02-10 12:49:24 +00:00
if ( i = = MAX_TRIES )
grub_util_error ( _ ( " cannot read `%s' correctly " ) , core_path_dev ) ;
}
2003-01-02 20:12:33 +00:00
2012-02-27 20:36:58 +00:00
# endif
2003-01-02 20:12:33 +00:00
/* Clean out the blocklists. */
block = first_block ;
while ( block - > len )
{
block - > start = 0 ;
block - > len = 0 ;
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2003-01-02 20:12:33 +00:00
block - > segment = 0 ;
2010-09-14 19:07:39 +00:00
# endif
2003-01-02 20:12:33 +00:00
block - - ;
2009-06-10 21:04:23 +00:00
2003-01-02 20:12:33 +00:00
if ( ( char * ) block < = core_img )
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , _ ( " no terminator in the core image " ) ) ;
2003-01-02 20:12:33 +00:00
}
2009-06-10 21:04:23 +00:00
2012-02-27 20:36:58 +00:00
block = first_block ;
2009-06-10 21:04:23 +00:00
2012-02-27 20:36:58 +00:00
# ifdef __linux__
{
grub_partition_t container = root_dev - > disk - > partition ;
2012-04-13 14:58:02 +00:00
grub_uint64_t container_start = grub_partition_get_start ( container ) ;
2012-02-27 20:36:58 +00:00
struct fiemap fie1 ;
int fd ;
/* Write the first two sectors of the core image onto the disk. */
grub_util_info ( " opening the core image `%s' " , core_path ) ;
fp = fopen ( core_path , " rb " ) ;
if ( ! fp )
grub_util_error ( _ ( " cannot open `%s': %s " ) , core_path ,
strerror ( errno ) ) ;
fd = fileno ( fp ) ;
grub_memset ( & fie1 , 0 , sizeof ( fie1 ) ) ;
fie1 . fm_length = core_size ;
fie1 . fm_flags = FIEMAP_FLAG_SYNC ;
if ( ioctl ( fd , FS_IOC_FIEMAP , & fie1 ) < 0 )
{
int nblocks , i , j ;
int bsize ;
int mul ;
grub_util_info ( " FIEMAP failed. Reverting to FIBMAP " ) ;
if ( ioctl ( fd , FIGETBSZ , & bsize ) < 0 )
grub_util_error ( _ ( " can't retrieve blocklists: %s " ) ,
strerror ( errno ) ) ;
if ( bsize & ( GRUB_DISK_SECTOR_SIZE - 1 ) )
grub_util_error ( " %s " , _ ( " blocksize is not divisible by 512 " ) ) ;
mul = bsize > > GRUB_DISK_SECTOR_BITS ;
nblocks = ( core_size + bsize - 1 ) / bsize ;
for ( i = 0 ; i < nblocks ; i + + )
{
unsigned blk = i ;
if ( ioctl ( fd , FIBMAP , & blk ) < 0 )
grub_util_error ( _ ( " can't retrieve blocklists: %s " ) ,
strerror ( errno ) ) ;
for ( j = 0 ; j < mul ; j + + )
{
int rest = core_size - ( ( i * mul + j ) < < GRUB_DISK_SECTOR_BITS ) ;
if ( rest < = 0 )
break ;
if ( rest > GRUB_DISK_SECTOR_SIZE )
rest = GRUB_DISK_SECTOR_SIZE ;
if ( i = = 0 & & j = = 0 )
save_first_sector ( ( ( grub_uint64_t ) blk ) * mul
2012-04-13 14:58:02 +00:00
+ container_start ,
2012-02-27 20:36:58 +00:00
0 , rest ) ;
else
save_blocklists ( ( ( grub_uint64_t ) blk ) * mul + j
2012-04-13 14:58:02 +00:00
+ container_start ,
2012-02-27 20:36:58 +00:00
0 , rest ) ;
}
}
}
else
{
struct fiemap * fie2 ;
int i , j ;
fie2 = xmalloc ( sizeof ( * fie2 )
+ fie1 . fm_mapped_extents
* sizeof ( fie1 . fm_extents [ 1 ] ) ) ;
memset ( fie2 , 0 , sizeof ( * fie2 )
+ fie1 . fm_mapped_extents * sizeof ( fie2 - > fm_extents [ 1 ] ) ) ;
fie2 - > fm_length = core_size ;
fie2 - > fm_flags = FIEMAP_FLAG_SYNC ;
fie2 - > fm_extent_count = fie1 . fm_mapped_extents ;
if ( ioctl ( fd , FS_IOC_FIEMAP , fie2 ) < 0 )
grub_util_error ( _ ( " can't retrieve blocklists: %s " ) ,
strerror ( errno ) ) ;
for ( i = 0 ; i < fie2 - > fm_mapped_extents ; i + + )
{
for ( j = 0 ;
j < ( ( fie2 - > fm_extents [ i ] . fe_length
+ GRUB_DISK_SECTOR_SIZE - 1 )
> > GRUB_DISK_SECTOR_BITS ) ;
j + + )
{
size_t len = ( fie2 - > fm_extents [ i ] . fe_length
- j * GRUB_DISK_SECTOR_SIZE ) ;
if ( len > GRUB_DISK_SECTOR_SIZE )
len = GRUB_DISK_SECTOR_SIZE ;
if ( i = = 0 & & j = = 0 )
save_first_sector ( ( fie2 - > fm_extents [ i ] . fe_physical
> > GRUB_DISK_SECTOR_BITS )
2012-04-13 14:58:02 +00:00
+ j + container_start ,
2012-02-27 20:36:58 +00:00
fie2 - > fm_extents [ i ] . fe_physical
& ( GRUB_DISK_SECTOR_SIZE - 1 ) , len ) ;
else
save_blocklists ( ( fie2 - > fm_extents [ i ] . fe_physical
> > GRUB_DISK_SECTOR_BITS )
2012-04-13 14:58:02 +00:00
+ j + container_start ,
2012-02-27 20:36:58 +00:00
fie2 - > fm_extents [ i ] . fe_physical
& ( GRUB_DISK_SECTOR_SIZE - 1 ) , len ) ;
2003-01-02 20:12:33 +00:00
2012-02-27 20:36:58 +00:00
}
}
}
fclose ( fp ) ;
}
# else
{
2012-02-29 13:07:53 +00:00
grub_file_t file ;
2012-02-27 20:36:58 +00:00
/* Now read the core image to determine where the sectors are. */
grub_file_filter_disable_compression ( ) ;
file = grub_file_open ( core_path_dev ) ;
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 ( " %s " , _ ( " 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 ( " %s " , _ ( " failed to read the rest sectors of the core image " ) ) ;
2012-02-29 13:07:53 +00:00
grub_file_close ( file ) ;
2012-02-27 20:36:58 +00:00
}
# endif
2003-01-02 20:12:33 +00:00
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_SPARC64
2010-09-14 19:07:39 +00:00
{
char * boot_devpath ;
boot_devpath = ( char * ) ( boot_img
+ GRUB_BOOT_AOUT_HEADER_SIZE
+ GRUB_BOOT_MACHINE_BOOT_DEVPATH ) ;
2012-02-03 09:35:28 +00:00
if ( dest_dev - > disk - > id ! = root_dev - > disk - > id
| | dest_dev - > disk - > dev - > id ! = root_dev - > disk - > dev - > id )
2010-09-14 19:07:39 +00:00
{
const char * dest_ofpath ;
dest_ofpath
2012-02-03 09:35:28 +00:00
= grub_util_devname_to_ofpath ( grub_util_biosdisk_get_osdev ( root_dev - > disk ) ) ;
2010-09-14 19:07:39 +00:00
grub_util_info ( " dest_ofpath is `%s' " , dest_ofpath ) ;
2012-02-27 13:24:22 +00:00
strncpy ( boot_devpath , dest_ofpath ,
GRUB_BOOT_MACHINE_BOOT_DEVPATH_END
2010-09-14 19:07:39 +00:00
- 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
2008-06-26 15:29:32 +00:00
free ( core_path_dev ) ;
2003-01-02 20:12:33 +00:00
free ( tmp_img ) ;
2009-06-10 21:04:23 +00:00
2010-09-14 19:07:39 +00:00
write_rootdev ( core_img , root_dev , boot_img , first_sector ) ;
2008-06-30 23:52:24 +00:00
2003-01-06 00:01:35 +00:00
/* Write the first two sectors of the core image onto the disk. */
2009-11-22 10:20:14 +00:00
grub_util_info ( " opening the core image `%s' " , core_path ) ;
2003-01-02 20:12:33 +00:00
fp = fopen ( core_path , " r+b " ) ;
if ( ! fp )
2012-02-05 10:07:33 +00:00
grub_util_error ( _ ( " cannot open `%s': %s " ) , core_path ,
strerror ( errno ) ) ;
2003-01-02 20:12:33 +00:00
2012-02-05 10:07:33 +00:00
grub_util_write_image ( core_img , GRUB_DISK_SECTOR_SIZE * 2 , fp , core_path ) ;
2012-02-27 20:36:58 +00:00
fflush ( fp ) ;
fsync ( fileno ( fp ) ) ;
2003-01-02 20:12:33 +00:00
fclose ( fp ) ;
2012-02-27 20:36:58 +00:00
grub_util_biosdisk_flush ( root_dev - > disk ) ;
grub_disk_cache_invalidate_all ( ) ;
{
char * buf , * ptr = core_img ;
size_t len = core_size ;
grub_uint64_t blk ;
2012-04-13 14:58:02 +00:00
grub_partition_t container = core_dev - > disk - > partition ;
2012-02-27 20:36:58 +00:00
grub_err_t err ;
2012-04-13 14:58:02 +00:00
core_dev - > disk - > partition = 0 ;
2012-02-27 20:36:58 +00:00
buf = xmalloc ( core_size ) ;
blk = first_sector ;
2012-04-13 14:58:02 +00:00
err = grub_disk_read ( core_dev - > disk , blk , 0 , GRUB_DISK_SECTOR_SIZE , buf ) ;
2012-02-27 20:36:58 +00:00
if ( err )
2012-04-13 14:58:02 +00:00
grub_util_error ( _ ( " cannot read `%s': %s " ) , core_dev - > disk - > name ,
2012-02-27 20:36:58 +00:00
grub_errmsg ) ;
if ( grub_memcmp ( buf , ptr , GRUB_DISK_SECTOR_SIZE ) ! = 0 )
grub_util_error ( " %s " , _ ( " blocklists are invalid " ) ) ;
ptr + = GRUB_DISK_SECTOR_SIZE ;
len - = GRUB_DISK_SECTOR_SIZE ;
block = first_block ;
while ( block - > len )
{
size_t cur = grub_target_to_host16 ( block - > len ) < < GRUB_DISK_SECTOR_BITS ;
blk = grub_target_to_host64 ( block - > start ) ;
if ( cur > len )
cur = len ;
2012-04-13 14:58:02 +00:00
err = grub_disk_read ( core_dev - > disk , blk , 0 , cur , buf ) ;
2012-02-27 20:36:58 +00:00
if ( err )
2012-04-13 14:58:02 +00:00
grub_util_error ( _ ( " cannot read `%s': %s " ) , core_dev - > disk - > name ,
2012-02-27 20:36:58 +00:00
grub_errmsg ) ;
if ( grub_memcmp ( buf , ptr , cur ) ! = 0 )
grub_util_error ( " %s " , _ ( " blocklists are invalid " ) ) ;
ptr + = cur ;
len - = cur ;
block - - ;
if ( ( char * ) block < = core_img )
grub_util_error ( " %s " , _ ( " no terminator in the core image " ) ) ;
}
2012-04-13 14:58:02 +00:00
core_dev - > disk - > partition = container ;
2012-02-27 20:36:58 +00:00
free ( buf ) ;
}
2003-01-02 20:12:33 +00:00
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_BIOS
2010-09-15 22:27:06 +00:00
finish :
2012-02-10 12:49:24 +00:00
# endif
2010-09-15 22:27:06 +00:00
2003-01-02 20:12:33 +00:00
/* Write the boot image onto the disk. */
2010-09-14 19:07:39 +00:00
if ( grub_disk_write ( dest_dev - > disk , BOOT_SECTOR ,
0 , GRUB_DISK_SECTOR_SIZE , boot_img ) )
2012-02-10 12:49:24 +00:00
grub_util_error ( " %s " , grub_errmsg ) ;
2003-01-02 20:12:33 +00:00
2011-04-19 20:39:14 +00:00
grub_util_biosdisk_flush ( root_dev - > disk ) ;
grub_util_biosdisk_flush ( dest_dev - > disk ) ;
2009-06-10 21:04:23 +00:00
2008-06-26 15:29:32 +00:00
free ( core_path ) ;
2003-01-02 20:12:33 +00:00
free ( core_img ) ;
free ( boot_img ) ;
2004-04-04 13:46:03 +00:00
grub_device_close ( dest_dev ) ;
2008-02-03 21:53:32 +00:00
grub_device_close ( root_dev ) ;
2003-01-02 20:12:33 +00:00
}
2010-09-20 10:37:37 +00:00
static struct argp_option options [ ] = {
{ " boot-image " , ' b ' , N_ ( " FILE " ) , 0 ,
2012-02-25 00:15:29 +00:00
N_ ( " use FILE as the boot image [default=%s] " ) , 0 } ,
2010-09-20 10:37:37 +00:00
{ " core-image " , ' c ' , N_ ( " FILE " ) , 0 ,
2012-02-25 00:15:29 +00:00
N_ ( " use FILE as the core image [default=%s] " ) , 0 } ,
2010-09-20 10:37:37 +00:00
{ " directory " , ' d ' , N_ ( " DIR " ) , 0 ,
2012-02-25 00:15:29 +00:00
N_ ( " use GRUB files in the directory DIR [default=%s] " ) , 0 } ,
2010-09-20 10:37:37 +00:00
{ " device-map " , ' m ' , N_ ( " FILE " ) , 0 ,
2012-02-08 18:26:01 +00:00
N_ ( " use FILE as the device map [default=%s] " ) , 0 } ,
2010-09-20 10:37:37 +00:00
{ " force " , ' f ' , 0 , 0 ,
2012-02-08 18:26:01 +00:00
N_ ( " install even if problems are detected " ) , 0 } ,
2010-09-20 10:37:37 +00:00
{ " skip-fs-probe " , ' s ' , 0 , 0 ,
2012-02-25 00:15:29 +00:00
N_ ( " do not probe for filesystems in DEVICE " ) , 0 } ,
2012-02-05 10:23:47 +00:00
{ " verbose " , ' v ' , 0 , 0 , N_ ( " print verbose messages. " ) , 0 } ,
2010-10-16 22:35:14 +00:00
{ " allow-floppy " , ' a ' , 0 , 0 ,
2012-03-05 15:42:26 +00:00
/* TRANSLATORS: The potential breakage isn't limited to floppies but it's
likely to make the install unbootable from HDD . */
2012-02-25 00:15:29 +00:00
N_ ( " make the drive also bootable as floppy (default for fdX devices). May break on some BIOSes. " ) , 0 } ,
2010-10-16 22:35:14 +00:00
2010-09-20 10:37:37 +00:00
{ 0 , 0 , 0 , 0 , 0 , 0 }
} ;
static char *
help_filter ( int key , const char * text , void * input __attribute__ ( ( unused ) ) )
{
switch ( key )
{
case ' b ' :
return xasprintf ( text , DEFAULT_BOOT_FILE ) ;
case ' c ' :
return xasprintf ( text , DEFAULT_CORE_FILE ) ;
case ' d ' :
return xasprintf ( text , DEFAULT_DIRECTORY ) ;
case ' m ' :
return xasprintf ( text , DEFAULT_DEVICE_MAP ) ;
2003-01-02 20:12:33 +00:00
2010-09-20 10:37:37 +00:00
default :
return ( char * ) text ;
}
}
struct arguments
{
char * boot_file ;
char * core_file ;
char * dir ;
char * dev_map ;
int force ;
int fs_probe ;
2010-10-16 22:35:14 +00:00
int allow_floppy ;
2010-09-20 10:37:37 +00:00
char * device ;
} ;
static error_t
argp_parser ( int key , char * arg , struct argp_state * state )
{
/* Get the input argument from argp_parse, which we
know is a pointer to our arguments structure . */
struct arguments * arguments = state - > input ;
switch ( key )
{
2010-10-16 22:35:14 +00:00
case ' a ' :
arguments - > allow_floppy = 1 ;
break ;
2010-09-20 10:37:37 +00:00
case ' b ' :
if ( arguments - > boot_file )
free ( arguments - > boot_file ) ;
arguments - > boot_file = xstrdup ( arg ) ;
break ;
case ' c ' :
if ( arguments - > core_file )
free ( arguments - > core_file ) ;
arguments - > core_file = xstrdup ( arg ) ;
break ;
case ' d ' :
if ( arguments - > dir )
free ( arguments - > dir ) ;
arguments - > dir = xstrdup ( arg ) ;
break ;
case ' m ' :
if ( arguments - > dev_map )
free ( arguments - > dev_map ) ;
arguments - > dev_map = xstrdup ( arg ) ;
break ;
case ' f ' :
arguments - > force = 1 ;
break ;
case ' s ' :
arguments - > fs_probe = 0 ;
break ;
case ' v ' :
verbosity + + ;
break ;
case ARGP_KEY_ARG :
if ( state - > arg_num = = 0 )
arguments - > device = xstrdup ( arg ) ;
else
{
/* Too many arguments. */
2012-02-26 16:28:05 +00:00
fprintf ( stderr , _ ( " Unknown extra argument `%s'. " ) , arg ) ;
fprintf ( stderr , " \n " ) ;
2010-09-20 10:37:37 +00:00
argp_usage ( state ) ;
}
break ;
case ARGP_KEY_NO_ARGS :
2010-09-20 16:56:14 +00:00
fprintf ( stderr , " %s " , _ ( " No device is specified. \n " ) ) ;
2010-09-20 10:37:37 +00:00
argp_usage ( state ) ;
2012-02-03 20:18:37 +00:00
exit ( 1 ) ;
2010-09-20 10:37:37 +00:00
break ;
default :
return ARGP_ERR_UNKNOWN ;
}
return 0 ;
2003-01-02 20:12:33 +00:00
}
2010-09-20 10:37:37 +00:00
static struct argp argp = {
options , argp_parser , N_ ( " DEVICE " ) ,
2010-09-21 09:17:54 +00:00
" \n " N_ ( " \
2010-09-20 10:37:37 +00:00
Set up images to boot from DEVICE . \ n \
\ n \
2010-09-21 09:17:54 +00:00
You should not normally run this program directly . Use grub - install instead . " )
" \v " N_ ( " \
2010-10-26 10:33:57 +00:00
DEVICE must be an OS device ( e . g . / dev / sda ) . " ),
2010-09-20 10:37:37 +00:00
NULL , help_filter , NULL
} ;
2003-01-02 20:12:33 +00:00
static char *
get_device_name ( char * dev )
{
size_t len = strlen ( dev ) ;
2009-06-10 21:04:23 +00:00
2003-01-02 20:12:33 +00:00
if ( dev [ 0 ] ! = ' ( ' | | dev [ len - 1 ] ! = ' ) ' )
return 0 ;
dev [ len - 1 ] = ' \0 ' ;
return dev + 1 ;
}
int
main ( int argc , char * argv [ ] )
{
2010-09-14 19:07:39 +00:00
char * root_dev = NULL ;
char * dest_dev = NULL ;
2010-09-20 10:37:37 +00:00
struct arguments arguments ;
2009-06-10 21:04:23 +00:00
2009-11-18 23:20:22 +00:00
set_program_name ( argv [ 0 ] ) ;
2010-01-01 20:32:30 +00:00
grub_util_init_nls ( ) ;
2003-01-02 20:12:33 +00:00
2010-09-20 10:37:37 +00:00
/* Default option values. */
memset ( & arguments , 0 , sizeof ( struct arguments ) ) ;
arguments . fs_probe = 1 ;
2003-01-02 20:12:33 +00:00
2010-09-20 10:37:37 +00:00
/* Parse our arguments */
if ( argp_parse ( & argp , argc , argv , 0 , 0 , & arguments ) ! = 0 )
{
2010-09-20 16:56:14 +00:00
fprintf ( stderr , " %s " , _ ( " Error in parsing command line arguments \n " ) ) ;
2010-09-20 10:37:37 +00:00
exit ( 1 ) ;
2003-01-02 20:12:33 +00:00
}
2012-02-27 13:24:22 +00:00
# ifdef GRUB_SETUP_SPARC64
2010-09-30 17:27:28 +00:00
arguments . force = 1 ;
# endif
2008-02-09 10:46:37 +00:00
if ( verbosity > 1 )
grub_env_set ( " debug " , " all " ) ;
2005-07-24 18:16:26 +00:00
/* Initialize the emulated biosdisk driver. */
2010-09-20 10:37:37 +00:00
grub_util_biosdisk_init ( arguments . dev_map ? : DEFAULT_DEVICE_MAP ) ;
2003-01-02 20:12:33 +00:00
2007-07-22 19:17:27 +00:00
/* Initialize all modules. */
grub_init_all ( ) ;
2011-08-16 14:19:06 +00:00
grub_gcry_init_all ( ) ;
2009-06-10 21:04:23 +00:00
2010-09-05 21:24:57 +00:00
grub_lvm_fini ( ) ;
2010-09-20 18:09:31 +00:00
grub_mdraid09_fini ( ) ;
grub_mdraid1x_fini ( ) ;
2012-01-29 13:28:01 +00:00
grub_diskfilter_fini ( ) ;
grub_diskfilter_init ( ) ;
2010-09-20 18:09:31 +00:00
grub_mdraid09_init ( ) ;
grub_mdraid1x_init ( ) ;
2010-09-05 21:24:57 +00:00
grub_lvm_init ( ) ;
2010-09-20 10:37:37 +00:00
dest_dev = get_device_name ( arguments . device ) ;
2003-01-02 20:12:33 +00:00
if ( ! dest_dev )
{
2005-07-24 18:16:26 +00:00
/* Possibly, the user specified an OS device file. */
2010-09-20 10:37:37 +00:00
dest_dev = grub_util_get_grub_dev ( arguments . device ) ;
2005-07-24 18:16:26 +00:00
if ( ! dest_dev )
2010-09-20 10:37:37 +00:00
{
char * program = xstrdup ( program_name ) ;
fprintf ( stderr , _ ( " Invalid device `%s'. \n " ) , arguments . device ) ;
argp_help ( & argp , stderr , ARGP_HELP_STD_USAGE , program ) ;
free ( program ) ;
exit ( 1 ) ;
}
2010-09-14 19:07:39 +00:00
grub_util_info ( " transformed OS device `%s' into GRUB device `%s' " ,
2010-09-20 10:37:37 +00:00
arguments . device , dest_dev ) ;
2003-01-02 20:12:33 +00:00
}
2005-07-24 18:16:26 +00:00
else
2010-09-14 19:07:39 +00:00
{
/* For simplicity. */
dest_dev = xstrdup ( dest_dev ) ;
grub_util_info ( " Using `%s' as GRUB device " , dest_dev ) ;
}
2003-01-02 20:12:33 +00:00
2012-01-29 13:28:01 +00:00
/* Do the real work. */
setup ( arguments . dir ? : DEFAULT_DIRECTORY ,
arguments . boot_file ? : DEFAULT_BOOT_FILE ,
arguments . core_file ? : DEFAULT_CORE_FILE ,
2012-02-03 09:35:28 +00:00
dest_dev , arguments . force ,
2012-01-29 13:28:01 +00:00
arguments . fs_probe , arguments . allow_floppy ) ;
2003-01-02 20:12:33 +00:00
/* Free resources. */
2007-07-22 19:17:27 +00:00
grub_fini_all ( ) ;
2004-04-04 13:46:03 +00:00
grub_util_biosdisk_fini ( ) ;
2009-06-10 21:04:23 +00:00
2010-09-20 10:37:37 +00:00
free ( arguments . boot_file ) ;
free ( arguments . core_file ) ;
free ( arguments . dir ) ;
free ( arguments . dev_map ) ;
free ( arguments . device ) ;
2003-01-02 20:12:33 +00:00
free ( root_dev ) ;
2005-07-24 18:16:26 +00:00
free ( dest_dev ) ;
2009-06-10 21:04:23 +00:00
2003-01-02 20:12:33 +00:00
return 0 ;
}