Joakim Bech | 8b02ad7 | 2023-06-08 11:12:59 +0200 | [diff] [blame] | 1 | #!/usr/bin/env bash |
| 2 | # Helper script to make a SD-card image for the official OP-TEE Raspberry Pi 3 |
| 3 | # build. |
| 4 | |
| 5 | set -e |
| 6 | WORKDIR="" |
| 7 | |
| 8 | display_usage() { |
| 9 | echo "Usage: $0 [options]" |
| 10 | echo "Options:" |
| 11 | echo " -w|--workdir <dir> : The OP-TEE RPI3 working directory" |
| 12 | echo " -h|--help : Display this help message" |
| 13 | } |
| 14 | |
| 15 | while [[ $# -gt 0 ]]; do |
| 16 | key="$1" |
| 17 | case $key in |
| 18 | -w | --workdir) |
| 19 | WORKDIR="$2" |
| 20 | shift 2 |
| 21 | ;; |
| 22 | -h | --help) |
| 23 | display_usage |
| 24 | exit 0 |
| 25 | ;; |
| 26 | *) |
| 27 | echo "Invalid option: $1" |
| 28 | display_usage |
| 29 | exit 1 |
| 30 | ;; |
| 31 | esac |
| 32 | done |
| 33 | |
| 34 | # No point to continue if files/folders we depend on are not existing. |
| 35 | check_exist() { |
| 36 | local dir="$1" |
| 37 | if [ ! -e "${dir}" ]; then |
| 38 | echo "Folder ${dir} does not exist. Exiting..." |
| 39 | exit 1 |
| 40 | fi |
| 41 | } |
| 42 | |
| 43 | check_exist ${WORKDIR} |
| 44 | |
| 45 | IMAGE_FILE=${WORKDIR}/out/rpi3-sdcard.img |
| 46 | rm -f ${IMAGE_FILE} |
| 47 | |
| 48 | ################################################################################ |
| 49 | # Configuration |
| 50 | ################################################################################ |
| 51 | OFFSET_KIB=1024 |
| 52 | BOOT_PARTITION_SIZE_MB=64 |
| 53 | # ROOT FS size is read out from the rootfs file created by Buildroot, therefore |
| 54 | # we don't need to configure that here. |
| 55 | |
| 56 | ################################################################################ |
| 57 | # Image and partition generation |
| 58 | ################################################################################ |
| 59 | # In bytes, always 512, when creating msdos/MBR images. |
| 60 | SECTOR_SIZE=512 |
| 61 | |
| 62 | # 1. Compute the sector size for the offset to the first partition. |
| 63 | OFFSET_SECTOR_SIZE=$((OFFSET_KIB * 1024 / SECTOR_SIZE)) |
| 64 | echo "OFFSET_SECTOR_SIZE: $((OFFSET_KIB * 1024)) bytes ($((OFFSET_KIB / 1024))MB in ${OFFSET_SECTOR_SIZE} sectors)" |
| 65 | |
| 66 | # 2. Calculate the boot partition sizes. |
| 67 | BOOT_PARTITION_SIZE_KIB=$((BOOT_PARTITION_SIZE_MB * 1024)) |
| 68 | BOOT_PARTITION_SIZE_BYTES=$((BOOT_PARTITION_SIZE_KIB * 1024)) |
| 69 | BOOT_PARTITION_SECTOR_SIZE=$((BOOT_PARTITION_SIZE_BYTES / SECTOR_SIZE)) |
| 70 | echo "BOOT PARTITION SIZE: ${BOOT_PARTITION_SIZE_BYTES} bytes ($(($BOOT_PARTITION_SIZE_BYTES / 1024 / 1024))MB in ${BOOT_PARTITION_SECTOR_SIZE} sectors)" |
| 71 | |
| 72 | # 3. Find out the size of the rootfs produced by Buildroot and calculate the |
| 73 | # rootfs partition sizes. |
| 74 | ROOTFS_IMG=${WORKDIR}/out-br/images/rootfs.ext2 |
| 75 | check_exist ${ROOTFS_IMG} |
| 76 | ROOTFS_SIZE_BYTES=$(stat -c %s ${ROOTFS_IMG}) |
| 77 | ROOTFS_SECTOR_SIZE=$((ROOTFS_SIZE_BYTES / SECTOR_SIZE)) |
| 78 | echo "ROOTFS PARTITION SIZE: ${ROOTFS_SIZE_BYTES} bytes ($((ROOTFS_SIZE_BYTES / 1024 / 1024))MB in ${ROOTFS_SECTOR_SIZE} sectors)" |
| 79 | |
| 80 | # 4. Compute the images size, based on the rootfs size, the |
| 81 | # desired boot image size and the offset to the first partition. |
| 82 | IMG_SECTOR_SIZE=$((OFFSET_SECTOR_SIZE + BOOT_PARTITION_SECTOR_SIZE + ROOTFS_SECTOR_SIZE)) |
| 83 | IMG_SIZE_KIB=$((IMG_SECTOR_SIZE * SECTOR_SIZE / 1024)) |
| 84 | echo "TOTAL IMAGE SIZE: ${IMG_SIZE_KIB} bytes ($((IMG_SIZE_KIB / 1024))MB in ${IMG_SECTOR_SIZE} sectors)" |
| 85 | |
| 86 | # Create empty disk image |
| 87 | truncate -s ${IMG_SIZE_KIB}KiB ${IMAGE_FILE} |
| 88 | |
| 89 | parted -s ${IMAGE_FILE} unit kiB mklabel msdos |
| 90 | parted -a optimal ${IMAGE_FILE} unit kiB mkpart primary fat16 ${OFFSET_KIB} ${BOOT_PARTITION_SIZE_KIB} |
| 91 | parted -a optimal ${IMAGE_FILE} set 1 boot on |
| 92 | parted -a optimal ${IMAGE_FILE} unit kiB mkpart primary ext4 $((OFFSET_KIB + BOOT_PARTITION_SIZE_KIB)) 100% |
| 93 | |
| 94 | # Show some useful information about the image we just created. |
| 95 | echo "" |
| 96 | fdisk -l ${IMAGE_FILE} |
| 97 | |
| 98 | ################################################################################ |
| 99 | # Copy the ext2 partition from Buildroot to the second partition. |
| 100 | ################################################################################ |
| 101 | dd if=${ROOTFS_IMG} of=${IMAGE_FILE} bs=${SECTOR_SIZE} seek=$((OFFSET_SECTOR_SIZE + BOOT_PARTITION_SECTOR_SIZE)) conv=notrunc,fsync |
| 102 | |
| 103 | ################################################################################ |
| 104 | # Create the boot image and copy it to the boot partition |
| 105 | ################################################################################ |
| 106 | GENIMAGE=${WORKDIR}/out-br/host/bin/genimage |
| 107 | check_exist ${GENIMAGE} |
| 108 | |
| 109 | # Used for a temporary genimage config file. |
| 110 | RPI3_GENIMAGE_CFG=$(mktemp) |
| 111 | |
| 112 | # Used for temporarily storing files when creating the boot vfat image. |
| 113 | RPI3_GENIMAGE_TMPPATH=$(mktemp -d) |
| 114 | echo "RPI3_GENIMAGE_CFG: ${RPI3_GENIMAGE_CFG}" |
| 115 | echo "RPI3_GENIMAGE_TMPPATH: ${RPI3_GENIMAGE_TMPPATH}" |
| 116 | |
| 117 | trap "rm -rf ${RPI3_GENIMAGE_CFG} ${RPI3_GENIMAGE_TMPPATH}" EXIT |
| 118 | |
| 119 | BOOT_PARTITION_FILES=${WORKDIR}/out/boot |
| 120 | check_exist ${BOOT_PARTITION_FILES} |
| 121 | |
| 122 | # Create the config file for genimage on the fly. |
| 123 | cat <<EOF >${RPI3_GENIMAGE_CFG} |
| 124 | image boot.vfat { |
| 125 | vfat { |
| 126 | } |
| 127 | |
| 128 | size = ${BOOT_PARTITION_SIZE_MB}M |
| 129 | mountpoint = "/" |
| 130 | } |
| 131 | EOF |
| 132 | |
| 133 | # Create the boot.vfat image. |
| 134 | ${GENIMAGE} --rootpath ${BOOT_PARTITION_FILES} --config ${RPI3_GENIMAGE_CFG} --tmppath=${RPI3_GENIMAGE_TMPPATH} --outputpath=${WORKDIR}/out |
| 135 | |
| 136 | # Copy the contents of boot.vfat to the boot partition in the image we prepared. |
| 137 | dd if=${WORKDIR}/out/boot.vfat of=${IMAGE_FILE} bs=${SECTOR_SIZE} seek=${OFFSET_SECTOR_SIZE} conv=notrunc,fsync |