diff options
author | Andrew Robbins <contact@andrewrobbins.info> | 2018-12-25 21:41:27 -0500 |
---|---|---|
committer | Andrew Robbins <contact@andrewrobbins.info> | 2018-12-25 21:41:27 -0500 |
commit | c9e5a6b91406fe0e1b8188c2818c5e2f7ad3e267 (patch) | |
tree | ed2e90f3927d0b3094121c42b338e38463057281 /projects | |
parent | 4f989bf93a6b8c1a6ce0f38adf47469cd58493e0 (diff) | |
download | librebootfr-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')
-rwxr-xr-x | projects/grub/grub-helper | 96 |
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 +} |