95 lines
3 KiB
Shell
95 lines
3 KiB
Shell
|
|
#!/usr/bin/env bash
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
[[ $# -eq 3 ]] || {
|
||
|
|
echo "usage: test-native-physical-probe.sh <candidate-image> <probe-stage> <receipt-output>" >&2
|
||
|
|
exit 64
|
||
|
|
}
|
||
|
|
|
||
|
|
candidate=$(readlink -f "$1")
|
||
|
|
probe_stage=$2
|
||
|
|
receipt=$(readlink -m "$3")
|
||
|
|
[[ ${probe_stage} =~ ^[1-9]$ ]]
|
||
|
|
source_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||
|
|
native_root=${source_root}/native/x86_64-bios
|
||
|
|
test_root=$(mktemp -d)
|
||
|
|
serial_log=${test_root}/serial.log
|
||
|
|
disk_image=${test_root}/physical-probe.img
|
||
|
|
block_image=${test_root}/virtio-block.img
|
||
|
|
trap 'rm -rf "${test_root}"' EXIT
|
||
|
|
|
||
|
|
truncate -s 2M "${disk_image}"
|
||
|
|
truncate -s 8M "${block_image}"
|
||
|
|
nasm -f bin "${native_root}/physical-test-mbr.asm" \
|
||
|
|
-o "${test_root}/physical-test-mbr.bin"
|
||
|
|
dd if="${test_root}/physical-test-mbr.bin" of="${disk_image}" \
|
||
|
|
bs=512 seek=0 conv=notrunc status=none
|
||
|
|
dd if="${candidate}" of="${disk_image}" \
|
||
|
|
bs=512 seek=34 conv=notrunc status=none
|
||
|
|
|
||
|
|
set +e
|
||
|
|
timeout 20 qemu-system-x86_64 \
|
||
|
|
-machine pc,accel=tcg \
|
||
|
|
-m 64M \
|
||
|
|
-drive "format=raw,file=${disk_image}" \
|
||
|
|
-drive "if=none,id=ghblk,format=raw,file=${block_image}" \
|
||
|
|
-device virtio-blk-pci,drive=ghblk,disable-modern=on \
|
||
|
|
-netdev user,id=ghnet \
|
||
|
|
-device virtio-net-pci,netdev=ghnet,disable-modern=on,mac=52:54:00:26:71:98 \
|
||
|
|
-display none \
|
||
|
|
-monitor none \
|
||
|
|
-serial "file:${serial_log}" \
|
||
|
|
-device isa-debug-exit,iobase=0xf4,iosize=0x04
|
||
|
|
qemu_status=$?
|
||
|
|
set -e
|
||
|
|
|
||
|
|
[[ ${qemu_status} -eq 33 ]]
|
||
|
|
grep -q '^GHOS_NATIVE_KERNEL_ENTERED=true' "${serial_log}"
|
||
|
|
grep -q '^GHOS_DISK_PROOF_WRITTEN=LBA63' "${serial_log}"
|
||
|
|
grep -q '^GHOS_DISK_PROOF_OBSERVED_AFTER_RESET=LBA63' "${serial_log}"
|
||
|
|
python3 - "${disk_image}" "${probe_stage}" <<'PY'
|
||
|
|
import pathlib
|
||
|
|
import sys
|
||
|
|
|
||
|
|
disk = pathlib.Path(sys.argv[1]).read_bytes()
|
||
|
|
stage = int(sys.argv[2])
|
||
|
|
proof = disk[63 * 512:64 * 512]
|
||
|
|
assert proof[0] == 0xA5
|
||
|
|
assert proof[1:].startswith(b"GHOS_NATIVE_LONG64_DISK_PROOF\x00")
|
||
|
|
assert proof[42] == 0x80 + stage
|
||
|
|
assert proof[43] == 0
|
||
|
|
assert proof[32:34] == bytes([1, 1])
|
||
|
|
assert int.from_bytes(proof[50:52], "little") > 0
|
||
|
|
assert int.from_bytes(proof[52:54], "little") > 0
|
||
|
|
if stage >= 5:
|
||
|
|
assert proof[36:42] == bytes.fromhex("525400267198")
|
||
|
|
if stage >= 6:
|
||
|
|
assert int.from_bytes(proof[44:46], "little") > 0
|
||
|
|
if stage >= 7:
|
||
|
|
assert int.from_bytes(proof[46:48], "little") > 0
|
||
|
|
assert proof[34] == 1
|
||
|
|
if stage >= 9:
|
||
|
|
assert int.from_bytes(proof[48:50], "little") > 0
|
||
|
|
assert proof[35] == 1
|
||
|
|
PY
|
||
|
|
|
||
|
|
observed_at=$(date --iso-8601=seconds)
|
||
|
|
image_sha=$(sha256sum "${candidate}" | awk '{print $1}')
|
||
|
|
cat >"${receipt}" <<EOF
|
||
|
|
schema: guanghu.ghal-physical-probe-test/v1
|
||
|
|
receipt_id: GH-OS-LAB-001-GHAL-PROBE-${probe_stage}-QEMU
|
||
|
|
status: VERIFIED
|
||
|
|
observed_at: ${observed_at}
|
||
|
|
probe_stage: ${probe_stage}
|
||
|
|
image_sha256: ${image_sha}
|
||
|
|
proof:
|
||
|
|
flag: 0xa5
|
||
|
|
completion_stage: 0x8${probe_stage}
|
||
|
|
disk_lba: 63
|
||
|
|
disk_receipt_observed_after_reset: true
|
||
|
|
acceptance:
|
||
|
|
qemu_probe_return: true
|
||
|
|
physical_server_probe: false
|
||
|
|
next_action: RUN_ONE_TIME_PHYSICAL_PROBE_STAGE_${probe_stage}
|
||
|
|
EOF
|
||
|
|
cat "${serial_log}" >>"${receipt}.serial.log"
|