blob: 413178b9308a44982ddfd06bad39ab62df55ffab [file] [log] [blame] [edit]
#!/bin/bash
set -o errexit
set -o pipefail
set -o nounset
# Script to generate kernelefi.img and shimefi.img.
#
# kernelefi.img uses a kernel from cos-125-19216-104-133 and shimefi.img uses a
# shim from the same COS image.
#
# e.g.:
# bash create_efi_gpt.sh kernelefi.img bzImage 2 /efi/boot/bootx64.efi
# bash create_efi_gpt.sh shimefi.img shimx64.efi 2 /efi/boot/bootx64.efi
if [[ $# -ne 4 ]]; then
echo "Usage: $0 <output_image_path> <bootx64_efi_source> <priority_partition> <efi_internal_path>"
echo "Example efi_internal_path: /efi/boot/bootx64.efi"
exit 1
fi
readonly OUTPUT_IMAGE="$1"
readonly BOOT_SOURCE="$2"
readonly PRIORITY_PART="$3"
readonly EFI_INTERNAL_PATH="$4"
readonly EFI_PART_IMAGE="efi_part.img"
# 1. Calculate required size for the partition
SOURCE_SIZE=$(stat -c%s "$BOOT_SOURCE")
# Add overhead for FAT metadata (at least 512KB for small files, total min 1MB)
EFI_SIZE_BYTES=$((SOURCE_SIZE + 512 * 1024))
if [[ $EFI_SIZE_BYTES -lt $((1024 * 1024)) ]]; then
EFI_SIZE_BYTES=$((1024 * 1024))
fi
# Align partition size to 512-byte sectors
PART_SIZE_SECTORS=$(( (EFI_SIZE_BYTES + 511) / 512 ))
# 2. Create the FAT image
truncate -s "$((PART_SIZE_SECTORS * 512))" "$EFI_PART_IMAGE"
mkfs.vfat "$EFI_PART_IMAGE"
# 3. Create directory structure and copy the EFI file
# Ensure leading ::/ for mtools
INTERNAL_PATH_MTOOLS="::${EFI_INTERNAL_PATH#/}"
DIR_PATH=$(dirname "${EFI_INTERNAL_PATH}")
# Recursively create directories
IFS='/' read -ra ADDR <<< "$DIR_PATH"
CURRENT_DIR="::"
for i in "${ADDR[@]}"; do
if [[ -n "$i" ]]; then
CURRENT_DIR="${CURRENT_DIR}/$i"
# mmd might fail if directory exists, so we ignore error.
mmd -i "$EFI_PART_IMAGE" "$CURRENT_DIR" || true
fi
done
mcopy -i "$EFI_PART_IMAGE" "$BOOT_SOURCE" "$INTERNAL_PATH_MTOOLS"
# 4. Define GPT layout
# Start at sector 2048 (1MiB) for alignment compatibility and to avoid
# "sector already used" errors with some versions of sfdisk.
readonly START_SECTOR=2048
# Backup GPT is 33 sectors at the end.
# sfdisk by default aligns partitions to 1MiB (2048 sectors).
# We add enough sectors to account for alignment of partitions 2, 3, and 4.
TOTAL_SECTORS=$(( START_SECTOR + PART_SIZE_SECTORS + 3 * 2048 + 33 ))
# 5. Create the final container
truncate -s "$((TOTAL_SECTORS * 512))" "$OUTPUT_IMAGE"
# 6. Initialize GPT and create the partitions
# Partition 1: EFI System Partition GUID: C12A7328-F81F-11D2-BA4B-00A0C93EC93B
# Partition 2: ChromeOS Kernel GUID: FE3A2A5D-4F32-41A7-B725-ACCC3285A309
# Partition 3: ChromeOS Root GUID: 3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC
# Partition 4: ChromeOS Kernel GUID: FE3A2A5D-4F32-41A7-B725-ACCC3285A309
echo "label: gpt
start=${START_SECTOR}, size=${PART_SIZE_SECTORS}, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, name=\"EFI-SYSTEM\"
size=1, type=FE3A2A5D-4F32-41A7-B725-ACCC3285A309, name=\"KERN-A\"
size=1, type=3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC, name=\"ROOT-A\"
size=1, type=FE3A2A5D-4F32-41A7-B725-ACCC3285A309, name=\"KERN-B\"" | sfdisk --no-reread "$OUTPUT_IMAGE"
cgpt prioritize -i "$PRIORITY_PART" -P 2 "$OUTPUT_IMAGE"
# 7. DD the EFI partition into the GPT image
dd if="$EFI_PART_IMAGE" of="$OUTPUT_IMAGE" bs=512 seek="${START_SECTOR}" conv=notrunc status=none
# Cleanup
rm "$EFI_PART_IMAGE"
echo "Successfully created minimal GPT image: $OUTPUT_IMAGE ($((TOTAL_SECTORS * 512 / 1024)) KiB)"