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内删除有争议的资源。欢迎大家多多交流,期待共同学习进步。