diff options
-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 +} |