Project overview

Flash installation

On this page

This is the normal way to use this firmware. After installation the router boots OpenWrt by itself and keeps its settings across power cycles.

The procedure below writes only the kernel and the root filesystem. The bootloader, the hwsetting area that holds your MAC addresses, the vendor configuration, and the vendor JFFS2 partition are not written. That is what makes the rollback in this guide possible.

What you need

ItemRequirement
ComputerWindows, Linux, or macOS with Python 3
NetworkEthernet cable from the computer directly to a router LAN port
Computer addressStatic 192.168.1.50, mask 255.255.255.0
Firmware imagefirmware/openwrt-rtkmipsel-rtl8197f-hh71vm-fwupg.bin from the flash bundle
Free disk spaceAbout 16 MiB for the stock backup
UART adapterNot required

Disconnect or disable any other interface on 192.168.1.0/24 so that the transfers cannot go to the wrong adapter.

Download the latest flash bundle and its SHA-256 file. Verify the ZIP before extracting it, then open PowerShell, Command Prompt, or a terminal in the extracted hh71vm-openwrt-flash-bundle directory. Cloning the source repository is not required.

Host firewall

The tools transfer files over TFTP, and the router replies from a port other than 69. Allow inbound UDP for the Python interpreter you will run. On Windows this is a rule for the specific python.exe; a rule created for a different interpreter will not apply.

The backup step makes the router send its flash contents to your computer, so your computer acts as the TFTP server. Without the inbound UDP rule the backup will time out.

1. Verify the bundle and image

Verify the downloaded ZIP against hh71vm-openwrt-flash-bundle.zip.sha256.

Windows PowerShell:

powershell
$expected = (Get-Content .\hh71vm-openwrt-flash-bundle.zip.sha256 -Raw).Split()[0]
$actual = (Get-FileHash .\hh71vm-openwrt-flash-bundle.zip -Algorithm SHA256).Hash
if ($actual -ne $expected) { throw "Flash bundle checksum mismatch" }

Linux:

sh
sha256sum -c hh71vm-openwrt-flash-bundle.zip.sha256

macOS:

sh
shasum -a 256 -c hh71vm-openwrt-flash-bundle.zip.sha256

After extraction, verify every bundled file on Windows, Linux, or macOS:

text
python verify_bundle.py

The command prints the exact immutable Release tag. Stop if either check fails.

You can also inspect the firmware image directly.

Windows PowerShell:

powershell
Get-FileHash -Algorithm SHA256 firmware/openwrt-rtkmipsel-rtl8197f-hh71vm-fwupg.bin

Windows Command Prompt:

bat
certutil -hashfile firmware\openwrt-rtkmipsel-rtl8197f-hh71vm-fwupg.bin SHA256

Linux or macOS:

sh
sha256sum firmware/openwrt-rtkmipsel-rtl8197f-hh71vm-fwupg.bin

Compare the result with the bundled SHA256SUMS. Record the exact Release tag and image SHA-256 for recovery and bug reports.

2. Back up your stock firmware

The installer performs the backup itself as its first step, from the running stock firmware, and writes it to the directory you name. Keep that directory, and copy it somewhere else as well.

The backup is read over Telnet and TFTP from the stock Realtek system, so for this step the router must be running its original firmware and reachable at its normal address, with Telnet enabled. Follow the stock Telnet access guide before starting the backup. The installer connects to port 2323 by default, matching the primary method in that guide. If you used its marker-only fallback on the default Telnet port, add --telnet-port 23 to the dry-run and installation commands.

3. Install

Run the dry run first. It checks the image, builds the write plan, saves or verifies the stock backup over Telnet, and stops before entering the bootloader or writing flash:

text
python tools/flash/install_openwrt_lan.py --image firmware/openwrt-rtkmipsel-rtl8197f-hh71vm-fwupg.bin --backup-dir backup-stock --dry-run

To validate only the local image and write plan without contacting the router, explicitly skip the backup in dry-run mode:

text
python tools/flash/install_openwrt_lan.py --image firmware/openwrt-rtkmipsel-rtl8197f-hh71vm-fwupg.bin --dry-run --skip-backup --yes --pc-ip 192.168.1.50

This command does not transfer anything to the router. Do not carry --skip-backup --yes over to the real installation unless you accept the warning below.

If the dry run reports no problem, run the installation. It verifies and reuses the backup already stored in backup-stock; it does not download the partitions again:

text
python tools/flash/install_openwrt_lan.py --image firmware/openwrt-rtkmipsel-rtl8197f-hh71vm-fwupg.bin --backup-dir backup-stock

The tool then:

  1. verifies the image and builds the write plan;
  2. saves the 16 MiB stock backup into backup-stock, or verifies the existing copy;
  3. asks you to put the router into its bootloader console;
  4. waits until the bootloader answers on the network;
  5. writes the root filesystem, then the kernel;
  6. lets the board restart itself after the kernel is written.

When the tool asks for the bootloader console:

  1. disconnect router power;
  2. press and hold the WPS button;
  3. apply power while still holding WPS;
  4. keep holding it for about 12 seconds, then release.

The bootloader brings Ethernet up on 192.168.1.6 by itself. The tool waits for it to answer and stops without sending a single byte if it does not, so a missed button press is not dangerous.

Do not interrupt the tool between the two sections. The bootloader is single-threaded: after it accepts a section it goes away to write flash and answers nothing at all for tens of seconds. The tool waits for that on its own.

4. First boot

The first boot after installation takes about two minutes. During it the system erases the settings partition, which still holds part of the old stock root filesystem. This is normal and it is not a hang. Later boots are fast.

For the first minute or two after a fresh installation, SSH may refuse the empty root password while the settings partition is still being built. LuCI accepts you during the same period. It resolves by itself.

5. Check the result

text
ping 192.168.1.1
ssh -o HostKeyAlgorithms=+ssh-rsa [email protected]

LuCI is at http://192.168.1.1/.

If the browser shows Bad Request or the old vendor page, it still has the vendor interface cached for that address. Reload, or clear site data for 192.168.1.1.

On the router:

sh
cat /etc/openwrt_release
cat /proc/mtd
ubus call hh71vm-modem status

Set a root password and change both Wi-Fi keys before connecting anything else. The defaults are published in the README.

Then work through the testing guide and send a compatibility report.

Updating an installed system

New images include autosysupgrade, which downloads and verifies the latest production Release, runs the OpenWrt image compatibility check, and asks for confirmation before changing flash:

sh
autosysupgrade

It verifies the signed release.json against the public key embedded in the read-only firmware, then verifies the image SHA-256. The confirmation warns that the router can remain unavailable for approximately 5-7 minutes. Use autosysupgrade -n for a clean installation that does not preserve the current configuration. autosysupgrade --check performs all download, signature, checksum, and compatibility checks without starting an upgrade.

The same signed update path is available in System > Backup / Flash Firmware. The Firmware Updates & Upgrade section shows the installed build, checks the newest five GitHub Releases, and displays a signed changelog when one was published for a build. Check Updates does not download or install firmware. Upgrade Firmware repeats the release verification, downloads the selected immutable image, verifies its SHA-256 and platform compatibility, and asks for a final confirmation before installing it with settings preserved. The download runs on the router in the background, so a slow mobile link cannot cut it off; the page follows it and reports a failure instead of waiting for a reboot that is not coming. From SSH, autosysupgrade --job-json shows the same progress.

For older images without this command, use the OpenWrt updater manually. No installation tool and no button press is needed. Download the latest sysupgrade image and verify it against the SHA256SUMS from the same Release before copying it to the router.

The image has no SFTP server, so copy the file with legacy SCP mode. Dropbear only offers the SHA-1 ssh-rsa host key, which current OpenSSH releases do not accept by default, so scp needs the same option as ssh:

text
scp -O -o HostKeyAlgorithms=+ssh-rsa openwrt-rtkmipsel-rtl8197f-hh71vm-sysupgrade.bin [email protected]:/tmp/

Then, on the router:

sh
sysupgrade -v /tmp/openwrt-rtkmipsel-rtl8197f-hh71vm-sysupgrade.bin

Settings are kept. To install a clean system instead, add -n:

sh
sysupgrade -n -v /tmp/openwrt-rtkmipsel-rtl8197f-hh71vm-sysupgrade.bin

Rolling back to your stock firmware

This uses the backup from step 2 and the same button-and-network path as the installation. No UART is needed.

text
python tools/flash/restore_stock_lan.py --backup-dir backup-stock --dry-run
python tools/flash/restore_stock_lan.py --backup-dir backup-stock

The tool restores the stock kernel, root filesystem, and the stock data that occupied rootfs_data. The bootloader, MAC area, vendor configuration, and vendor JFFS2 were never overwritten by OpenWrt, so the tool deliberately leaves those original bytes in place.

The restore sections do not restart the board. After the tool finishes, disconnect and reconnect power without holding WPS. The router then boots the restored stock firmware. Nothing opens a terminal for you; use the stock interface as you did before.

If you have a UART adapter

UART is not required for anything above. These alternatives exist and were used during development:

SituationTool
Install from a running stock system, over its serial consoleflash_openwrt_vendor.py
Install when no working system is left on the deviceflash_openwrt_tftp.py
Roll back with the serial console availablerestore_stock.py

Each of them prints its plan before touching the port, and each supports --dry-run. The serial console is 38400 8N1 on the Realtek side; see the RAM boot guide for the pinout photo and wiring rules.

Close every other program using the serial port first. Only one program can own it.

If something goes wrong

The tool never saw the bootloader. The router is untouched: the tool stops before sending anything. Power off, hold WPS for the full 12 seconds while applying power, and check that your computer is on 192.168.1.50/24 with no other adapter on that subnet.

The installation stopped partway. The bootloader console is reachable the same way at any time, because it lives in a region that is never written. Repeat the installation, or run tools/flash/restore_stock_lan.py with your backup.

The router does not boot at all. Use the same WPS-at-power-on path with your backup and tools/flash/restore_stock_lan.py. It does not need a working system on the device.

A configuration change locked you out. Reinstalling the firmware does not help: the settings live in a partition that installation never writes, so the same configuration comes back on the next boot. Clear it with the RESET button, or with tools/flash/reset_openwrt.py if the router no longer boots. See factory-reset.md.

Nothing works and there is no backup. Do not use a dump from another device. Recovery then requires an SPI flash programmer and a verified full-chip image from the same unit. This is why step 2 exists.

From the project repositoryRevision 201b0e1