通用 NOR 备份
基于 NAND 的设备应使用NAND-aware程序,因为dd
不能正确处理 NAND 闪存的纠错或坏块标记。
请查看file_system和flash 布局详细信息,并注意OpenWrt 仅涵盖firmware
部分。(引导程序)bootloader分区,ART
/NVRAM
和类似的分区不是OpenWrt的固件的一部分。如果出现问题并且这些分区上的数据意外损坏,您将无法通过公共 OpenWrt 源替换它!
由于 OpenWrt 不会写入这些分区,因此它们不太可能被 OpenWrt 本身损坏。但是,如果您想折腾bootloader部分,当然应该在您的 PC 上创建此数据的副本。否则,万一您丢失了该数据,您将不得不去论坛,让某人备份他的数据并发送给您,然后您必须更换MAC地址,然后通过port.jtag将其刷写,否则您的设备可能无法再启动。
创建 ART 备份
如果您的 ART 分区损坏了,您仍然可以启动 OpenWrt,只是您的无线设备无法正常工作。使用mtd
可以轻松修复。
dd if=/dev/$(sed -n -e '/:.*"art"/s///p' /proc/mtd) of=/tmp/art.backup
如果您的引导加载程序分区已损坏,您甚至无法使用bootloader的控制台(该控制台只能通过串行端口访问),唯一的恢复方法是通过JTAG 端口或通过拆焊闪存芯片,请参阅generic.debrick寻求帮助。
但是,一旦您已经准备好再次写入闪存,您仍然需要一些可以写入的东西,会起作用的东西。在这里,您的备份将派上用场:
dd if=/dev/mtd0 of=/tmp/boot.backup
然后通过 scp 或 ssh 将您的备份文件复制到您的 PC 上,并确保它们的安全以供您可能需要它们。
创建完整的 MTD 备份
该脚本假设在原生类 Unix 或 WSL 环境中使用Bash 和SSH。如果您更改了路由器的IP地址,请将 OPENWRT 变量值更改为OpenWrt 路由器的主机名/ IP。这会将您的 mtd 内容备份到mtd_backup.tgz
与脚本相同的文件夹中的压缩 tarball 文件中。
cat << "EOF" > mtdbk.sh #!/bin/bash set -e function die() { echo "${@}" exit 2 } OUTPUT_FILE="mtd_backup.tgz" OPENWRT="root@openwrt.lan" TMPDIR=$(mktemp -d) BACKUP_DIR="${TMPDIR}/mtd_backup" mkdir -p "${BACKUP_DIR}" SSH_CONTROL="${TMPDIR}/ssh_control" function cleanup() { set +e echo "Closing master SSH connection" "${SSH_CMD[@]}" -O stop echo "Removing temporary backup files" rm -r "${TMPDIR}" } trap cleanup EXIT # Open master ssh connection, to avoid the need to authenticate multiple times echo "Opening master SSH connection" ssh -o "ControlMaster=yes" -o "ControlPath=${SSH_CONTROL}" -o "ControlPersist=10" -n -N "${OPENWRT}" # This is the command we'll use to reuse the master connection SSH_CMD=(ssh -o "ControlMaster=no" -o "ControlPath=${SSH_CONTROL}" -n "${OPENWRT}") # List remote mtd devices from /proc/mtd. The first line is just a table # header, so skip it (using tail) "${SSH_CMD[@]}" 'cat /proc/mtd' | tail -n+2 | while read; do MTD_DEV=$(echo ${REPLY} | cut -f1 -d:) MTD_NAME=$(echo ${REPLY} | cut -f2 -d\") echo "Backing up ${MTD_DEV} (${MTD_NAME})" # It's important that the remote command only prints the actual file # contents to stdout, otherwise our backup files will be corrupted. Other # info must be printed to stderr instead. Luckily, this is how the dd # command already behaves by default, so no additional flags are needed. "${SSH_CMD[@]}" "dd if='/dev/${MTD_DEV}ro'" > "${BACKUP_DIR}/${MTD_DEV}_${MTD_NAME}.backup" || die "dd failed, aborting..." done # Use gzip and tar to compress the backup files echo "Compressing backup files to \"${OUTPUT_FILE}\"" (cd "${TMPDIR}" && tar czf - "$(basename "${BACKUP_DIR}")") > "${OUTPUT_FILE}" || die 'tar failed, aborting...' # Clean up a little earlier, so the completion message is the last thing the user sees cleanup # Reset signal handler trap EXIT echo -e "\nMTD backup complete. Extract the files using:\ntar xzf \"${OUTPUT_FILE}\"" EOF chmod +x mtdbk.sh ./mtdbk.sh
从 OpenWrt 创建完整的 MTD 备份
上述方法效果很好,但前提是您对路由器具有SSH根访问权限。在某些情况下,当您没有对路由器的SSH根访问权限,但可以从 UART 控制台连接时。例如带有原始官方固件的 TP-Link Archer C9 HW ver 5.0。您可以从路由器备份到您的主机。
# Save the script cat << "EOF" > /tmp/backup.sh #!/bin/sh BACKUP_HOST="pc.lan" BACKUP_USER="root" echo "Backup host ${BACKUP_HOST}" cat /proc/mtd | tail -n+2 | while read; do MTD_DEV=$(echo ${REPLY} | cut -f1 -d:) MTD_NAME=$(echo ${REPLY} | cut -f2 -d\") echo "Backing up ${MTD_DEV} (${MTD_NAME})" dd if=/dev/${MTD_DEV}ro | ssh -y ${BACKUP_USER}@${BACKUP_HOST} "dd of=~/${MTD_DEV}_${MTD_NAME}.backup" done EOF # Run the script sh /tmp/backup.sh
现在,您需要从 PC 为每个 mtd 设备输入5 次或更多次的SSH密码 。
操作完成后,您将在PC 上的用户主目录中找到所有文件。
如果您使用 linux 并希望查看进度,您可以在 PC 上的单独控制台中运行:
watch -n 0.2 ls -l --block-size=K ~
从引导加载程序创建备份
有时可能需要从原始固件备份设置/分区。根据引导加载程序,可能有不同的策略。
闪存芯片被映射到一个起始地址。使用 uboot 它应该在以下设置中:
printenv bdinfo
内存转储到串口(uboot: md ; redboot: dump)。将转储写入 tftp 或 nfs。
从引导加载程序控制台恢复备份
许多引导加载程序允许您使用 mtd 分区,但要注意:它们不必与内核 mtd 分区相同!此外,对于某些引导加载程序,您不能使用 mtd-partition,您必须使用偏移量。在后一种情况下,在进行备份时记下这些正确的偏移量可能是个好主意。
从 OpenWrt 控制台恢复备份
mtd write art.backup art
上述方法可能可以使用,但很可能无法正常使用,因为art分区通常不可写,因此您必须在做一些小修改后编译自己的内核。然后你必须把它刷到你的设备上,启动它,现在分区应该是可写的。