find_mmc_part() { local DEVNAME PARTNAME if grep -q "$1" /proc/mtd; then echo "" && return 0 fi for DEVNAME in /sys/block/mmcblk0/mmcblk*p*; do PARTNAME=$(grep PARTNAME ${DEVNAME}/uevent | cut -f2 -d'=') [ "$PARTNAME" = "$1" ] && echo "/dev/$(basename $DEVNAME)" && return 0 done } get_full_section_name() { local img=$1 local sec=$2 dumpimage -l ${img} | grep "^ Image.*(${sec})" | \ sed 's,^ Image.*(\(.*\)),\1,' } image_contains() { local img=$1 local sec=$2 dumpimage -l ${img} | grep -q "^ Image.*(${sec}.*)" || return 1 } print_sections() { local img=$1 dumpimage -l ${img} | awk '/^ Image.*(.*)/ { print gensub(/Image .* \((.*)\)/,"\\1", $0) }' } image_has_mandatory_section() { local img=$1 local mandatory_sections=$2 for sec in ${mandatory_sections}; do image_contains $img ${sec} || {\ return 1 } done } image_demux() { local img=$1 for sec in $(print_sections ${img}); do local fullname=$(get_full_section_name ${img} ${sec}) local position=$(dumpimage -l ${img} | grep "(${fullname})" | awk '{print $2}') dumpimage -i ${img} -o /tmp/${fullname}.bin -T "flat_dt" -p "${position}" ${fullname} > /dev/null || { \ echo "Error while extracting \"${sec}\" from ${img}" return 1 } done return 0 } image_is_FIT() { if ! dumpimage -l $1 > /dev/null 2>&1; then echo "$1 is not a valid FIT image" return 1 fi return 0 } switch_layout() { local layout=$1 local boot_layout=`find / -name boot_layout` # Layout switching is only required as the boot images (up to u-boot) # use 512 user data bytes per code word, whereas Linux uses 516 bytes. # It's only applicable for NAND flash. So let's return if we don't have # one. [ -n "$boot_layout" ] || return case "${layout}" in boot|1) echo 1 > $boot_layout;; linux|0) echo 0 > $boot_layout;; *) echo "Unknown layout \"${layout}\"";; esac } do_flash_mtd() { local bin=$1 local mtdname=$2 local append="" local mtdpart=$(grep "\"${mtdname}\"" /proc/mtd | awk -F: '{print $1}') local pgsz=$(cat /sys/class/mtd/${mtdpart}/writesize) [ -f "$CONF_TAR" -a "$SAVE_CONFIG" -eq 1 -a "$2" == "rootfs" ] && append="-j $CONF_TAR" dd if=/tmp/${bin}.bin bs=${pgsz} conv=sync | mtd $append -e "/dev/${mtdpart}" write - "/dev/${mtdpart}" } do_flash_emmc() { local bin=$1 local emmcblock=$2 dd if=/dev/zero of=${emmcblock} dd if=/tmp/${bin}.bin of=${emmcblock} } do_flash_partition() { local bin=$1 local mtdname=$2 local emmcblock="$(find_mmc_part "$mtdname")" if [ -e "$emmcblock" ]; then do_flash_emmc $bin $emmcblock else do_flash_mtd $bin $mtdname fi } do_flash_bootconfig() { local bin=$1 local mtdname=$2 # Fail safe upgrade if [ -f /proc/boot_info/getbinary_${bin} ]; then cat /proc/boot_info/getbinary_${bin} > /tmp/${bin}.bin do_flash_partition $bin $mtdname fi } do_flash_failsafe_partition() { local bin=$1 local mtdname=$2 local emmcblock local primaryboot # Fail safe upgrade [ -f /proc/boot_info/$mtdname/upgradepartition ] && { default_mtd=$mtdname mtdname=$(cat /proc/boot_info/$mtdname/upgradepartition) primaryboot=$(cat /proc/boot_info/$default_mtd/primaryboot) if [ $primaryboot -eq 0 ]; then echo 1 > /proc/boot_info/$default_mtd/primaryboot else echo 0 > /proc/boot_info/$default_mtd/primaryboot fi } emmcblock="$(find_mmc_part "$mtdname")" if [ -e "$emmcblock" ]; then do_flash_emmc $bin $emmcblock else do_flash_mtd $bin $mtdname fi } do_flash_ubi() { local bin=$1 local mtdname=$2 local mtdpart local primaryboot mtdpart=$(grep "\"${mtdname}\"" /proc/mtd | awk -F: '{print $1}') ubidetach -p /dev/${mtdpart} # Fail safe upgrade [ -f /proc/boot_info/$mtdname/upgradepartition ] && { primaryboot=$(cat /proc/boot_info/$mtdname/primaryboot) if [ $primaryboot -eq 0 ]; then echo 1 > /proc/boot_info/$mtdname/primaryboot else echo 0 > /proc/boot_info/$mtdname/primaryboot fi mtdname=$(cat /proc/boot_info/$mtdname/upgradepartition) } mtdpart=$(grep "\"${mtdname}\"" /proc/mtd | awk -F: '{print $1}') ubiformat /dev/${mtdpart} -y -f /tmp/${bin}.bin } do_flash_tz() { local sec=$1 local mtdpart=$(grep "\"0:QSEE\"" /proc/mtd | awk -F: '{print $1}') local emmcblock="$(find_mmc_part "0:QSEE")" if [ -n "$mtdpart" -o -e "$emmcblock" ]; then do_flash_failsafe_partition ${sec} "0:QSEE" else do_flash_failsafe_partition ${sec} "0:TZ" fi } do_flash_ddr() { local sec=$1 local mtdpart=$(grep "\"0:CDT\"" /proc/mtd | awk -F: '{print $1}') local emmcblock="$(find_mmc_part "0:CDT")" if [ -n "$mtdpart" -o -e "$emmcblock" ]; then do_flash_failsafe_partition ${sec} "0:CDT" else do_flash_failsafe_partition ${sec} "0:DDRPARAMS" fi } to_upper () { echo $1 | awk '{print toupper($0)}' } flash_section() { local sec=$1 local board=$(board_name) case "${sec}" in hlos*) switch_layout linux; do_flash_failsafe_partition ${sec} "0:HLOS";; rootfs*) switch_layout linux; do_flash_failsafe_partition ${sec} "rootfs";; fs*) switch_layout linux; do_flash_failsafe_partition ${sec} "rootfs";; ubi*) switch_layout linux; do_flash_ubi ${sec} "rootfs";; #sbl1*) switch_layout boot; do_flash_partition ${sec} "0:SBL1";; #sbl2*) switch_layout boot; do_flash_failsafe_partition ${sec} "0:SBL2";; #sbl3*) switch_layout boot; do_flash_failsafe_partition ${sec} "0:SBL3";; #mibib*) switch_layout boot; do_flash_partition ${sec} "0:MIBIB";; #dtb-$(to_upper $board)*) switch_layout boot; do_flash_partition ${sec} "0:DTB";; u-boot*) switch_layout boot; do_flash_failsafe_partition ${sec} "0:APPSBL";; #ddr-$(to_upper $board)*) switch_layout boot; do_flash_ddr ${sec};; ddr-${board}-*) switch_layout boot; do_flash_failsafe_partition ${sec} "0:CDT";; #ssd*) switch_layout boot; do_flash_partition ${sec} "0:SSD";; tz*) switch_layout boot; do_flash_tz ${sec};; #rpm*) switch_layout boot; do_flash_failsafe_partition ${sec} "0:RPM";; *) echo "Section ${sec} ignored"; return 1;; esac echo "Flashed ${sec}" } erase_emmc_config() { local emmcblock="$(find_mmc_part "rootfs_data")" if [ -e "$emmcblock" ]; then dd if=/dev/zero of=${emmcblock} mkfs.ext4 "$emmcblock" fi } platform_pre_upgrade() { cp /sbin/upgraded /tmp ubus call system nandupgrade "{\"path\": \"$1\" }" } platform_check_image_ipq() { local board=$(board_name) local mandatory_nand="ubi" local mandatory_nor_emmc="hlos fs" local mandatory_nor="hlos" local mandatory_section_found=0 local optional="sbl2 u-boot ddr-${board} ssd tz rpm" local ignored="mibib bootconfig sbl1" image_is_FIT $1 || return 1 image_has_mandatory_section $1 ${mandatory_nand} && {\ mandatory_section_found=1 } image_has_mandatory_section $1 ${mandatory_nor_emmc} && {\ mandatory_section_found=1 } image_has_mandatory_section $1 ${mandatory_nor} && {\ mandatory_section_found=1 } if [ $mandatory_section_found -eq 0 ]; then echo "Error: mandatory section(s) missing from \"$1\". Abort..." return 1 fi for sec in ${optional}; do image_contains $1 ${sec} || {\ echo "Warning: optional section \"${sec}\" missing from \"$1\". Continue..." } done for sec in ${ignored}; do image_contains $1 ${sec} && {\ echo "Warning: section \"${sec}\" will be ignored from \"$1\". Continue..." } done image_demux $1 || {\ echo "Error: \"$1\" couldn't be extracted. Abort..." return 1 } [ -f /tmp/hlos_version ] && rm -f /tmp/*_version dumpimage -c $1 2>/dev/null return $? } platform_version_upgrade() { local version_files="appsbl_version sbl_version tz_version hlos_version rpm_version" local sys="/sys/devices/system/qfprom/qfprom0/" local tmp="/tmp/" for file in $version_files; do [ -f "${tmp}${file}" ] && { echo "Updating "${sys}${file}" with `cat "${tmp}${file}"`" echo `cat "${tmp}${file}"` > "${sys}${file}" rm -f "${tmp}${file}" } done } # The U-Boot loader of the OpenMesh devices requires image sizes and # checksums to be provided in the U-Boot environment. # The OpenMesh devices come with 2 main partitions - while one is active # sysupgrade will flash the other. The boot order is changed to boot the # newly flashed partition. If the new partition can't be booted due to # upgrade failures the previously used partition is loaded. platform_do_upgrade_ipq() { local board=$(board_name) # verify some things exist before erasing if [ ! -e $1 ]; then echo "Error: Can't find $1 after switching to ramfs, aborting upgrade!" reboot fi for sec in $(print_sections $1); do if [ ! -e /tmp/${sec}.bin ]; then echo "Error: Cant' find ${sec} after switching to ramfs, aborting upgrade!" reboot fi done case "$board" in teltonika,rutx) for sec in $(print_sections $1); do flash_section ${sec} done switch_layout linux # update bootconfig to register that fw upgrade has been done do_flash_bootconfig bootconfig "0:BOOTCONFIG" do_flash_bootconfig bootconfig1 "0:BOOTCONFIG1" platform_version_upgrade erase_emmc_config return 0; ;; esac echo "Upgrade failed!" return 1; } platform_copy_config_ipq() { local emmcblock="$(find_mmc_part "rootfs_data")" mkdir -p /tmp/overlay if [ -e "$emmcblock" ]; then mount -t ext4 "$emmcblock" /tmp/overlay cp /tmp/sysupgrade.tgz /tmp/overlay/ sync umount /tmp/overlay else local mtdname=rootfs local mtdpart [ -f /proc/boot_info/$mtdname/upgradepartition ] && { mtdname=$(cat /proc/boot_info/$mtdname/upgradepartition) } mtdpart=$(grep "\"${mtdname}\"" /proc/mtd | awk -F: '{print $1}') ubiattach -p /dev/${mtdpart} mount -t ubifs ubi0:rootfs_data /tmp/overlay cp /tmp/sysupgrade.tgz /tmp/overlay/ sync umount /tmp/overlay fi }