#!/usr/bin/env bash set -euo pipefail [[ $# -eq 4 ]] || { echo "usage: prepare-native-physical-once.sh " >&2 exit 64 } [[ ${EUID} -eq 0 ]] || { echo "must run as root" >&2 exit 77 } world_root=$(readlink -f "$1") candidate=$(readlink -f "$2") disk=$(readlink -f "$3") recovery_root=$(readlink -m "$4") source_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) render_root=$(mktemp -d) trap 'rm -rf "${render_root}"' EXIT [[ ${disk} == /dev/vda ]] grep -q '^node_id: BS-SH-005$' "${world_root}/CURRENT.hldp" /guanghu/bin/ghctl authorize "${world_root}" write_bootloader_and_system_partitions \ >/dev/null [[ $(stat -c %s "${candidate}") -eq 14848 ]] partition_dump=$(sfdisk -d "${disk}") grep -q '^label: gpt$' <<<"${partition_dump}" grep -q '^label-id: E549327B-8DC7-4797-944F-DC6185D1B550$' \ <<<"${partition_dump}" grep -Eq '^/dev/vda1 : start= *2048, size= *2048,' <<<"${partition_dump}" grep -Eq '^/dev/vda2 : start= *4096, size= *104853471,' <<<"${partition_dump}" mkdir -p "${recovery_root}" chmod 0700 "${recovery_root}" printf '%s\n' "${partition_dump}" >"${recovery_root}/sfdisk-before.txt" dd if="${disk}" of="${recovery_root}/first-2MiB.before.bin" \ bs=1M count=2 status=none disk_sectors=$(blockdev --getsz "${disk}") dd if="${disk}" of="${recovery_root}/last-2MiB.before.bin" \ bs=512 skip=$((disk_sectors - 4096)) count=4096 status=none dd if="${disk}" of="${recovery_root}/lba34-62.before.bin" \ bs=512 skip=34 count=29 status=none if ! cmp -s "${recovery_root}/lba34-62.before.bin" \ <(head -c 14848 /dev/zero); then echo "candidate sectors 34-62 are not empty" >&2 exit 65 fi dd if="${disk}" of="${recovery_root}/lba63.before.bin" \ bs=512 skip=63 count=1 status=none if ! cmp -s "${recovery_root}/lba63.before.bin" \ <(head -c 512 /dev/zero); then echo "native proof sector 63 is not empty" >&2 exit 65 fi "${source_root}/scripts/render-native-recovery-beacon.sh" "${render_root}" dd if="${disk}" of="${recovery_root}/lba68-69.before.bin" \ bs=512 skip=68 count=2 status=none if ! cmp -s "${recovery_root}/lba68-69.before.bin" \ <(head -c 1024 /dev/zero) && ! cmp -s "${recovery_root}/lba68-69.before.bin" \ "${render_root}/guanghu-recovery-clear.env"; then echo "native recovery beacon sectors 68-69 contain unknown data" >&2 exit 65 fi dd if="${disk}" of="${recovery_root}/lba70-71.before.bin" \ bs=512 skip=70 count=2 status=none if ! cmp -s "${recovery_root}/lba70-71.before.bin" \ <(head -c 1024 /dev/zero); then echo "native gestational index sectors 70-71 are not empty before first installation" >&2 exit 65 fi cp /boot/grub/grub.cfg "${recovery_root}/grub.cfg.before" cp /boot/grub/grubenv "${recovery_root}/grubenv.before" cp /etc/default/grub "${recovery_root}/default-grub.before" cp /etc/grub.d/40_custom "${recovery_root}/40_custom.before" tar -czf "${recovery_root}/etc-grub.d.before.tar.gz" -C /etc grub.d cp "${candidate}" "${recovery_root}/guanghu-os-physical-candidate.img" install -m 0755 /dev/stdin /etc/grub.d/41_guanghu_native_once <<'EOF' #!/bin/sh exec tail -n +3 $0 menuentry 'Guanghu OS native one-time proof' --id 'guanghu-native-once' { insmod chain chainloader (hd0)34+1 } EOF dd if="${render_root}/guanghu-recovery-clear.env" of="${disk}" \ bs=512 seek=68 count=2 conv=notrunc,fsync status=none install -m 0755 "${render_root}/08_guanghu_native_recovery" \ /etc/grub.d/08_guanghu_native_recovery update-grub >/dev/null grub-script-check /boot/grub/grub.cfg grep -q "load_env --file '(hd0)68+2' guanghu_recovery" /boot/grub/grub.cfg grep -q "menuentry 'Guanghu OS native one-time proof'.*'guanghu-native-once'" \ /boot/grub/grub.cfg dd if="${candidate}" of="${disk}" bs=512 seek=34 count=29 \ conv=notrunc,fsync status=none candidate_sha=$(sha256sum "${candidate}" | awk '{print $1}') readback_sha=$(dd if="${disk}" bs=512 skip=34 count=29 status=none | sha256sum | awk '{print $1}') [[ ${candidate_sha} == "${readback_sha}" ]] sha256sum "${recovery_root}"/* >"${recovery_root}/SHA256SUMS" chmod 0400 "${recovery_root}"/* observed_at=$(date --iso-8601=seconds) cat >"${recovery_root}/PREPARE-RECEIPT.hldp" <