hololake-system-architecture/product-source/hololake-platform/guanghu-os/scripts/prepare-native-physical-once.sh

146 lines
5.1 KiB
Shell
Executable file

#!/usr/bin/env bash
set -euo pipefail
[[ $# -eq 4 ]] || {
echo "usage: prepare-native-physical-once.sh <world-root> <candidate-image> <disk> <recovery-root>" >&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" <<EOF
schema: guanghu.native-physical-prepare/v1
receipt_id: GH-OS-LAB-001-NATIVE-PHYSICAL-PREPARE-001
status: VERIFIED
observed_at: ${observed_at}
node_id: BS-SH-005
instance_id: lhins-14w5y3ce
disk:
path: /dev/vda
candidate_start_lba: 34
candidate_sector_count: 29
proof_lba: 63
recovery_beacon_lba_start: 68
recovery_beacon_sector_count: 2
gestational_index_lba_start: 70
gestational_index_sector_count: 2
existing_partition_start_lba: 2048
candidate:
sha256: ${candidate_sha}
readback_sha256: ${readback_sha}
grub:
entry_id: guanghu-native-once
recovery_protocol: GHNRP
recovery_raw_blocklist: (hd0)68+2
armed: false
recovery:
directory: ${recovery_root}
first_2mib_backed_up: true
last_2mib_backed_up: true
partition_table_backed_up: true
grub_configuration_backed_up: true
proof_sector_backed_up: true
recovery_beacon_backed_up: true
gestational_index_backed_up: true
next_action: ARM_ONE_TIME_ENTRY_AND_REBOOT
EOF
chmod 0400 "${recovery_root}/PREPARE-RECEIPT.hldp"
cat "${recovery_root}/PREPARE-RECEIPT.hldp"