aboutsummaryrefslogtreecommitdiff
path: root/projects/grub
diff options
context:
space:
mode:
Diffstat (limited to 'projects/grub')
-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
+}