aboutsummaryrefslogtreecommitdiff
path: root/projects/grub/grub-helper
diff options
context:
space:
mode:
authorAndrew Robbins <contact@andrewrobbins.info>2018-12-25 21:41:27 -0500
committerAndrew Robbins <contact@andrewrobbins.info>2018-12-25 21:41:27 -0500
commitc9e5a6b91406fe0e1b8188c2818c5e2f7ad3e267 (patch)
treeed2e90f3927d0b3094121c42b338e38463057281 /projects/grub/grub-helper
parent4f989bf93a6b8c1a6ce0f38adf47469cd58493e0 (diff)
downloadlibrebootfr-c9e5a6b91406fe0e1b8188c2818c5e2f7ad3e267.tar.gz
librebootfr-c9e5a6b91406fe0e1b8188c2818c5e2f7ad3e267.zip
Automate updating SeaGRUB floppy image blocklists
Related issue #553 Determining the byte offset of core.img on the SeaGRUB floppy is accomplished using grub_bo(), though it is memory bound as it requires reading hex dumps for the pattern and comparand into memory. The blocklists that are stored in the boot record and core.img are sector numbers. Of particular note is the blocklist written to core.img is always the location of its *second* sector--not the first. Blocklists are used because floppy disks DO NOT have an MBR or MBR gap as the filesystem spans the entire disk. Consequently, the core.img cannot be stored in the usual ~1MiB gap. Unfortunately, using blocklists means they will have to be updated whenever core.img is moved. New functions added to grub-helper: * grub_bo * grub_bo_dump * grub_bo_search * grub_blocklist_format * grub_blocklist_generate * grub_floppy_image_make_bootable * grub_floppy_image_update_blocklists
Diffstat (limited to 'projects/grub/grub-helper')
-rwxr-xr-xprojects/grub/grub-helper96
1 files changed, 95 insertions, 1 deletions
diff --git a/projects/grub/grub-helper b/projects/grub/grub-helper
index 04814575..ccc9cd73 100755
--- a/projects/grub/grub-helper
+++ b/projects/grub/grub-helper
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (C) 2017 Andrew Robbins <contact@andrewrobbins.info>
+# Copyright (C) 2017,2018 Andrew Robbins <contact@andrewrobbins.info>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -62,6 +62,47 @@ grub_modmin_path() {
project_file_path "$project" "$CONFIGS" "$MODMIN" "$@"
}
+grub_bo_search() {
+ local pattern="$1"
+ local comparand="$2"
+
+ grep -Fbof <(grub_bo_dump "$pattern") <(grub_bo_dump "$comparand") | cut -d: -f1
+}
+
+grub_bo_dump() {
+ local file="$1"
+
+ od -Anx -t x1 -w16 -v "$file" | paste -sd '' | tr -d ' '
+}
+
+grub_bo() {
+ local pattern="$1"
+ local comparand="$2"
+
+ local nibble_offset="$(grub_bo_search "$pattern" "$comparand")"
+
+ if [[ -n "$nibble_offset" ]]; then
+ printf '0x%X\n' $((nibble_offset / 2))
+ else
+ return 1
+ fi
+}
+
+grub_blocklist_format() {
+ local blocklist="$1"
+ local byte
+
+ while read -N 2 byte; do
+ printf '%s' "\\x$byte"
+ done <<< "$blocklist"
+}
+
+grub_blocklist_generate() {
+ local -i byte_offset="$1"
+
+ printf '%04x' $((byte_offset / 512)) | tac -rs ..
+}
+
grub_copy_modules() {
local grub_module_dir="$sources_path/grub-core"
local keep_dir="$build_path/$(grub_format "$target" "$@")"
@@ -179,6 +220,7 @@ grub_build_floppy_image() {
grub_floppy_image_mmd "$floppyimg" /boot /boot/grub "/boot/grub/$format"
grub_floppy_image_mcopy "$floppyimg" "/boot/grub/$format" "${modules[@]}"
+ grub_floppy_image_make_bootable "$floppyimg"
}
grub_build_standalone_image() {
@@ -232,3 +274,55 @@ grub_floppy_image_mcopy() {
mcopy -i "$img" -pQv "${files[@]}" "::$target"
fi
}
+
+grub_floppy_image_make_bootable() {
+ local floppyimg="$1"
+ local bootimg="$build_path/boot.img"
+ local coreimg="$build_path/core.img"
+ local oem_name='\x4C\x49\x42\x52\x45\x20\x20\x20'
+
+ # write $floppyimg Bios Parameter Block to $bootimg first
+ dd if="$floppyimg" of="$bootimg" bs=1 skip=11 seek=11 count=52 conv=notrunc
+ dd if=<(printf "$oem_name") of="$bootimg" bs=1 seek=3 conv=notrunc
+ dd if=/dev/zero of="$floppyimg" count=1 conv=notrunc
+ dd if="$bootimg" of="$floppyimg" conv=notrunc
+
+ grub_floppy_image_mcopy "$floppyimg" /boot/grub "$bootimg"
+ grub_floppy_image_mcopy "$floppyimg" /boot/grub "$coreimg"
+
+ grub_floppy_image_update_blocklists "$coreimg" "$floppyimg"
+ rm -f "$bootimg" "$coreimg"
+}
+
+grub_floppy_image_update_blocklists() {
+ local coreimg="$1"
+ local floppyimg="$2"
+
+ local -i coreimg_offset="$(grub_bo "$coreimg" "$floppyimg")"
+ local -i coreimg_second_sector_offset=$((coreimg_offset + 0x200))
+
+ local -i boot_record_blocklist_offset=0x5C
+ local -i coreimg_blocklist_offset=$((coreimg_offset + 0x1F4))
+
+ # blocklists (little endian) describe the $coreimg_offset in sectors
+ local boot_record_blocklist="$(grub_blocklist_generate "$coreimg_offset")"
+ local coreimg_blocklist="$(grub_blocklist_generate "$coreimg_second_sector_offset")"
+
+ if [[ $coreimg_offset -gt 0 ]]; then
+ dd if=<(printf "$(grub_blocklist_format "$boot_record_blocklist")") \
+ of="$floppyimg" \
+ bs=1 \
+ seek="$boot_record_blocklist_offset" \
+ conv=notrunc
+
+ dd if=<(printf "$(grub_blocklist_format "$coreimg_blocklist")") \
+ of="$floppyimg" \
+ bs=1 \
+ seek="$coreimg_blocklist_offset" \
+ conv=notrunc
+ else
+ printf 1>&2 '%s\n' "Error: ${coreimg##*/} offset not found"
+
+ return 1
+ fi
+}