WISE-PaaS/OTA Agent(risc linux)
Contents
Introduction
This document demonstrates how to support our ota-agent solution on your risc arm linux for BSP update.
Requirement
- The storage(sd card, Nand flash) capacity need greate than 4G. 8G is recommended
Note
We take our rsb4220 (TI am335x platform) for example. It is similar for other platfrom.
Architecture
In order to support rollback, we requires the device to have a certain partition layout. At least four different partitions are needed:
- one boot partition, containing the U-Boot bootloader and its environment
- two partitions for storing the root file system and kernel. The kernel image file, zImage, and any device tree binary should be stored in directory /boot
- one partition for persistent data
One of the rootfs and kernel partitions will be marked as the active partition, from which the kernel and rootfs will be booted. The other, called the inactive partition, will be used by the update mechanism to write the updated image. After an update their roles are swapped.
The persistent data partition stores data that needs to be preserved through an update.For our rsb4220, the partition layout is as follow:
- /dev/mmcblk0p1 containing the u-boot
- /dev/mmcblk0p2 containing the Current System, or named the active partition
- /dev/mmcblk0p3 before update, it is blank, it will be used by the update mechanism to write the updated image
- /dev/mmcblk0p4 persistent data
How to support
uboot modification
modify uboot to let it can switch the boot partition. take our rsb4220 for example:
- modify file include/configs/am335x_rsb4220.h
define CONFIG_LINUX_OTA
// add boot_part=0
#define CONFIG_EXTRA_ENV_SETTINGS \
...
"boot_part=0\0" \
...
- modify file arch/arm/lib/board.c
void board_set_boot_device()
{
int dev = (*(int *)0XC1000000);
char *part;
unsigned int partindex;
part = getenv("boot_part");
printf("boot_part index %s\n", part);
partindex = part ? simple_strtoul (part, NULL, 10) : 0;
switch(dev) {
case 0:
/* booting from MMC0*/
printf("booting from SD\n");
setenv("mmcdev", "0");
#ifdef CONFIG_LINUX_OTA
if(partindex == 0){
setenv("mmcroot", "/dev/mmcblk0p2 rw");
setenv("loaduimage","ext2load mmc ${mmcdev}:2 ${kloadaddr} /boot/${bootfile}");
}
else if(partindex == 1){
setenv("mmcroot", "/dev/mmcblk0p3 rw");
setenv("loaduimage","ext2load mmc ${mmcdev}:3 ${kloadaddr} /boot/${bootfile}");
}
else{
printf("## error: invalid part index, using part A\n");
setenv("mmcroot", "/dev/mmcblk0p2 rw");
setenv("loaduimage","ext2load mmc ${mmcdev}:2 ${kloadaddr} /boot/${bootfile}");
}
#else
setenv("mmcroot", "/dev/mmcblk0p2 rw");
#endif
#endif
break;
}
}
make sd card script
The script formats sd card to meet the requirement of ota under risc linux
You can get the script form here:
https://github.com/ADVANTECH-Corp/wise-paas-ota-agent-risc-linux
Ota script under Linux
This part achieve the ota details under risc linux, mainly copy the kernel and rootfs to the updated partition:
#!/bin/bash
deviceprefix=/dev/mmcblk0p
mountpprefix=/media/mmcblk0p
ubootpartno=1
rootpartAno=2
rootpartBno=3
workpartno=4
ubootdevice=${deviceprefix}${ubootpartno}
rootAdevice=${deviceprefix}${rootpartAno}
rootBdevice=${deviceprefix}${rootpartBno}
workdevice=${deviceprefix}${workpartno}
ubootpoint=${mountpprefix}${ubootpartno}
rootApoint=${mountpprefix}${rootpartAno}
rootBpoint=${mountpprefix}${rootpartBno}
workpoint=${mountpprefix}${workpartno}
OTA_WORK_DIR=${mountpprefix}${workpartno}/ota/work
OTA_LOG_DIR=${mountpprefix}${workpartno}/ota/log
OTA_LOG_FILE=`date +"%Y%m%d%H%M%S"`.log
OTA_LOG_FILE=${OTA_LOG_DIR}/${OTA_LOG_FILE}
partindex=`fw_printenv boot_part | busybox cut -d '=' -f 2`
error_log(){
echo "$1" >> ${OTA_LOG_FILE}
exit 1
}
mount_prepare()
{
umount ${workdevice}
mount -t ext3 ${workdevice} ${workpoint}
[ "$?" -ne 0 ] && error_log "error: mount failed"
}
if [[ -z $1 ]]; then
cat << EOF
SYNOPSIS:
$0 {new-bsp-file}
EXAMPLE:
$0 4221LIV0001_2016-02-29.tar.gz
EOF
exit 1
fi
#mount_prepare
t1=`echo $1 | busybox cut -d '_' -f 1`
version=`echo ${t1:0-5}`
mkdir -p ${OTA_WORK_DIR}
mkdir -p ${OTA_LOG_DIR}
rm -rf ${OTA_WORK_DIR}/*
touch ${OTA_LOG_FILE}
echo "info: begin: " > ${OTA_LOG_FILE}
echo "info: version: ${version}" >> ${OTA_LOG_FILE}
echo "info: boot_part: ${partindex}" >> ${OTA_LOG_FILE}
tar xvf $1 -C ${OTA_WORK_DIR} > /dev/null
[ "$?" -ne 0 ] && error_log "error: tar failed"
cd ${OTA_WORK_DIR}/image
if [ ${partindex} == "0" ];then
echo "info: current is partA" >> ${OTA_LOG_FILE}
umount ${rootBdevice}
echo "info: mkfs.ext3 for rootB" >> ${OTA_LOG_FILE}
mkfs.ext3 ${rootBdevice}
[ "$?" -ne 0 ] && error_log "error: format rootB failed"
echo "info: mount rootB" >> ${OTA_LOG_FILE}
mount -t ext3 ${rootBdevice} ${rootBpoint}
[ "$?" -ne 0 ] && error_log "error: mount rootB failed"
echo "info: copy files to rootB" >> ${OTA_LOG_FILE}
busybox cp -rfa ${OTA_WORK_DIR}/image/rootfs/* ${rootBpoint}/
[ "$?" -ne 0 ] && error_log "error: copy rootB failed"
elif [ ${version} == "1" ];then
echo "info: current is partB" >> ${OTA_LOG_FILE}
umount ${rootAdevice}
echo "info: mkfs.ext3 for rootA" >> ${OTA_LOG_FILE}
mkfs.ext3 ${rootAdevice}
[ "$?" -ne 0 ] && error_log "error: format rootA failed"
echo "info: mount rootA" >> ${OTA_LOG_FILE}
mount -t ext3 ${rootAdevice} ${rootApoint}
[ "$?" -ne 0 ] && error_log "error: mount rootA failed"
echo "info: copy files to rootA" >> ${OTA_LOG_FILE}
busybox cp -rfa ${OTA_WORK_DIR}/image/rootfs/* ${rootApoint}/
[ "$?" -ne 0 ] && error_log "error: copy rootA failed"
else
error_log "error: invalid partition"
fi
rm -rf ${OTA_WORK_DIR}/*
let newpartindex=($partindex+1)%2
echo "info: will set boot_part to ${newpartindex}" >> ${OTA_LOG_FILE}
fw_setenv boot_part ${newpartindex}
echo "info: success" >> ${OTA_LOG_FILE}
echo "==============================================" >> ${OTA_LOG_FILE}
#sync
#reboot
modify-env-tools under linux
After update new-bsp to the update partition, it is time to modify the uboot-env to let uboot to boot this new-bsp when next startup.
It is easy under uboot through set the env boot_part, but under linux system, we can't. So we find a tool named fw_printenv to do this.
The source code of fw_printenv tools is under uboot source code(tools/env).Cross-compile it and move fw_printenv to /bin directory under your board. then create a softlink named fw_setenv to fw_printenv.
Now your can use command fw_printenv to print some environment variable and use fw_setenv to modify some environment variable.