OpenWrt 19.07系统下参考imx6平台移植imx8平台,使用EMMC作为启动和存储介质,imx6 的apalis平台使用的是4GB eMMC,但实际升级时使用MTD操作nand flash,这时就需要MTD能操作EMMC的方法了。
分析sysupgrade升级流程
sysupgrade命令脚本sbin/sysupgrade 代码
#!/bin/sh
. /lib/functions.sh 提供工具函数
. /lib/functions/system.sh 提供mtd和mac操作函数
. /usr/share/libubox/jshn.sh 提供json_xx函数
# initialize defaults
export MTD_ARGS=""
export MTD_CONFIG_ARGS=""
export INTERACTIVE=0
export VERBOSE=1
export SAVE_CONFIG=1
export SAVE_OVERLAY=0
export SAVE_OVERLAY_PATH=
export SAVE_PARTITIONS=1
export SAVE_INSTALLED_PKGS=0
export SKIP_UNCHANGED=0
export CONF_IMAGE=
export CONF_BACKUP_LIST=0
export CONF_BACKUP=
export CONF_RESTORE=
export NEED_IMAGE=
export HELP=0
export FORCE=0
export TEST=0
export UMOUNT_ETCBACKUP_DIR=0
# parse options
while [ -n "$1" ]; do
case "$1" in
-i) export INTERACTIVE=1;;
-v) export VERBOSE="$(($VERBOSE + 1))";;
-q) export VERBOSE="$(($VERBOSE - 1))";;
-n) export SAVE_CONFIG=0;;
-c) export SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/etc;;
-o) export SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/;;
-p) export SAVE_PARTITIONS=0;;
-k) export SAVE_INSTALLED_PKGS=1;;
-u) export SKIP_UNCHANGED=1;;
-b|--create-backup) export CONF_BACKUP="$2" NEED_IMAGE=1; shift;;
-r|--restore-backup) export CONF_RESTORE="$2" NEED_IMAGE=1; shift;;
-l|--list-backup) export CONF_BACKUP_LIST=1;;
-f) export CONF_IMAGE="$2"; shift;;
-F|--force) export FORCE=1;;
-T|--test) export TEST=1;;
-h|--help) export HELP=1; break;;
-*)
echo "Invalid option: $1" >&2
exit 1
;;
*) break;;
esac
shift;
done
export CONFFILES=/tmp/sysupgrade.conffiles
export CONF_TAR=/tmp/sysupgrade.tgz
export ETCBACKUP_DIR=/etc/backup
export INSTALLED_PACKAGES=${ETCBACKUP_DIR}/installed_packages.txt
IMAGE="$1"
[ -z "$IMAGE" -a -z "$NEED_IMAGE" -a $CONF_BACKUP_LIST -eq 0 -o $HELP -gt 0 ] && {
cat <<EOF
Usage: $0 [<upgrade-option>...] <image file or URL>
$0 [-q] [-i] [-c] [-u] [-o] [-k] <backup-command> <file>
upgrade-option:
-f <config> restore configuration from .tar.gz (file or url)
-i interactive mode
-c attempt to preserve all changed files in /etc/
-o attempt to preserve all changed files in /, except those
from packages but including changed confs.
-u skip from backup files that are equal to those in /rom
-n do not save configuration over reflash
-p do not attempt to restore the partition table after flash.
-k include in backup a list of current installed packages at
$INSTALLED_PACKAGES
-T | --test
Verify image and config .tar.gz but do not actually flash.
-F | --force
Flash image even if image checks fail, this is dangerous!
-q less verbose
-v more verbose
-h | --help display this help
backup-command:
-b | --create-backup <file>
create .tar.gz of files specified in sysupgrade.conf
then exit. Does not flash an image. If file is '-',
i.e. stdout, verbosity is set to 0 (i.e. quiet).
-r | --restore-backup <file>
restore a .tar.gz created with sysupgrade -b
then exit. Does not flash an image. If file is '-',
the archive is read from stdin.
-l | --list-backup
list the files that would be backed up when calling
sysupgrade -b. Does not create a backup file.
EOF
exit 1
}
[ -n "$IMAGE" -a -n "$NEED_IMAGE" ] && {
cat <<-EOF
-b|--create-backup and -r|--restore-backup do not perform a firmware upgrade.
Do not specify both -b|-r and a firmware image.
EOF
exit 1
}include /lib/upgrade导入common.sh fwtool.sh luci-add-conffiles.sh nand.sh platform.sh脚本函数
type platform_check_image >/dev/null 2>/dev/null || {
echo "Firmware upgrade is not implemented for this platform." >&2
exit 1
}
lib/upgrade/platform.sh
platform_check_image() {
local board=$(board_name)
case "$board" in
apalis*)
return 0
;;
*gw5*)
nand_do_platform_check $board $1
return $?;
;;
esac
echo "Sysupgrade is not yet supported on $board."
return 1
}检测函数会根据board_name名称
if [ -n "$CONF_IMAGE" ]; then
case "$(get_magic_word $CONF_IMAGE cat)" in
# .gz files
1f8b) ;;
*)
echo "Invalid config file. Please use only .tar.gz files" >&2
exit 1
;;
esac
get_image "$CONF_IMAGE" "cat" > "$CONF_TAR"
export SAVE_CONFIG=1
elif ask_bool $SAVE_CONFIG "Keep config files over reflash"; then
[ $TEST -eq 1 ] || do_save_conffiles "$CONF_TAR"
export SAVE_CONFIG=1
else
[ $TEST -eq 1 ] || rm -f "$CONF_TAR"
export SAVE_CONFIG=0
fi
if [ $TEST -eq 1 ]; then
exit 0
fi
install_bin /sbin/upgraded
v "Commencing upgrade. Closing all shell sessions."
COMMAND='/lib/upgrade/do_stage2'
if [ -n "$FAILSAFE" ]; then
printf '%s\x00%s\x00%s' "$RAM_ROOT" "$IMAGE" "$COMMAND" >/tmp/sysupgrade
lock -u /tmp/.failsafe
else
force_attr=""
[ $FORCE -eq 1 ] && force_attr="\"force\": true,"
backup_attr=""
[ $SAVE_CONFIG -eq 1 ] && backup_attr="\"backup\": $(json_string $CONF_TAR),"
ubus call system sysupgrade "{
\"prefix\": $(json_string "$RAM_ROOT"),
\"path\": $(json_string "$IMAGE"),
$force_attr
$backup_attr
\"command\": $(json_string "$COMMAND"),
\"options\": {
\"save_partitions\": $SAVE_PARTITIONS
}
}"
fi最后使用ubus call system sysupgrade调用do_stage2升级:
#!/bin/sh . /lib/functions.sh include /lib/upgrade v "Performing system upgrade..." if type 'platform_do_upgrade' >/dev/null 2>/dev/null; then platform_do_upgrade "$IMAGE" else default_do_upgrade "$IMAGE" fi if [ -n "$UPGRADE_BACKUP" ] && type 'platform_copy_config' >/dev/null 2>/dev/null; then platform_copy_config fi v "Upgrade completed" sleep 1 v "Rebooting system..." umount -a reboot -f sleep 5 echo b 2>/dev/null >/proc/sysrq-trigger
platform_do_upgrade函数的实现
platform_do_upgrade() {
local board=$(board_name)
case "$board" in
apalis*)
apalis_do_upgrade "$1"
;;
*gw5*)
nand_do_upgrade "$1"
;;
esac
}
apalis_do_upgrade() {
local board_name=$(board_name)
board_name=${board_name/,/_}
apalis_mount_boot
get_image "$1" | tar Oxf - sysupgrade-${board_name}/kernel > /boot/uImage
get_image "$1" | tar Oxf - sysupgrade-${board_name}/root > $(rootpart_from_uuid)
sync
umount /boot
}
apalis_mount_boot() {
mkdir -p /boot
mount -t jffs2 mtd:rootfs_data /boot
}没有rootfs_data分区导致挂载失败:
root@OpenWrt:~# sysupgrade openwrt-imx8-ubox-squashfs-sysupgrade.bin Image not in /tmp, copying... Sysupgrade is not yet supported on ubox. Saving config files... Commencing upgrade. Closing all shell sessions. Watchdog handover: fd=3 - watchdog - killall: telnetd: no process killed Sending TERM to remaining processes ... ubusd askfirst urngd logd rpcd dnsmasq netifd odhcpd uhttpd hostapd udhcpd ntpd [ 273.003190] wlan: Stoping AP [ 273.008717] Invalid proberesp_p2p_index for mgmt frame ie. [ 273.014247] wlan: AP stopped Sending KILL to remaining processes ... Switching to ramdisk... [ 278.092977] EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered Performing system upgrade... [ 8288.416092] MTD: MTD device with name "rootfs_data" not found. mount: mounting mtd:rootfs_data on /boot failed: No such file or directory /lib/upgrade/do_stage2: line 31: rootpart_from_uuid: not found /lib/upgrade/do_stage2: line 31: can't create : nonexistent directory cat: write error: Broken pipe umount: can't unmount /boot: Invalid argument Upgrade completed Rebooting system... umount: can't unmount /dev: Resource busy umount: can't unmount /tmp: Resource busy [ 279.316786] ci_hdrc ci_hdrc.0: remove, state 1 [ 279.321280] usb usb3: USB disconnect, device number 1 [ 279.326358] usb 3-1: USB disconnect, device number 2 [ 279.331502] rndis_host 3-1:1.0 usb0: unregister 'rndis_host' usb-ci_hdrc.0-1, RNDIS device [ 279.340240] [RMNET:HI] rmnet_config_notify_cb(): Kernel is trying to unregister usb0 [ 279.362981] [RMNET:HI] rmnet_config_notify_cb(): Kernel is trying to unregister usb0 [ 279.373054] ci_hdrc ci_hdrc.0: USB bus 3 deregistered [ 279.390955] reboot: Restarting system
block2mtd 模拟MTD
fdisk查看emmc分区的信息:
root@OpenWrt:~# fdisk -l Disk /dev/mmcblk0: 7264 MB, 7616856064 bytes, 14876672 sectors 232448 cylinders, 4 heads, 16 sectors/track Units: sectors of 1 * 512 = 512 bytes Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type /dev/mmcblk0p1 320,0,1 575,3,16 20480 430079 409600 200M c Win95 FAT32 (LBA) /dev/mmcblk0p2 384,0,1 63,3,16 614400 7737343 7122944 3478M 83 Linux /dev/mmcblk0p3 64,0,1 319,3,16 7737344 8146943 409600 200M c Win95 FAT32 (LBA) /dev/mmcblk0p4 320,0,1 1023,3,16 8146944 14876671 6729728 3286M 83 Linux Disk /dev/mmcblk0rpmb: 4 MB, 4194304 bytes, 8192 sectors 128 cylinders, 4 heads, 16 sectors/track Units: sectors of 1 * 512 = 512 bytes Disk /dev/mmcblk0rpmb doesn't contain a valid partition table Disk /dev/mmcblk0boot1: 16 MB, 16777216 bytes, 32768 sectors 512 cylinders, 4 heads, 16 sectors/track Units: sectors of 1 * 512 = 512 bytes Disk /dev/mmcblk0boot1 doesn't contain a valid partition table Disk /dev/mmcblk0boot0: 16 MB, 16777216 bytes, 32768 sectors 512 cylinders, 4 heads, 16 sectors/track Units: sectors of 1 * 512 = 512 bytes Disk /dev/mmcblk0boot0 doesn't contain a valid partition table
打开内核的mtd,block2mtd的支持,执行如下命令
#设置mtd2block的分区 root@OpenWrt:/# echo "/dev/mmcblk0p3,8192" > /sys/module/block2mtd/parameters/block2mtd [ 1938.086585] Creating 1 MTD partitions on "/dev/mmcblk0p3": [ 1938.092141] 0x000000000000-0x00000c800000 : "/dev/mmcblk0p3" [ 1938.098764] block2mtd: mtd0: [/dev/mmcblk0p3] erase_size = 8KiB [8192] root@OpenWrt:/# ls /dev/mtd* -l crw------- 1 root root 90, 0 Jan 1 00:00 /dev/mtd0 crw------- 1 root root 90, 1 Jan 1 00:00 /dev/mtd0ro brw------- 1 root root 31, 0 Jan 1 00:02 /dev/mtdblock0 root@OpenWrt:/# cat /proc/mtd dev: size erasesize name mtd0: 0c800000 00002000 "/dev/mmcblk0p3" #格式化mtdblock0 root@OpenWrt:/# mkfs.ext4 /dev/mtdblock0 mke2fs 1.44.5 (15-Dec-2018) /dev/mtdblock0 contains a vfat file system Proceed anyway? (y,N) y Creating filesystem with 204800 1k blocks and 51200 inodes Filesystem UUID: 49faec10-c3b3-4716-962d-717f2ed5fa68 Superblock backups stored on blocks: 8193, 24577, 40961, 57345, 73729 Allocating group tables: done Writing inode tables: done Creating journal (4096 blocks): done Writing superblocks and filesystem accounting information: done #烧录rootfs squashfs镜像 root@OpenWrt:~# mtd write root.squashfs /dev/mtdblock0 Unlocking /dev/mtdblock0... Writing from root.squashfs to /dev/mtdblock0 ...
这样操作就把磁盘的p3分区模拟成了mtd分区,所以可以使用mtd相关命令来对/dev/mtdblock0进行操作。
本站的文章和资源来自互联网或者站长的原创,按照 CC BY -NC -SA 3.0 CN协议发布和共享,转载或引用本站文章应遵循相同协议。如果有侵犯版权的资 源请尽快联系站长,我们会在24h内删除有争议的资源。欢迎大家多多交流,期待共同学习进步。








