Wed 16 Dec 2015 02:53:02 AM UTC, original submission:
Suppose you wanted to make a FAT-based GRUB2 floppy disk image, as follows:
>>>>
mkdosfs -F 12 -R 2 -I -C -S 512 /tmp/14.img 1440
mount -t vfat -o loop,sync,dirsync,umask=0,shortname=mixed /tmp/14.img /media/fd || exit 1
grub-install \
--boot-directory=/media/fd/boot \
--modules='fat iso9660 biosdisk part_msdos part_bsd part_gpt halt reboot' \
--install-modules='cat linux16 halt reboot help normal ls chain fat ext2 ufs2 ntfs zfs xfs msdospart ' \
--fonts= --locales= --allow-floppy \
--force \
--debug --debug \
/dev/loop0
umount /media/fd
<<<<
grub-install will always fail with
>>>>
grub2-install: warning: Embedding is not possible. GRUB can only be installed in this setup by using blocklists. However, blocklists are UNRELIABLE and their use is discouraged..
grub2-install: info: will leave the core image on the filesystem.
grub2-install: info: opening the core image `/media/fd/boot/grub2/i386-pc/core.img'.
grub2-install: info: FIEMAP failed. Reverting to FIBMAP.
grub2-install: info: saving <924,0,512>.
....
grub2-install: info: saving <1018,0,415>.
grub2-install: info: opening the core image `/media/fd/boot/grub2/i386-pc/core.img'.
grub-core/osdep/hostdisk.c:395: reusing open device `/dev/loop0'
grub2-install: error: blocklists are invalid.
<<<<
This is due to bug/feature of accessing unpartitioned device on linux;
suppose block Y of /dev/loop0 is affected.
(1) grub read-aheads block Y from /dev/loop0
(2) grub writes via filesystem the core.img, which correctly rewrites underlying block Y
(3) grub re-reads block Y via /dev/loop0 as blocklist of core.img to
verify content,
which kernel returns stale data of (1),
resulting in verify mismatch; "error: blocklists are invalid"
grub-install purges its disk cache before core.img verification, but this
isn't effective since stale data is returned by kernel itself.
This problem also occurs on real block device /dev/floppy .
This does NOT occur on partitioned device such as /dev/sdb1, for unknown reason;
so did not affect standard HDD installs.
Fix: Open(2) /dev/loop0 with O_DIRECT flag. This fixed the problem.
Patch attached. Do
% find . -name '*setup_bios.o' |xargs rm
% find . -name '*hostdisk.o' |xargs rm
(or make clean) after applying patch for correct rebuild.
Unfortunately O_DIRECT requires block-aligned buffer for read(2)ing,
so grub_util_biosdisk_read() needs a whole mess of preparing aligned buffer.
----- 8< -----
Open(2) destination device with O_DIRECT flag. This fixes grub-install to fail
when installing using a blocklist to a filesystem mounted via /dev/loop0 loopback.
|