2020
09-04

小米路由器AX3600官方固件使用mkxqimage解包AX3600官方固件修改

小米路由器官方提供的固件是自定义格式,而且刷机时要验证 RSA 签名,因此刷自制固件比较麻烦。

最终通过对固件工具mkxqimage和固件的分析,基本弄清楚了固件打包和解包的流程,采用修改 flash.sh 来烧录重新打包的固件,绕过 mkxqimage的重新打包和验证。

同时今天分享一款AX3600的openwrt(qsdk)固件ax3600刷openwrt(qsdk)固件下载刷机教程

小米路由器AX3600官方固件使用mkxqimage解包

固件解包

下面以 AX3600 稳定版 1.0.67 为例,介绍固件修改和打包方法。

用mkxqimage解包固件

cd /tmp/diy
mkxqimage -x miwifi_r3600_firmware_f7f3e_1.0.67.bin

得到 2 个文件:

root.ubi

xiaoqiang

root.ubi 是 FLASH 全镜像,这个文件 ubi 格式,使用以下命令解包。

ubireader_extract_images root.ubi
img-267845145_vol-kernel.ubifs
img-267845145_vol-ubi_rootfs.ubifs

前者是内核镜像,基本不需要修改,就不研究了

后者是硬盘固件镜像,是 squashfs 格式,挂载然后修改

mount -o loop -t squashfs img-267845145_vol-ubi_rootfs.ubifs /mnt/ubi
rsync -az /mnt/ubi /mnt/rootfscd /mnt/rootfs
diy
umount /mnt/ubi
mksquashfs rootfs rootfs.ubifs -b 256k -comp xz

固件打包

将修改后的固件镜像和内核镜像这两个文件重新打包成 ubi 格式
先运行命令获取原包的参数

ubireader_display_info '/home/basher/root.ubi'

然后根据获取到的信息将下面文件写入到 ubinize.cfg

[kernel]
mode=ubi
image=img-267845145_vol-ubi_kernel.ubifs
vol_id=0
vol_type=dynamic
vol_name=kernel 
vol_alignment=1
[ubi_rootfs]
mode=ubi
image=rootfs.ubifs
vol_id=1
vol_type=dynamic
vol_name=ubi_rootfs
vol_alignment=1

运行下面命令打包

sudo ubinize -o root.img -Q 267845145 -m 2048 -p 128KiB -O 2048 ubinize.cfg

本来想用 mkxqimage 再打包成固件包在线更新安装的,结果这个 mkxqimage 更新了,原来的打包参数不对,懒得去研究了,就直接修改 flash.sh 直接进行命令行烧录更新了

flash.sh root.img

修改后的 flash.sh

#!/bin/sh
. /lib/functions.sh
klogger() {
    local msg1="$1"
    local msg2="$2"
    if [ "$msg1" = "-n" ]; then
        echo -n "$msg2" >> /dev/kmsg 2>/dev/null
        echo -n "$msg2"
    else
        echo "$msg1" >> /dev/kmsg 2>/dev/null
        echo "$msg1"
    fi
    return 0
}
hndmsg() {
    if [ -n "$msg" ]; then
        echo "$msg"
        echo "$msg" >> /dev/kmsg 2>/dev/null
        echo $log > /proc/sys/kernel/printk
        stty intr ^C
        exit 1
    fi
}
uperr() {
    exit 1
}
pipe_upgrade_rootfs_ubi() {
    local mtd_dev=mtd$1
    local package=$2
    if [ -f $package -a $1 ]; then
        klogger -n "Burning rootfs image to $mtd_dev ..."
        ubiformat /dev/$mtd_dev -f $package -s 2048 -O 2048 -y
        if [ $? -eq 0 ]; then
            klogger "Done"
        else
            klogger "Error"
            uperr
        fi
    fi
}
verify_rootfs_ubifs() {
    local mtd_devn=$1
    local temp_ubi_data_devn=9
    klogger "Check if mtd$mtd_devn can be attached as an ubi device ..."
    # Try attach the device
    ubiattach /dev/ubi_ctrl -d $temp_ubi_data_devn -m $mtd_devn -O 2048
    if [ "$?" == "0" ]; then
        klogger "PASSED"
        ubidetach -d $temp_ubi_data_devn
        return 0
    else
        klogger "FAILED"
        return 1
    fi
}
board_prepare_upgrade() {
    # gently stop pppd, let it close pppoe session
    ifdown wan
    timeout=5
    while [ $timeout -gt 0 ]; do
        pidof pppd >/dev/null || break
        sleep 1
        let timeout=timeout-1
    done
    # down backhauls
    #ifconfig eth3 down
    #ifconfig wl01 down
    #ifconfig wl11 down
    # clean up upgrading environment
    # call shutdown scripts with some exceptions
    wait_stat=0
    klogger "@Shutdown service "
    for i in /etc/rc.d/K*; do
        # filter out K01reboot-wdt and K99umount
        case $i in
            *reboot-wdt | *umount)
                klogger "$i skipped"
                continue
            ;;
        esac
        [ -x "$i" ] || continue
        # wait for high-priority K* scripts to finish
        if echo "$i" | grep -qE "K7"; then
            if [ $wait_stat -eq 0 ]; then
                wait
                sleep 2
                wait_stat=1
            fi
            klogger "  service $i shutdown 2>&1"
            $i shutdown 2>&1
        else
            klogger "  service $i shutdown 2>&1 &"
            $i shutdown 2>&1 &
        fi
    done
    # try to kill all userspace processes
    # at this point the process tree should look like
    # init(1)---sh(***)---flash.sh(***)
    klogger "@Killing user process "
    for i in $(ps w | grep -v "flash.sh" | grep -v "/bin/ash" | grep -v "PID" | grep -v watchdog | awk '{print $1}'); do
        if [ $i -gt 100 ]; then
            # skip if kthread
            [ -f "/proc/${i}/cmdline" ] || continue
            [ -z "`cat /proc/${i}/cmdline`" ] && {
                klogger " $i is kthread, skip"
                continue
            }
            klogger " kill user process {`ps -w | grep $i | grep -v grep`} "
            kill $i 2>/dev/null
            # TODO: Revert to SIGKILL after watchdog bug is fixed
            # kill -9 $i 2>/dev/null
        fi
    done
    # flush cache and dump meminfo
    sync
    echo 3>/proc/sys/vm/drop_caches
    klogger "@dump meminfo"
    klogger "`cat /proc/meminfo | xargs`"
}
board_start_upgrade_led() {
    gpio 1 1
    gpio 3 1
    gpio l 1000 2
}
board_system_upgrade() {
    local filename=$1
    uboot_mtd=$(grep '"0:APPSBL"' /proc/mtd | awk -F: '{print substr($1,4)}')
    crash_mtd=$(grep '"crash"' /proc/mtd | awk -F: '{print substr($1,4)}')
    #kernel0_mtd=$(grep '"kernel0"' /proc/mtd | awk -F: '{print substr($1,4)}')
    #kernel1_mtd=$(grep '"kernel1"' /proc/mtd | awk -F: '{print substr($1,4)}')
    rootfs0_mtd=$(grep '"rootfs"' /proc/mtd | awk -F: '{print substr($1,4)}')
    rootfs1_mtd=$(grep '"rootfs_1"' /proc/mtd | awk -F: '{print substr($1,4)}')
    os_idx=$(nvram get flag_boot_rootfs)
    rootfs_mtd_current=$(($rootfs0_mtd+${os_idx:-0}))
    rootfs_mtd_target=$(($rootfs0_mtd+$rootfs1_mtd-$rootfs_mtd_current))
    #kernel_mtd_current=$(($rootfs_mtd_current-2))
    #kernel_mtd_target=$(($kernel0_mtd+$kernel1_mtd-$kernel_mtd_current))
    #pipe_upgrade_uboot $uboot_mtd $filename
    #pipe_upgrade_kernel $kernel_mtd_target $filename
    pipe_upgrade_rootfs_ubi $rootfs_mtd_target $filename
    # back up etc
    rm -rf /data/etc_bak
    cp -prf /etc /data/etc_bak
}
upgrade_param_check() {
    if [ -z "$1" -o ! -f "$1" ]; then
        klogger "USAGE: $0 input.bin [1:restore defaults, 0:don't] [1:don't reboot, 0:reboot]"
        exit 1
    fi
    flg_ota=`nvram get flag_ota_reboot`
    if [ "$flg_ota" = "1" ]; then
        klogger "flag_ota_reboot is set ?"
        exit 1
    fi
    cur_ver=`cat /usr/share/xiaoqiang/xiaoqiang_version`
    klogger "Begin Ugrading..., current version: $cur_ver"
    sync
    model=`cat /proc/xiaoqiang/model`
    [ "$model" != "R4A" -a "$model" != "R3GV2" ] && echo 3 > /proc/sys/vm/drop_caches
}
upgrade_prepare_dir() {
    absolute_path=`echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"`
    mount -o remount,size=100% /tmp
    rm -rf /tmp/system_upgrade
    mkdir -p /tmp/system_upgrade
    if [ ${absolute_path:0:4} = "/tmp" ]; then
        file_in_tmp=1
        mv $absolute_path /tmp/system_upgrade/
    else
        file_in_tmp=0
        cp $absolute_path /tmp/system_upgrade/
    fi
}
upgrade_done_set_flags() {
    # tell server upgrade is finished
    [ -f /etc/config/messaging -a -f /sbin/uci ] && {
        /sbin/uci set /etc/config/messaging.deviceInfo.UPGRADE_STATUS_UPLOAD=0
        /sbin/uci commit
        klogger "messaging.deviceInfo.UPGRADE_STATUS_UPLOAD=`uci get /etc/config/messaging.deviceInfo.UPGRADE_STATUS_UPLOAD`"
        klogger "/etc/config/messaging : `cat /etc/config/messaging`"
    }
    # update nvram setting when upgrading
    if [ "$2" = "1" ]; then
        nvram set restore_defaults=1
        klogger "Restore defaults is set."
    else
        nvram set restore_defaults=2
    fi
    [ "$upkernel" = "true" ] && nvram set flag_ota_reboot=1
    nvram set flag_upgrade_push=1
    nvram commit
    if [ "$3" = "1" ]; then
        klogger "Skip rebooting..."
    else
        klogger "Rebooting..."
        reboot
    fi
}
uploadUpgrade() {
    [ "1" = "`cat /proc/xiaoqiang/ft_mode`" ] && return 0
    [ "YES" != "`uci -q get xiaoqiang.common.INITTED`" ] && return 0
    wanstatus=`ubus call network.interface.wan status | grep up | grep false`
    if [ "$wanstatus" = "" ];then
        logger stat_points_none upgrade=start
        [ -f /usr/sbin/StatPoints ] && /usr/sbin/StatPoints
    fi
}
#check pid exist
pid_file="/tmp/pid_xxxx"
if [ -f $pid_file ]; then
    exist_pid=`cat $pid_file`
    if [ -n $exist_pid ]; then
        kill -0 $exist_pid 2>/dev/null
        if [ $? -eq 0 ]; then
            klogger "Upgrading, exit... $?"
            exit 1
        else
            echo $$ > $pid_file
        fi
    else
        echo $$ > $pid_file
    fi
else
    echo $$ > $pid_file
fi
upgrade_param_check $1
# image verification...
uploadUpgrade
board_start_upgrade_led
# stop services
# board_prepare_upgrade
# prepare to extract file
filename=`basename $1`
upgrade_prepare_dir $1
cd /tmp/system_upgrade
# start board-specific upgrading...
klogger "Begin Upgrading and Rebooting..."
board_system_upgrade $filename $2 $3
# some board may reset after system upgrade and not reach here
# clean up
cd /
cap=700
curcap=`du -sk /tmp/system_upgrade/|awk '{print $1}'`
if [[ $curcap -gt $cap ]] ; then
    upkernel=true
fi
rm -rf /tmp/system_upgrade
upgrade_done_set_flags $1 $2 $3

支付宝消费券福利分享


支付宝扫码加入支付宝消费券活动

您可能感兴趣的文章

如果本文对你有帮助,那么请你赞助我,让我更有激情的写下去,帮助更多的人。
本站加入了Google AdSense,因为谷歌 AdSense 算是广告商里难得“有节操、有底线”的佼佼者,没有任何低俗、垃圾、恶心的广告,所有希望不要“一刀切”式的拦截广告

如无特殊说明,解压密码均为:aisoa.cn
本站附件分享,如附件失效,可以去找找看
诚通网盘附件、百度网盘附件正在以10KB/s的速度下载,请耐心等待。

支付宝打赏支付宝打赏微信打赏微信打赏