#!/usr/bin/env bash # Partition a whole disk with a bringup-oriented Android GBL GPT layout. # # Usage: # sudo ./partition_gbl_disk.sh [--efi /path/to/BOOTAA64.EFI] /dev/sdX # # Optional environment overrides: # SUPER_SIZE=8G ./partition_gbl_disk.sh /dev/sdX # # The script intentionally asks for confirmation once before touching the disk. set -euo pipefail ESP_SIZE="${ESP_SIZE:-8M}" MISC_SIZE="${MISC_SIZE:-4M}" BOOT_SIZE="${BOOT_SIZE:-128M}" VENDOR_BOOT_SIZE="${VENDOR_BOOT_SIZE:-128M}" INIT_BOOT_SIZE="${INIT_BOOT_SIZE:-8M}" VBMETA_SIZE="${VBMETA_SIZE:-4M}" DTBO_SIZE="${DTBO_SIZE:-32M}" SUPER_SIZE="${SUPER_SIZE:-8G}" METADATA_SIZE="${METADATA_SIZE:-64M}" die() { echo "error: $*" >&2 exit 1 } usage() { cat >&2 </dev/null 2>&1 || die "missing required command: $1" } cleanup() { if [[ -n "${ESP_A_MNT:-}" && -d "${ESP_A_MNT:-}" ]]; then umount "$ESP_A_MNT" 2>/dev/null || true rmdir "$ESP_A_MNT" 2>/dev/null || true fi if [[ -n "${ESP_B_MNT:-}" && -d "${ESP_B_MNT:-}" ]]; then umount "$ESP_B_MNT" 2>/dev/null || true rmdir "$ESP_B_MNT" 2>/dev/null || true fi if [[ -n "${SFDISK_SCRIPT:-}" ]]; then rm -f "$SFDISK_SCRIPT" fi } partition_path() { local disk="$1" local number="$2" case "$disk" in *[0-9]) printf '%sp%s\n' "$disk" "$number" ;; *) printf '%s%s\n' "$disk" "$number" ;; esac } EFI_PAYLOAD="" ARGS=() while [[ $# -gt 0 ]]; do case "$1" in --efi) [[ $# -ge 2 ]] || die "--efi requires a file path" EFI_PAYLOAD="$2" shift 2 ;; -h | --help) usage exit 0 ;; --) shift ARGS+=("$@") break ;; -*) die "unknown argument: $1" ;; *) ARGS+=("$1") shift ;; esac done [[ ${#ARGS[@]} -eq 1 ]] || { usage exit 2 } DISK="${ARGS[0]}" [[ $EUID -eq 0 ]] || die "run as root, for example: sudo $0 $DISK" [[ -b "$DISK" ]] || die "$DISK is not a block device" if [[ -n "$EFI_PAYLOAD" ]]; then [[ -f "$EFI_PAYLOAD" ]] || die "--efi payload does not exist or is not a regular file: $EFI_PAYLOAD" fi require_cmd sfdisk require_cmd lsblk require_cmd findmnt if [[ -n "$EFI_PAYLOAD" ]]; then require_cmd mount require_cmd umount require_cmd mkfs.vfat fi if [[ "$(lsblk -dn -o TYPE "$DISK")" != "disk" ]]; then die "$DISK is not a whole disk according to lsblk" fi if findmnt --source "$DISK" >/dev/null 2>&1; then die "$DISK itself is mounted; unmount it first" fi while read -r child; do [[ -n "$child" ]] || continue if findmnt --source "$child" >/dev/null 2>&1; then die "$child is mounted; unmount all partitions on $DISK first" fi done < <(lsblk -nrpo NAME "$DISK" | tail -n +2) cat <"$SFDISK_SCRIPT" </dev/null 2>&1; then partprobe "$DISK" || true fi if command -v udevadm >/dev/null 2>&1; then udevadm settle || true fi blockdev --rereadpt "$DISK" 2>/dev/null || true ESP_A="$(partition_path "$DISK" 1)" ESP_B="$(partition_path "$DISK" 2)" if command -v mkfs.fat >/dev/null 2>&1; then echo "Formatting Android ESP partitions as FAT32..." mkfs.vfat -n EFI "$ESP_A" mkfs.vfat -n EFI "$ESP_B" else echo "warning: mkfs.fat not found; format $ESP_A and $ESP_B as FAT32 manually" >&2 fi if [[ -n "$EFI_PAYLOAD" ]]; then echo "Copying GBL EFI payload to Android ESP partitions..." ESP_A_MNT="$(mktemp -d /tmp/gbl-esp-a.XXXXXX)" ESP_B_MNT="$(mktemp -d /tmp/gbl-esp-b.XXXXXX)" mount "$ESP_A" "$ESP_A_MNT" mount "$ESP_B" "$ESP_B_MNT" mkdir -p "$ESP_A_MNT/EFI/BOOT" mkdir -p "$ESP_B_MNT/EFI/BOOT" cp "$EFI_PAYLOAD" "$ESP_A_MNT/EFI/BOOT/BOOTAA64.EFI" cp "$EFI_PAYLOAD" "$ESP_B_MNT/EFI/BOOT/BOOTAA64.EFI" sync umount "$ESP_A_MNT" umount "$ESP_B_MNT" rmdir "$ESP_A_MNT" "$ESP_B_MNT" ESP_A_MNT="" ESP_B_MNT="" fi echo echo "Done. Resulting partition table:" sfdisk -d "$DISK" echo if [[ -n "$EFI_PAYLOAD" ]]; then echo "GBL EFI payload copied to both ESPs as /EFI/BOOT/BOOTAA64.EFI." else echo "Copy GBL to both ESPs as /EFI/BOOT/BOOTAA64.EFI before booting." fi