From e1e49678b99f8f53586a007474daca15d6bf9d7b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Feb 2012 21:36:58 +0100 Subject: [PATCH] * util/grub-install.in: Clarify strings. Fix source dir check. --- grub-core/fs/affs.c | 1 + grub-core/fs/bfs.c | 1 + grub-core/fs/btrfs.c | 1 + grub-core/fs/cpio.c | 1 + grub-core/fs/ext2.c | 1 + grub-core/fs/fat.c | 1 + grub-core/fs/hfs.c | 4 + grub-core/fs/hfsplus.c | 1 + grub-core/fs/iso9660.c | 4 + grub-core/fs/jfs.c | 4 + grub-core/fs/minix.c | 4 + grub-core/fs/nilfs2.c | 1 + grub-core/fs/ntfs.c | 1 + grub-core/fs/reiserfs.c | 4 + grub-core/fs/romfs.c | 1 + grub-core/fs/sfs.c | 1 + grub-core/fs/squash4.c | 1 + grub-core/fs/udf.c | 4 + grub-core/fs/ufs.c | 4 + grub-core/fs/xfs.c | 1 + grub-core/fs/zfs/zfs.c | 1 + include/grub/fs.h | 3 + util/grub-setup.c | 220 ++++++++++++++++++++++++++++++++++++---- 23 files changed, 247 insertions(+), 18 deletions(-) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 4ebdbd5e4..50ab8026b 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -571,6 +571,7 @@ static struct grub_fs grub_affs_fs = .label = grub_affs_label, #ifdef GRUB_UTIL .reserved_first_sector = 0, + .blocklist_install = 1, #endif .next = 0 }; diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c index 095764ffe..fd5deb056 100644 --- a/grub-core/fs/bfs.c +++ b/grub-core/fs/bfs.c @@ -1027,6 +1027,7 @@ static struct grub_fs grub_bfs_fs = { #endif #ifdef GRUB_UTIL .reserved_first_sector = 1, + .blocklist_install = 1, #endif }; diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index a3a72a495..c7b09fa8b 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -1656,6 +1656,7 @@ static struct grub_fs grub_btrfs_fs = { #ifdef GRUB_UTIL .embed = grub_btrfs_embed, .reserved_first_sector = 1, + .blocklist_install = 0, #endif }; diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index 1065df94a..cadb5c184 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -715,6 +715,7 @@ static struct grub_fs grub_cpio_fs = { .close = grub_cpio_close, #ifdef GRUB_UTIL .reserved_first_sector = 0, + .blocklist_install = 0, #endif }; diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c index 875f7b928..7ff3cb6f5 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -972,6 +972,7 @@ static struct grub_fs grub_ext2_fs = .mtime = grub_ext2_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 1, + .blocklist_install = 1, #endif .next = 0 }; diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index a6c9760c6..0694051e9 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -1154,6 +1154,7 @@ static struct grub_fs grub_fat_fs = #else .reserved_first_sector = 1, #endif + .blocklist_install = 1, #endif .next = 0 }; diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index 7a5947b23..890cdacbe 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -1357,6 +1357,10 @@ static struct grub_fs grub_hfs_fs = .label = grub_hfs_label, .uuid = grub_hfs_uuid, .mtime = grub_hfs_mtime, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, + .blocklist_install = 1, +#endif .next = 0 }; diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 19cbe563f..5635ebded 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -1108,6 +1108,7 @@ static struct grub_fs grub_hfsplus_fs = .uuid = grub_hfsplus_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 1, + .blocklist_install = 1, #endif .next = 0 }; diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 5e767dc27..2cff864ff 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -1093,6 +1093,10 @@ static struct grub_fs grub_iso9660_fs = .label = grub_iso9660_label, .uuid = grub_iso9660_uuid, .mtime = grub_iso9660_mtime, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, + .blocklist_install = 1, +#endif .next = 0 }; diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index 3676ed719..b323fe0c8 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -913,6 +913,10 @@ static struct grub_fs grub_jfs_fs = .close = grub_jfs_close, .label = grub_jfs_label, .uuid = grub_jfs_uuid, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, + .blocklist_install = 1, +#endif .next = 0 }; diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index ce5c4c738..03122ea4b 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -652,6 +652,10 @@ static struct grub_fs grub_minix_fs = .open = grub_minix_open, .read = grub_minix_read, .close = grub_minix_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, + .blocklist_install = 1, +#endif .next = 0 }; diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index 31d91dbd9..89fc28bd3 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -1178,6 +1178,7 @@ static struct grub_fs grub_nilfs2_fs = { .mtime = grub_nilfs2_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 1, + .blocklist_install = 0, #endif .next = 0 }; diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index a2e014945..31c01f3d5 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -1252,6 +1252,7 @@ static struct grub_fs grub_ntfs_fs = .uuid = grub_ntfs_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 1, + .blocklist_install = 1, #endif .next = 0 }; diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c index 5bb529285..4cb6d66c1 100644 --- a/grub-core/fs/reiserfs.c +++ b/grub-core/fs/reiserfs.c @@ -1389,6 +1389,10 @@ static struct grub_fs grub_reiserfs_fs = .close = grub_reiserfs_close, .label = grub_reiserfs_label, .uuid = grub_reiserfs_uuid, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, + .blocklist_install = 1, +#endif .next = 0 }; diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index 3ea90a214..c32ae9e55 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -455,6 +455,7 @@ static struct grub_fs grub_romfs_fs = .label = grub_romfs_label, #ifdef GRUB_UTIL .reserved_first_sector = 0, + .blocklist_install = 0, #endif .next = 0 }; diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index bc7258963..790c361a5 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -616,6 +616,7 @@ static struct grub_fs grub_sfs_fs = .label = grub_sfs_label, #ifdef GRUB_UTIL .reserved_first_sector = 0, + .blocklist_install = 1, #endif .next = 0 }; diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 2d66abf07..06fac32df 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -935,6 +935,7 @@ static struct grub_fs grub_squash_fs = .mtime = grub_squash_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 0, + .blocklist_install = 0, #endif .next = 0 }; diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 537bb37f0..60653a54c 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -1097,6 +1097,10 @@ static struct grub_fs grub_udf_fs = { .read = grub_udf_read, .close = grub_udf_close, .label = grub_udf_label, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, + .blocklist_install = 1, +#endif .next = 0 }; diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index 12c0e8715..1d0f7a088 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -791,6 +791,10 @@ static struct grub_fs grub_ufs_fs = .label = grub_ufs_label, .uuid = grub_ufs_uuid, .mtime = grub_ufs_mtime, + /* FIXME: set reserved_first_sector. */ +#ifdef GRUB_UTIL + .blocklist_install = 1, +#endif .next = 0 }; diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index fbadc8fa5..b86e2ed0a 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -884,6 +884,7 @@ static struct grub_fs grub_xfs_fs = .uuid = grub_xfs_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 0, + .blocklist_install = 1, #endif .next = 0 }; diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 131d03feb..232005043 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -3939,6 +3939,7 @@ static struct grub_fs grub_zfs_fs = { #ifdef GRUB_UTIL .embed = grub_zfs_embed, .reserved_first_sector = 1, + .blocklist_install = 0, #endif .next = 0 }; diff --git a/include/grub/fs.h b/include/grub/fs.h index 10374ed90..00b78591d 100644 --- a/include/grub/fs.h +++ b/include/grub/fs.h @@ -86,6 +86,9 @@ struct grub_fs /* Whether this filesystem reserves first sector for DOS-style boot. */ int reserved_first_sector; + + /* Whether blocklist installs have a chance to work. */ + int blocklist_install; #endif }; typedef struct grub_fs *grub_fs_t; diff --git a/util/grub-setup.c b/util/grub-setup.c index 9768497c1..2b4dce4aa 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -54,6 +54,12 @@ #include #include +#ifdef __linux__ +#include +#include +#include +#endif + #define _GNU_SOURCE 1 #include @@ -153,7 +159,6 @@ setup (const char *dir, = GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4); #endif grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; - grub_file_t file; FILE *fp; auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, @@ -554,6 +559,17 @@ unable_to_embed: grub_util_error ("%s", _("embedding is not possible, but this is required for " "RAID and LVM install")); + { + 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); + } + #ifdef GRUB_SETUP_BIOS if (dest_dev->disk->id != root_dev->disk->id || dest_dev->disk->dev->id != root_dev->disk->dev->id) @@ -580,11 +596,15 @@ unable_to_embed: grub_util_biosdisk_flush (root_dev->disk); +#ifndef __linux__ + #define MAX_TRIES 5 { int i; for (i = 0; i < MAX_TRIES; i++) { + grub_file_t file; + 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); @@ -648,6 +668,8 @@ unable_to_embed: grub_util_error (_("cannot read `%s' correctly"), core_path_dev); } +#endif + /* Clean out the blocklists. */ block = first_block; while (block->len) @@ -664,22 +686,132 @@ unable_to_embed: grub_util_error ("%s", _("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_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")); + +#ifdef __linux__ + { + grub_partition_t container = root_dev->disk->partition; + 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 + + grub_partition_get_start (container), + 0, rest); + else + save_blocklists (((grub_uint64_t) blk) * mul + j + + grub_partition_get_start (container), + 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) + + j, + 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) + + j, + fie2->fm_extents[i].fe_physical + & (GRUB_DISK_SECTOR_SIZE - 1), len); + + + } + } + } + fclose (fp); + } +#else + { + /* 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")); + } +#endif #ifdef GRUB_SETUP_SPARC64 { @@ -710,8 +842,6 @@ unable_to_embed: } #endif - grub_file_close (file); - free (core_path_dev); free (tmp_img); @@ -725,7 +855,61 @@ unable_to_embed: strerror (errno)); grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp, core_path); + fflush (fp); + fsync (fileno (fp)); fclose (fp); + 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; + grub_partition_t container = root_dev->disk->partition; + grub_err_t err; + + root_dev->disk->partition = 0; + + buf = xmalloc (core_size); + blk = first_sector; + err = grub_disk_read (dest_dev->disk, blk, 0, GRUB_DISK_SECTOR_SIZE, buf); + if (err) + grub_util_error (_("cannot read `%s': %s"), dest_dev->disk->name, + 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; + + err = grub_disk_read (dest_dev->disk, blk, 0, cur, buf); + if (err) + grub_util_error (_("cannot read `%s': %s"), dest_dev->disk->name, + 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")); + } + root_dev->disk->partition = container; + free (buf); + } #ifdef GRUB_SETUP_BIOS finish: