#!/bin/bash # Partition alignment value in bytes. declare -i partition_alignment # Boot partition storage offset in bytes. declare -i vfat_storage_offset PART_ALIGN_4MB=4194304 PART_ALIGN_8MB=8388608 # Default 'data' partition size in MiB. declare -i data_part_size_mb # Default total storage size in MiB. declare -i storage_total_size_mb DATA_PART_SIZE_MB=128 STORAGE_TOTAL_SIZE_MB=8000 # Number of required heads in a final image. declare -i -r heads=255 # Number of required sectors in a final image. declare -i -r sectors=63 declare -a mender_partitions_regular=('boot' 'primary' 'secondary' 'data') declare -a mender_partitions_extended=('boot' 'primary' 'secondary' 'n/a' 'data' 'swap') declare -a raw_disk_partitions=('boot' 'rootfs') declare -A raw_disk_sizes declare -A mender_disk_sizes tool_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" files_dir=${tool_dir}/files output_dir=${tool_dir}/output integration_dir=${tool_dir}/integration build_log=${output_dir}/build.log embedded_base_dir=$output_dir/embedded sdimg_base_dir=$output_dir/sdimg embedded_boot_dir=$embedded_base_dir/boot embedded_rootfs_dir=$embedded_base_dir/rootfs sdimg_boot_dir=$sdimg_base_dir/boot sdimg_primary_dir=$sdimg_base_dir/primary sdimg_secondary_dir=$sdimg_base_dir/secondary sdimg_data_dir=$sdimg_base_dir/data logsetup() { [ ! -f $build_log ] && { touch $build_log; } echo -n "" > $build_log exec > >(tee -a $build_log) exec 2>&1 } log() { echo -e "$*" } # Takes following arguments: # # $1 -relative file path get_path() { echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")" } get_part_number_from_device() { case "$1" in /dev/*[0-9]p[1-9]) echo ${1##*[0-9]p} ;; /dev/[sh]d[a-z][1-9]) echo ${1##*d[a-z]} ;; ubi[0-9]_[0-9]) echo ${1##*[0-9]_} ;; [a-z]*\.sdimg[1-9]) echo ${1##*\.sdimg} ;; /dev/mapper/*[0-9]p[1-9]) echo ${1##*[0-9]p} ;; *) log "Could not determine partition number from $1" exit 1 ;; esac } # Takes following arguments: # # $1 - raw disk image # $2 - boot partition start offset (in sectors) # $3 - boot partition size (in sectors) create_single_disk_partition_table() { local device=$1 local bootstart=$2 local stopsector=$(( $3 - 1 )) sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' << EOF | sudo fdisk $device &> /dev/null d # delete partition n # new partition p # primary partition 1 # partion number 1 ${bootstart} +${stopsector} a # set boot flag w # write the partition table q # and we're done EOF } # Takes following arguments: # # $1 - raw disk image # $2 - root filesystem partition start offset (in sectors) # $3 - root filesystem partition size (in sectors) create_double_disk_partition_table() { local device=$1 local rootfsstart=$2 local rootfsstop=$(( $3 - 1 )) sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' << EOF | sudo fdisk $device &> /dev/null d # delete partition 2 n p 2 ${rootfsstart} +${rootfsstop} w # write the partition table q # and we're done EOF } # Takes following arguments: # # $1 - raw_disk image path # # Calculates following values: # # $2 - number of partitions # $3 - array of partitions' sizes for raw disk # get_raw_disk_sizes() { local limage=$1 local rvar_count=$2 shift 2 local rvar_array=($@) local lsubname=${limage:0:10} local lfdisk="$(fdisk -u -l ${limage})" local lparts=($(echo "${lfdisk}" | grep "^${lsubname}" | cut -d' ' -f1)) local lcount=${#lparts[@]} if [[ $lcount -gt 3 ]]; then log "\tError: invalid/unsupported raw disk image. Aborting." return 1 fi local lsectorsize=($(echo "${lfdisk}" | grep '^Sector' | cut -d' ' -f4)) local idx_start=2 local idx_size=4 local lfirstpartinfo="$(echo "${lfdisk}" | grep "^${lparts[0]}")" if [[ $lcount -gt 1 ]]; then local lsecondpartinfo="$(echo "${lfdisk}" | grep "^${lparts[1]}")" eval $rvar_array[prootfs_start]="'$(echo "${lsecondpartinfo}" | tr -s ' ' | cut -d' ' -f${idx_start})'" eval $rvar_array[prootfs_size]="'$(echo "${lsecondpartinfo}" | tr -s ' ' | cut -d' ' -f${idx_size})'" fi if [[ $lcount -gt 2 ]]; then local lthirdpartinfo="$(echo "${lfdisk}" | grep "^${lparts[2]}")" eval $rvar_array[pswap_start]="'$(echo "${lthirdpartinfo}" | tr -s ' ' | cut -d' ' -f${idx_start})'" eval $rvar_array[pswap_size]="'$(echo "${lthirdpartinfo}" | tr -s ' ' | cut -d' ' -f${idx_size})'" fi # Check is first partition is marked as bootable. if [[ "$lfirstpartinfo" =~ .*\*.* ]]; then ((idx_start+=1)) ((idx_size+=1)) fi eval $rvar_array[pboot_start]="'$(echo "${lfirstpartinfo}" | tr -s ' ' | cut -d' ' -f${idx_start})'" eval $rvar_array[pboot_size]="'$(echo "${lfirstpartinfo}" | tr -s ' ' | cut -d' ' -f${idx_size})'" eval $rvar_array[sector_size]="'$lsectorsize'" eval $rvar_count="'$lcount'" return 0 } # Takes the following argument # $1 - device type # # Calculates the following arguments: # $2 - partition alignment # $3 - vfat storage offset set_mender_disk_alignment() { local rvar_partition_alignment=$2 local rvar_vfat_storage_offset=$3 case "$1" in "beaglebone" | "qemux86_64") local lvar_partition_alignment=${PART_ALIGN_8MB} local lvar_vfat_storage_offset=$lvar_partition_alignment ;; "raspberrypi3" | "raspberrypi0w" | "rockpro64") local lvar_partition_alignment=${PART_ALIGN_4MB} local lvar_uboot_env_size=$(( $lvar_partition_alignment * 2 )) local lvar_vfat_storage_offset=$(( $lvar_partition_alignment + $lvar_uboot_env_size )) ;; *) log "Error: unsupported device type $1" exit 1 ;; esac eval $rvar_partition_alignment="'$lvar_partition_alignment'" eval $rvar_vfat_storage_offset="'$lvar_vfat_storage_offset'" } # Takes following arguments: # # $1 - Mender disk image path # # Calculates following values: # # $2 - number of partitions # $3 - size of the sector (in bytes) # $4 - rootfs A partition start offset (in sectors) # $5 - rootfs A partition size (in sectors) # $6 - rootfs B partition start offset (in sectors) # $7 - rootfs B partition size (in sectors) get_mender_disk_sizes() { local limage=$1 local rvar_count=$2 local rvar_sectorsize=$3 local rvar_rootfs_a_start=$4 local rvar_rootfs_a_size=$5 local rvar_rootfs_b_start=$6 local rvar_rootfs_b_size=$7 local lsubname=${limage:0:10} local lfdisk="$(fdisk -u -l ${limage})" local lparts=($(echo "${lfdisk}" | grep "^${lsubname}" | cut -d' ' -f1)) local lcount=${#lparts[@]} if [[ $lcount -ne 4 ]] && [[ $lcount -ne 6 ]]; then log "Error: invalid Mender disk image. Aborting." return 1 else local lsectorsize=($(echo "${lfdisk}" | grep '^Sector' | cut -d' ' -f4)) local lrootfs_a_info="$(echo "${lfdisk}" | grep "^${lparts[1]}")" local lrootfs_b_info="$(echo "${lfdisk}" | grep "^${lparts[2]}")" idx_start=2 idx_size=4 local lrootfs_a_start=($(echo "${lrootfs_a_info}" | tr -s ' ' | cut -d' ' -f${idx_start})) local lrootfs_a_size=($(echo "${lrootfs_a_info}" | tr -s ' ' | cut -d' ' -f${idx_size})) local lrootfs_b_start=($(echo "${lrootfs_b_info}" | tr -s ' ' | cut -d' ' -f${idx_start})) local lrootfs_b_size=($(echo "${lrootfs_b_info}" | tr -s ' ' | cut -d' ' -f${idx_size})) eval $rvar_count="'$lcount'" eval $rvar_sectorsize="'$lsectorsize'" eval $rvar_rootfs_a_start="'$lrootfs_a_start'" eval $rvar_rootfs_a_size="'$lrootfs_a_size'" eval $rvar_rootfs_b_start="'$lrootfs_b_start'" eval $rvar_rootfs_b_size="'$lrootfs_b_size'" return 0 fi } # Takes following arguments: # # $1 - size variable to be aligned in sectors # $2 - size of the sector # align_partition_size() { # Final size is aligned with reference to 'partition_alignment' variable. local rvar_size=$1 local -n ref=$1 local size_in_bytes=$(( $ref * $2 )) local reminder=$(( ${size_in_bytes} % ${partition_alignment} )) if [ $reminder -ne 0 ]; then size_in_bytes=$(( $size_in_bytes - $reminder + ${partition_alignment} )) fi local lsize=$(( $size_in_bytes / $2 )) eval $rvar_size="'$lsize'" } # Takes following arguments: # # $1 - number of partition of the raw disk image # $2 - mender image partition alignment # $3 - mender image's boot partition offset # $4 - data partition size (in MB) # $5 - array of partitions' sizes for raw image # # Returns: # # $6 - array of partitions' sizes for Mender image # set_mender_disk_sizes() { local count=$1 local alignment=$2 local offset=$3 local datasize_mb=$4 local _raw_sizes=$(declare -p $5) eval "declare -A raw_sizes="${_raw_sizes#*=} shift 5 local rvar_array=($@) local sector_size=${raw_sizes[sector_size]} local datasize=$(( ($datasize_mb * 1024 * 1024) / $sector_size )) local bootstart= local bootsize= local rootfsstart= local rootfssize= local bootflag= if [[ $count -eq 1 ]]; then # Default size of the boot partition: 16MiB. bootsize=$(( (${alignment} * 2) / ${sector_size} )) # Root filesystem size is determined by the size of the single partition. rootfssize=${raw_sizes[pboot_size]} else bootsize=${raw_sizes[pboot_size]} rootfssize=${raw_sizes[prootfs_size]} fi # Boot partition storage offset is defined from the top down. bootstart=$(( ${offset} / ${sector_size} )) align_partition_size bootsize $sector_size align_partition_size rootfssize $sector_size align_partition_size datasize $sector_size eval $rvar_array[pboot_start]="'$bootstart'" eval $rvar_array[pboot_size]="'$bootsize'" eval $rvar_array[prootfs_size]="'$rootfssize'" eval $rvar_array[pdata_size]="'$datasize'" if [[ $count -eq 3 ]]; then # Add space for Swap partition. local swapsize=${raw_sizes[pswap_size]} align_partition_size swapsize $sector_size eval $rvar_array[pswap_size]="'$swapsize'" fi eval $rvar_array[sector_size]="'$sector_size'" } # Takes following arguments: # # $1 - partition alignment # $2 - array of partitions' sizes for Mender image # # Returns: # # #3 - number of partitions of the Mender disk image # $4 - final Mender disk image size (in bytes) # calculate_mender_disk_size() { local _mender_sizes=$(declare -p $2) eval "declare -A mender_sizes="${_mender_sizes#*=} local sector_size=${mender_sizes[sector_size]} local rvar_counts=$3 local rvar_sdimgsize=$4 local sdimgsize=$(( (${mender_sizes[pboot_start]} + ${mender_sizes[pboot_size]} + \ 2 * ${mender_sizes[prootfs_size]} + \ ${mender_sizes[pdata_size]}) * $sector_size )) eval $rvar_counts="'4'" if [ -v mender_sizes[pswap_size] ]; then log "\tSwap partition found." # Add size of the swap partition to the total size. sdimgsize=$(( $sdimgsize + (${mender_sizes[pswap_size]} * $sector_size) )) # Add alignment used as swap partition offset. sdimgsize=$(( $sdimgsize + 2 * ${1} )) eval $rvar_counts="'6'" fi eval $rvar_sdimgsize="'$sdimgsize'" } # Takes following arguments: # # $1 - number of partition of the Mender image # $2 - calculated total size of the Mender image in bytes # $3 - expected total size of the Mender image in mb # $4 - array of partitions' sizes for Mender image # # Returns: # # Size of the rootfs partition updated and adjusted to total storage size # mender_image_size_to_total_storage_size() { local count=$1 local rvar_image_size=$2 local -n image_size_bytes=$2 local storage_size_mb=$3 local _mender_sizes=$(declare -p $4) eval "declare -A mender_sizes="${_mender_sizes#*=} shift 3 local rvar_array=($@) local image_size_mb=$(( (($image_size_bytes / 1024) / 1024) )) log "\tAdjust Mender disk image size to the total storage size (${storage_size_mb}MB)." if [ $image_size_mb -gt $storage_size_mb ]; then log "\tDefined total storage size of ${3}MB is too small." log "\tMinimal required storage is ${image_size_mb}MB. Aborting." return 1 elif [ $image_size_mb -eq $storage_size_mb ]; then # Simply continue. log "\tCalculated Mender image size exactly fits the defined total storage." return 0 fi # Get spare space for rootfs a/b partitions (in sectors). local sector_size=${mender_sizes[sector_size]} local image_size_s=$(( $image_size_bytes / $sector_size )) local storage_size_bytes=$(( ($storage_size_mb * 1024 * 1024) )) local storage_size_s=$(( $storage_size_bytes / $sector_size )) local rootfs_overplus_bytes=0 local spare_storage_bytes=$(( $storage_size_bytes - $image_size_bytes )) if [ $(($spare_storage_bytes % 2)) -ne 0 ]; then log "\tAdditional space for rootfs partitions not divisible by 2.\ \n\tFinal image will be smaller than ${storage_size_mb}MB" fi rootfs_overplus_bytes=$(( $spare_storage_bytes / 2 )) local reminder=$(( ${rootfs_overplus_bytes} % ${partition_alignment} )) if [ $reminder -ne 0 ]; then log "\tAdditional space for rootfs partitions not aligned.\ \n\tFinal image will be smaller than ${storage_size_mb}MB" fi rootfs_overplus_bytes=$(($rootfs_overplus_bytes - $reminder)) rootfs_overplus_s=$(( $rootfs_overplus_bytes / $sector_size )) local prootfs_size=${mender_sizes[prootfs_size]} prootfs_size=$(( $prootfs_size + $rootfs_overplus_s )) image_size_bytes=$(( $image_size_bytes + 2 * $rootfs_overplus_bytes )) eval $rvar_array[prootfs_size]="'$prootfs_size'" eval $rvar_image_size="'$image_size_bytes'" return 0 } # Takes following arguments: # # $1 - raw disk image path # $2 - raw disk image size create_mender_disk() { local lfile=$1 local lsize=$2 # Generates a sparse image dd if=/dev/zero of=${lfile} seek=${lsize} bs=1 count=0 >> "$build_log" 2>&1 } # Takes following arguments: # # $1 - Mender disk image path # $2 - Mender disk image size # $3 - partition alignment # $4 - array of partitions' sizes for Mender image # format_mender_disk() { local lfile=$1 local lsize=$2 local rc=0 local _mender_sizes=$(declare -p $4) eval "declare -A mender_sizes="${_mender_sizes#*=} local sector_size=${mender_sizes[sector_size]} local alignment=$(($3 / ${sector_size})) cylinders=$(( ${lsize} / ${heads} / ${sectors} / ${sector_size} )) pboot_start=${mender_sizes[pboot_start]} pboot_size=${mender_sizes[pboot_size]} pboot_end=$((${pboot_start} + ${pboot_size} - 1)) prootfs_size=${mender_sizes[prootfs_size]} prootfsa_start=$((${pboot_end} + 1)) prootfsa_end=$((${prootfsa_start} + ${prootfs_size} - 1)) prootfsb_start=$((${prootfsa_end} + 1)) prootfsb_end=$((${prootfsb_start} + ${prootfs_size} - 1)) pdata_start=$((${prootfsb_end} + 1)) pdata_size=${mender_sizes[pdata_size]} pdata_end=$((${pdata_start} + ${pdata_size} - 1)) if [ -v mender_sizes[pswap_size] ]; then local pextended_start=$((${prootfsb_end} + 1)) pdata_start=$(($pextended_start + ${alignment})) pdata_end=$((${pdata_start} + ${pdata_size} - 1)) local pswap_start=$((${pdata_end} + ${alignment} + 1)) local pswap_size=${mender_sizes[pswap_size]} local pswap_end=$((${pswap_start} + ${pswap_size} - 1)) fi sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' << EOF | sudo fdisk ${lfile} &> /dev/null o # clear the in memory partition table x h ${heads} s ${sectors} c ${cylinders} r w # write the partition table q # and we're done EOF # Create partition table sudo parted -s ${lfile} mklabel msdos || rc=$? sudo parted -s ${lfile} unit s mkpart primary fat32 ${pboot_start} ${pboot_end} || rc=$? sudo parted -s ${lfile} set 1 boot on || rc=$? sudo parted -s ${lfile} -- unit s mkpart primary ext4 ${prootfsa_start} ${prootfsa_end} || rc=$? sudo parted -s ${lfile} -- unit s mkpart primary ext4 ${prootfsb_start} ${prootfsb_end} || rc=$? if [ -v mender_sizes[pswap_size] ]; then log "\tAdding swap partition." sudo parted -s ${lfile} -- unit s mkpart extended ${pextended_start} 100% || rc=$? sudo parted -s ${lfile} -- unit s mkpart logical ext4 ${pdata_start} ${pdata_end} || rc=$? sudo parted -s ${lfile} -- unit s mkpart logical linux-swap ${pswap_start} ${pswap_end} || rc=$? else sudo parted -s ${lfile} -- unit s mkpart primary ext4 ${pdata_start} ${pdata_end} || rc=$? fi [[ $rc -eq 0 ]] && { log "\tChanges in partition table applied."; } return $rc } # Takes following arguments: # # $1 - raw disk file # verify_mender_disk() { local lfile=$1 local lcounts=$2 local limage=$(basename $lfile) local partitions=($(fdisk -l -u ${limage} | cut -d' ' -f1 | grep 'sdimg[1-9]\{1\}$')) local no_of_parts=${#partitions[@]} [[ $no_of_parts -eq $lcounts ]] || \ { log "Error: incorrect number of partitions: $no_of_parts. Aborting."; return 1; } return 0 } # Takes following arguments: # # $1 - raw disk image # $2 - partition mappings holder create_device_maps() { local -n mappings=$2 if [[ -n "$1" ]]; then loopdevice=$(sudo losetup --show -f $1) mapfile -t mappings < <( sudo kpartx -s -v -a $loopdevice | grep 'loop' | cut -d' ' -f3 ) [[ ${#mappings[@]} -eq 0 ]] \ && { log "Error: partition mappings failed. Aborting."; exit 1; } else log "Error: no device passed. Aborting." exit 1 fi sudo partprobe /dev/${mappings[0]%p*} } # Takes following arguments: # # $1 - partition mappings holder detach_device_maps() { local mappings=($@) [ ${#mappings[@]} -eq 0 ] && { log "\tPartition mappings cleaned."; return; } local mapper=${mappings[0]%p*} for mapping in ${mappings[@]} do map_dev=/dev/mapper/"$mapping" is_mounted=`grep ${map_dev} /proc/self/mounts | wc -l` if [ ${is_mounted} -ne 0 ]; then sudo umount -l $map_dev fi done sudo kpartx -d /dev/$mapper & sudo losetup -d /dev/$mapper & wait && sync } # Takes following arguments: # # $1 - partition mappings holder # make_mender_disk_filesystem() { local mappings=($@) local counts=${#mappings[@]} if [ $counts -eq 4 ]; then local labels=(${mender_partitions_regular[@]}) elif [ $counts -eq 6 ]; then local labels=(${mender_partitions_extended[@]}) fi for mapping in ${mappings[@]} do map_dev=/dev/mapper/"$mapping" part_no=$(get_part_number_from_device $map_dev) label=${labels[${part_no} - 1]} case ${part_no} in 1) log "\tCreating MS-DOS filesystem for '$label' partition." sudo mkfs.vfat -n ${label} $map_dev >> "$build_log" 2>&1 ;; 2|3) log "\tCreating ext4 filesystem for '$label' partition." sudo mkfs.ext4 -L ${label} $map_dev >> "$build_log" 2>&1 ;; 4) if [ $counts -eq 4 ]; then log "\tCreating ext4 filesystem for '$label' partition." sudo mkfs.ext4 -L ${label} $map_dev >> "$build_log" 2>&1 else continue fi ;; 5) log "\tCreating ext4 filesystem for '$label' partition." sudo mkfs.ext4 -L ${label} $map_dev >> "$build_log" 2>&1 ;; 6) log "\tCreating swap area for '$label' partition." sudo mkswap -L ${label} $map_dev >> "$build_log" 2>&1 ;; *) break ;; esac done } # Takes following arguments: # # $1 - partition mappings holder mount_raw_disk() { local mappings=($@) if [ ${#mappings[@]} -eq 1 ]; then local path=$embedded_rootfs_dir mkdir -p $path sudo mount /dev/mapper/"${mappings[0]}" $path return fi for mapping in ${mappings[@]} do local part_no=${mapping#*p*p} local path=$embedded_base_dir/${raw_disk_partitions[${part_no} - 1]} mkdir -p $path sudo mount /dev/mapper/"${mapping}" $path 2>&1 >/dev/null done } # Takes following arguments: # # $1 - partition mappings holder mount_mender_disk() { local mappings=($@) local counts=${#mappings[@]} if [ $counts -eq 4 ]; then local labels=(${mender_partitions_regular[@]}) elif [ $counts -eq 6 ]; then local labels=(${mender_partitions_extended[@]}) fi for mapping in ${mappings[@]} do local part_no=${mapping#*p*p} local path=$sdimg_base_dir/${labels[${part_no} - 1]} mkdir -p $path case ${part_no} in 1|2|3) sudo mount /dev/mapper/"${mapping}" $path 2>&1 >/dev/null ;; 4) if [ $counts -eq 4 ]; then sudo mount /dev/mapper/"${mapping}" $path 2>&1 >/dev/null else # Skip extended partition. continue fi ;; 5) sudo mount /dev/mapper/"${mapping}" $path 2>&1 >/dev/null ;; 6) # Skip swap partition. continue ;; *) break ;; esac done } # Takes following arguments # # $1 - device type set_fstab() { local mountpoint= local blk_device= local data_id=4 local device_type=$1 local sysconfdir="$sdimg_primary_dir/etc" [ ! -d "${sysconfdir}" ] && { log "Error: cannot find rootfs config dir."; exit 1; } # Erase/create the fstab file. sudo install -b -m 644 /dev/null ${sysconfdir}/fstab case "$device_type" in "beaglebone") mountpoint="/boot/efi" blk_device=mmcblk0p ;; "raspberrypi3"|"raspberrypi0w") mountpoint="/uboot" blk_device=mmcblk0p ;; "rockpro64") mountpoint="/uboot" blk_device=mmcblk1p ;; "qemux86_64") mountpoint="/boot/efi" blk_device=hda data_id=5 ;; *) log "Error: unsupported device type $device_type" exit 1 ;; esac # Add Mender specific entries to fstab. sudo bash -c "cat <<- EOF > ${sysconfdir}/fstab # stock fstab - you probably want to override this with a machine specific one /dev/root / auto defaults 1 1 proc /proc proc defaults 0 0 devpts /dev/pts devpts mode=0620,gid=5 0 0 tmpfs /run tmpfs mode=0755,nodev,nosuid,strictatime 0 0 tmpfs /var/volatile tmpfs defaults 0 0 # uncomment this if your device has a SD/MMC/Transflash slot #/dev/mmcblk0p1 /media/card auto defaults,sync,noauto 0 0 # Where the U-Boot environment resides; for devices with SD card support ONLY! /dev/${blk_device}1 $mountpoint auto defaults,sync 0 0 /dev/${blk_device}${data_id} /data auto defaults 0 0 EOF" if [ "$device_type" == "qemux86_64" ]; then # Add entry referring to swap partition. sudo tee -a ${sysconfdir}/fstab <<< "/dev/hda6 swap swap defaults 0 0" 2>&1 >/dev/null fi log "\tDone." } # Takes following arguments # # $1 - path to source raw disk image # $2 - sector start (in 512 blocks) # $3 - size (in 512 blocks) extract_file_from_image() { log "\tStoring data in $4." local cmd="dd if=$1 of=${output_dir}/$4 skip=$2 bs=512 count=$3 conv=sparse" $(${cmd}>> "$build_log" 2>&1) } # Takes following arguments # # $1 - device type # $2 - partition alignment in bytes # $3 - total size in bytes # $4 - array of partitions' sizes for Mender image # create_test_config_file() { local device_type=$1 local alignment=$2 local mender_image_size_mb=$(( (($3 / 1024) / 1024) )) local _mender_sizes=$(declare -p $4) eval "declare -A mender_sizes="${_mender_sizes#*=} local sector_size=${mender_sizes[sector_size]} local boot_offset=$(( (${mender_sizes[pboot_start]} * $sector_size) )) local boot_size_mb=$(( (((${mender_sizes[pboot_size]} * $sector_size) / 1024) / 1024) )) local rootfs_size_mb=$(( (((${mender_sizes[prootfs_size]} * $sector_size) / 1024) / 1024) )) local data_size_mb=$(( (((${mender_sizes[pdata_size]} * $sector_size) / 1024) / 1024) )) cp ${files_dir}/variables.template ${output_dir}/${device_type}_variables.cfg sed -i '/^MENDER_BOOT_PART_SIZE_MB/s/=.*$/="'${boot_size_mb}'"/' ${output_dir}/${device_type}_variables.cfg sed -i '/^MENDER_DATA_PART_SIZE_MB/s/=.*$/="'${data_size_mb}'"/' ${output_dir}/${device_type}_variables.cfg sed -i '/^MENDER_DEVICE_TYPE/s/=.*$/="'${device_type}'"/' ${output_dir}/${device_type}_variables.cfg sed -i '/^MENDER_PARTITION_ALIGNMENT/s/=.*$/="'${alignment}'"/' ${output_dir}/${device_type}_variables.cfg sed -i '/^MENDER_STORAGE_TOTAL_SIZE_MB/s/=.*$/="'${mender_image_size_mb}'"/' ${output_dir}/${device_type}_variables.cfg sed -i '/^MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET/s/=.*$/="'${boot_offset}'"/' ${output_dir}/${device_type}_variables.cfg sed -i '/^MENDER_CALC_ROOTFS_SIZE/s/=.*$/="'${rootfs_size_mb}'"/' ${output_dir}/${device_type}_variables.cfg sed -i '/^MENDER_MACHINE/s/=.*$/="'${device_type}'"/' ${output_dir}/${device_type}_variables.cfg sed -i '/^DEPLOY_DIR_IMAGE/s/=.*$/="'${output_dir//\//\\/}'"/' ${output_dir}/${device_type}_variables.cfg } # Takes following arguments # # $1 - device type # $2 - parameter name to change # $3 - parameter value update_test_config_file() { local device_type=$1 [ ! -f "${output_dir}/${device_type}_variables.cfg" ] && \ { log "Error: test configuration file '${device_type}_variables.cfg' not found. Aborting."; return 1; } shift while test ${#} -gt 0 do case "$1" in "artifact-name") sed -i '/^MENDER_ARTIFACT_NAME/s/=.*$/="'${2}'"/' ${output_dir}/${device_type}_variables.cfg ;; "distro-feature") sed -i '/^DISTRO_FEATURES/s/=.*$/="'${2}'"/' ${output_dir}/${device_type}_variables.cfg ;; "mount-location") sed -i '/^MENDER_BOOT_PART_MOUNT_LOCATION/s/=.*$/="'${2}'"/' ${output_dir}/${device_type}_variables.cfg ;; esac shift 2 done return 0 }