IOS Upgrade via TFTP — Copy Image, Verify MD5 & Update Boot Statement
Every production Cisco router and switch will require an IOS upgrade at some point — to patch a critical security vulnerability, enable a new feature, fix a known defect, or simply maintain support from Cisco TAC. The TFTP method is the most widely used approach for in-band upgrades: you place the new image on a TFTP server reachable by the device, transfer it to flash, verify its integrity with an MD5 checksum, update the boot statement, and reload. The entire procedure is performed from the CLI without physical access to the device — making it suitable for remote upgrades during maintenance windows.
The procedure requires careful attention to three potential failure points: flash space (the new image must fit in available flash — often requiring the old image to be deleted first), image integrity (the MD5 hash from Cisco's download page must match the hash computed on the device after transfer — any mismatch means a corrupt or tampered image that must never be booted), and boot statement order (IOS loads the first image it finds — if the boot statement is wrong or missing, the device may reboot into the old image or get stuck in ROMMON). Getting all three right is what separates a clean upgrade from an emergency recovery call at 3 AM. For saving configurations before and after the upgrade see Saving & Managing Cisco Configurations.
This lab covers the full upgrade workflow for both Cisco ISR
routers (IOS / IOS-XE) and Catalyst switches, flash space
management, TFTP server setup, the complete verification sequence,
and a ROMMON recovery procedure for the case where a bad upgrade
leaves the device unbootable. For recovering from a device that
will not boot at all — including using ROMMON's
tftpdnld command — see
ROMMON & Password
Recovery. For automating upgrades across a fleet of devices
see Ansible Playbook —
Automate IOS Configuration.
1. Core Concepts — Flash, Boot Sequence & Image Types
How Cisco IOS Locates and Loads an Image
IOS IMAGE SELECTION ORDER (evaluated at every boot):
Step 1 — Read config-register boot field (bits 0–3):
0x0 → Stay in ROMMON
0x1 → Load ROM image (mini-IOS / boot image)
0x2–0xF → Proceed to boot system statements
Step 2 — Check for 'boot system' statements in startup-config:
boot system flash:isr4300-universalk9.16.12.04.SPA.bin ← try first
boot system flash:isr4300-universalk9.16.09.06.SPA.bin ← try second (fallback)
boot system tftp:isr4300-universalk9.16.12.04.SPA.bin 192.168.1.100 ← tftp fallback
boot system rom ← ROM fallback
IOS tries each statement in ORDER — first one that succeeds wins.
If a file is not found, it tries the next statement.
If NO statements exist → loads first .bin file found in flash (alphabetical).
Step 3 — If no boot system statements AND no .bin file in flash:
→ Boots into ROMMON (rommon 1 >)
┌──────────────────────────────────────────────────────────────────┐
│ WHY EXPLICIT BOOT STATEMENTS MATTER │
│ │
│ Without a boot system statement, IOS loads the FIRST .bin file │
│ alphabetically in flash. After an upgrade where the OLD image │
│ was not deleted, you may have: │
│ flash:isr4300-universalk9.16.09.06.SPA.bin (old) │
│ flash:isr4300-universalk9.16.12.04.SPA.bin (new) │
│ │
│ Alphabetically, 16.09 comes before 16.12 — the device boots │
│ the OLD image after every reload until you add an explicit │
│ boot system statement pointing to the new one. │
│ │
│ Always set an explicit boot system statement after any upgrade. │
└──────────────────────────────────────────────────────────────────┘
IOS Image Filename Anatomy
Example: isr4300-universalk9.16.12.04.SPA.bin
isr4300 → Platform identifier (ISR 4300 series)
universal → Feature set: universal = all features, unlocked by licence
k9 → Encryption capable (supports IPsec, SSH, etc.)
16.12.04 → IOS-XE version: major.minor.maintenance (16.12.4)
SPA → Software type: SPA = Specific Platform Aggregated
.bin → Binary image file
Classic IOS example: c2960-lanbasek9-mz.152-7.E9.bin
c2960 → Platform (Catalyst 2960)
lanbasek9 → Feature set: LAN Base with encryption
mz → m = runs from RAM (decompressed), z = compressed in flash
152-7.E9 → Version 15.2(7)E9
.bin → Binary image
IOS-XE Packaging (16.x and later):
Newer IOS-XE uses a PACKAGE-based install instead of a single .bin:
show version → shows "packages.conf" as boot file
install add file flash:image.bin → adds to package repository
install activate → activates without full reload
install commit → makes permanent
This lab covers the traditional .bin file method (install mode
is covered separately in advanced upgrade procedures).
Flash Memory — Types and Locations
| Platform | Flash Location | IOS Command Reference | Typical Capacity |
|---|---|---|---|
| ISR 1900 / 2900 / 3900 | Onboard CompactFlash | flash: or flash0: |
256 MB – 1 GB |
| ISR 4000 series | Onboard flash + optional USB | bootflash: (primary), usb0: |
8 GB – 16 GB (bootflash) |
| Catalyst 2960 / 3560 | Onboard flash | flash: |
64 MB – 128 MB |
| Catalyst 3750 / 3850 | Onboard flash | flash: |
128 MB – 2 GB |
| Catalyst 9000 series | Onboard flash | flash: or bootflash: |
16 GB – 32 GB |
| ASR 1000 series | Hard disk + bootflash | harddisk:, bootflash: |
200 GB+ (harddisk) |
show flash: (or
show bootflash:) and verify sufficient free space
before starting the transfer.
2. Lab Topology & TFTP Server Setup
┌──────────────────┐ ┌─────────────────────────────────┐
│ TFTP Server │ │ NetsTuts_R1 (ISR 4321) │
│ 192.168.1.100 │──Gi0/0────│ Gi0/0: 192.168.1.1/24 │
│ Ubuntu / SolarWinds │ │ Current: IOS-XE 16.09.06 │
│ Tftpd64 / macOS│ │ Target: IOS-XE 16.12.04 │
└──────────────────┘ └─────────────────────────────────┘
│
┌────┴────┐
│ SW1 │
│Catalyst │
│ 2960 │
│Current: │
│15.2(7)E6│
│Target: │
│15.2(7)E9│
└─────────┘
TFTP Server Requirements:
OS: Windows (Tftpd64 / SolarWinds TFTP), Linux (tftpd-hpa),
or macOS (built-in tftpd)
IP: 192.168.1.100 (reachable from device management interface)
Root dir: Folder containing the .bin image file(s)
Firewall: UDP port 69 OPEN inbound on the TFTP server
(TFTP uses UDP 69 for requests, random high port for data)
IOS Image Files Required (obtain from cisco.com — CCO login needed):
Router: isr4300-universalk9.16.12.04.SPA.bin (approx 520 MB)
MD5 from Cisco download page: a3f8c12d... (record this)
Switch: c2960-lanbasek9-mz.152-7.E9.bin (approx 12 MB)
MD5 from Cisco download page: 7b4e91a2... (record this)
Management Connectivity:
Console cable connected (REQUIRED — you will reboot the device)
SSH / Telnet access to privileged exec confirmed
Ping from device to TFTP server succeeds before starting
Step 1 — Set Up the TFTP Server (Linux/Ubuntu)
# Install tftpd-hpa on Ubuntu/Debian $ sudo apt install tftpd-hpa # Configure TFTP root directory and options $ sudo nano /etc/default/tftpd-hpa TFTP_USERNAME="tftp" TFTP_DIRECTORY="/srv/tftp" # where image files must be placed TFTP_ADDRESS=":69" TFTP_OPTIONS="--secure --create" # --create allows uploads from device # Create root directory and set permissions $ sudo mkdir -p /srv/tftp $ sudo chown tftp:tftp /srv/tftp $ sudo chmod 777 /srv/tftp # Copy your IOS image to the TFTP root $ sudo cp ~/Downloads/isr4300-universalk9.16.12.04.SPA.bin /srv/tftp/ $ sudo cp ~/Downloads/c2960-lanbasek9-mz.152-7.E9.bin /srv/tftp/ # Start and verify the TFTP service $ sudo systemctl restart tftpd-hpa $ sudo systemctl status tftpd-hpa ● tftpd-hpa.service - LSB: HPA's tftp server Active: active (running) # Verify UDP 69 is listening $ sudo ss -ulnp | grep :69 UNCONN 0 0 0.0.0.0:69 0.0.0.0:* users:(("in.tftpd",...)) # Note the MD5 of the image on the server for later comparison $ md5sum /srv/tftp/isr4300-universalk9.16.12.04.SPA.bin a3f8c12d9e4b72f1c8d5a0e3b6f91234 isr4300-universalk9.16.12.04.SPA.bin
--create option in tftpd-hpa allows the Cisco
device to write a file to the TFTP server — needed if you
want to back up the current running-config or the old IOS
image to the server before upgrading. This is optional but
recommended as a safety measure. On Windows, Tftpd64 and
SolarWinds Free TFTP Server provide a GUI interface where you
set the root folder — place the .bin file in that folder and
the service handles the rest. Always record the MD5 hash of
the image on the TFTP server before transferring — this is
the reference value you will compare against after the copy.
3. Step 2 — Pre-Upgrade Checks on the Device
Run these checks on the router or switch before initiating any file transfer. Skipping pre-checks is the most common cause of mid-transfer failures and post-upgrade problems.
Check 1 — Verify Current IOS Version
Use show version to confirm the current IOS version, flash path, and config-register before any upgrade.
NetsTuts_R1#show version Cisco IOS XE Software, Version 16.09.06 Cisco IOS Software [Fuji], ISR Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.9.6, RELEASE SOFTWARE (fc3) ... cisco ISR4321/K9 (1RU) processor with 1647778K/6147K bytes of memory. Processor board ID FLM2044W0LT ... 4 Gigabit Ethernet interfaces 32768K bytes of non-volatile configuration memory. 8388608K bytes of physical memory. 7697408K bytes of flash memory at bootflash:. ← total flash ... Configuration register is 0x2102
bootflash: on ISR 4000, flash: on
ISR 1900/2900/3900 and Catalyst), and the config-register
value. The config-register must be 0x2102
(or similar normal value) before starting — if it shows
0x2142 from a previous password recovery that was not cleaned
up, fix it now before upgrading.
Check 2 — Verify Flash Space
! ── ISR 4000: use 'show bootflash:' ──────────────────────────────
NetsTuts_R1#show bootflash:
-#- --length-- -----date/time------ path
1 521347072 Mar 05 2026 09:14:22 isr4300-universalk9.16.09.06.SPA.bin
2 4096 Mar 05 2026 09:14:22 .installer/
3 1823744 Mar 05 2026 09:15:01 nvram:startup-config-20260305
7696801792 bytes available (789737472 bytes used) ← ~7.3 GB free
! ── New image is ~520 MB — 7.3 GB free is more than enough ────────
! ── ISR 1900/2900 or Catalyst: use 'show flash:' ─────────────────
NetsTuts_SW1#show flash:
Directory of flash:/
2 -rwx 12582912 Mar 05 2026 c2960-lanbasek9-mz.152-7.E6.bin ← old
3 -rwx 4414 Mar 05 2026 config.text
4 -rwx 736 Mar 05 2026 vlan.dat
64016384 bytes total (50511872 bytes available) ← ~48 MB free
! ── New switch image is ~12 MB — 48 MB free is sufficient ─────────
Check 3 — Verify TFTP Reachability
! ── Ping TFTP server from the management interface ─────────────── NetsTuts_R1#ping 192.168.1.100 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 192.168.1.100, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5) ! ── Extended ping to test with larger packets (TFTP uses 512-byte blocks) NetsTuts_R1#ping 192.168.1.100 size 1500 repeat 20 !!!!!!!!!!!!!!!!!!!! Success rate is 100 percent (20/20) ! ── If management VRF is used, specify it ──────────────────────── NetsTuts_R1#ping vrf Mgmt-intf 192.168.1.100
! replaced by .), fix the underlying
network issue before proceeding — do not attempt a large file
transfer over a lossy path.
Check 4 — Back Up Current Configuration
Back up the running-config before any changes. Ensure NTP is configured so backup filenames and logs have accurate timestamps.
! ── Save running-config to TFTP before any changes ─────────────── NetsTuts_R1#copy running-config tftp: Address or name of remote host []? 192.168.1.100 Destination filename [NetsTuts_R1-confg]? NetsTuts_R1-backup-20260307.cfg !! 1823 bytes copied in 0.204 secs (8937 bytes/sec) ! ── Optionally back up current IOS image to TFTP ───────────────── ! ── WARNING: this copies a 500MB+ file — only if TFTP has space ── NetsTuts_R1#copy bootflash:isr4300-universalk9.16.09.06.SPA.bin tftp: Address or name of remote host []? 192.168.1.100 Destination filename [isr4300-universalk9.16.09.06.SPA.bin]? !!!!!!!!!!!!!!!!... 521347072 bytes copied in 1234.567 secs (422465 bytes/sec)
4. Step 3 — Copy the New IOS Image to Flash
Router — Copy TFTP to bootflash (ISR 4000)
NetsTuts_R1#copy tftp: bootflash: Address or name of remote host []? 192.168.1.100 Source filename []? isr4300-universalk9.16.12.04.SPA.bin Destination filename [isr4300-universalk9.16.12.04.SPA.bin]? [press Enter — keep same filename] Accessing tftp://192.168.1.100/isr4300-universalk9.16.12.04.SPA.bin... Loading isr4300-universalk9.16.12.04.SPA.bin from 192.168.1.100 (via GigabitEthernet0/0/0): !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! [OK - 521347072 bytes] 521347072 bytes copied in 1187.234 secs (439151 bytes/sec)
! represents a UDP block successfully
received and written to flash. A . indicates
a timeout — the block was retransmitted. For a 500 MB image,
expect 1000+ exclamation marks. If the transfer shows
mostly dots and times out, the TFTP connection is unreliable —
abort with Ctrl+C, diagnose the network path, and retry.
TFTP transfer speed over a 1 Gbps LAN is typically
300–500 MB/s (throughput limited by flash write speed).
Over a WAN or slower management network, plan for 10–30
minutes per 500 MB image.
Router — Alternative: Direct URL Syntax
! ── Single-line copy with full URL (faster to type) ────────────── NetsTuts_R1#copy tftp://192.168.1.100/isr4300-universalk9.16.12.04.SPA.bin bootflash: Destination filename [isr4300-universalk9.16.12.04.SPA.bin]? [press Enter] !!!!!!!!!!!!!!!!!!!!!!!!!!!... 521347072 bytes copied in 1187.234 secs
Catalyst Switch — Copy TFTP to flash
NetsTuts_SW1#copy tftp: flash: Address or name of remote host []? 192.168.1.100 Source filename []? c2960-lanbasek9-mz.152-7.E9.bin Destination filename [c2960-lanbasek9-mz.152-7.E9.bin]? [press Enter] Accessing tftp://192.168.1.100/c2960-lanbasek9-mz.152-7.E9.bin... Loading c2960-lanbasek9-mz.152-7.E9.bin from 192.168.1.100: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! [OK - 12582912 bytes] 12582912 bytes copied in 35.211 secs (357348 bytes/sec)
Verify the File Was Written Correctly
! ── Check new image exists in flash ─────────────────────────────
NetsTuts_R1#show bootflash:
-#- --length-- -----date/time------ path
1 521347072 Mar 05 2026 09:14:22 isr4300-universalk9.16.09.06.SPA.bin ← old
2 521347072 Mar 07 2026 14:22:08 isr4300-universalk9.16.12.04.SPA.bin ← new ✓
7175454720 bytes available (1311883264 bytes used)
NetsTuts_SW1#show flash:
Directory of flash:/
2 -rwx 12582912 Mar 05 2026 c2960-lanbasek9-mz.152-7.E6.bin ← old
3 -rwx 12582912 Mar 07 2026 c2960-lanbasek9-mz.152-7.E9.bin ← new ✓
4 -rwx 4414 Mar 05 2026 config.text
5 -rwx 736 Mar 05 2026 vlan.dat
64016384 bytes total (37748736 bytes available)
5. Step 4 — Verify the MD5 Checksum
MD5 verification is mandatory — never boot a new IOS image without verifying its integrity first. A corrupted or tampered image can cause the device to boot into a broken state, crash mid-operation, or introduce security vulnerabilities. The MD5 hash from Cisco's software download page must match the hash computed on the device after transfer.
Where to Find the Official MD5 Hash
Source: software.cisco.com (requires CCO account)
When downloading an IOS image, the download page shows:
File name: isr4300-universalk9.16.12.04.SPA.bin
File size: 521,347,072 bytes
MD5 checksum: a3f8c12d9e4b72f1c8d5a0e3b6f91234 ← copy this exactly
SHA-512: 7b4e91a2f3c8d5e0a1b6c9d2e4f70123...
ALWAYS record the MD5 (or SHA-512) from the DOWNLOAD PAGE before
downloading — not from a secondary source or email.
You can also verify the file on the TFTP server (Linux):
$ md5sum /srv/tftp/isr4300-universalk9.16.12.04.SPA.bin
a3f8c12d9e4b72f1c8d5a0e3b6f91234
This gives you two reference points:
1. Cisco's official hash (from cisco.com download page)
2. Hash on the TFTP server before transfer
All three values must match: Cisco → TFTP server → device flash.
Verify MD5 on the Router
! ── Compute MD5 of the newly transferred image ─────────────────── ! ── WARNING: this takes 2–5 minutes for a 500 MB file ───────────── NetsTuts_R1#verify /md5 bootflash:isr4300-universalk9.16.12.04.SPA.bin .................................................................... .................................................................... .................................................................... Done! verify /md5 (bootflash:isr4300-universalk9.16.12.04.SPA.bin) = a3f8c12d9e4b72f1c8d5a0e3b6f91234 ! ── Compare against Cisco's published MD5: a3f8c12d9e4b72f1c8d5a0e3b6f91234 ! ── ✓ MATCH — image integrity confirmed, safe to proceed ───────── ! ── Optional: compare against a known-good hash in one command ─── NetsTuts_R1#verify /md5 bootflash:isr4300-universalk9.16.12.04.SPA.bin a3f8c12d9e4b72f1c8d5a0e3b6f91234 .................................................................... Verified (bootflash:isr4300-universalk9.16.12.04.SPA.bin) = a3f8c12d9e4b72f1c8d5a0e3b6f91234
Verify MD5 on the Switch
NetsTuts_SW1#verify /md5 flash:c2960-lanbasek9-mz.152-7.E9.bin ............................................ Done! verify /md5 (flash:c2960-lanbasek9-mz.152-7.E9.bin) = 7b4e91a2f3c8d5e0a1b6c9d2e4f70123 ! ── Compare with Cisco's value: 7b4e91a2f3c8d5e0a1b6c9d2e4f70123 ! ── ✓ MATCH — proceed to boot statement update ──────────────────
What to Do If MD5 Does Not Match
! ── MISMATCH EXAMPLE — do not proceed ──────────────────────────── verify /md5 (bootflash:isr4300-universalk9.16.12.04.SPA.bin) = ff00aa11bb22cc33dd44ee55ff66aa77 ! ── Cisco's value: a3f8c12d9e4b72f1c8d5a0e3b6f91234 ! ── These do not match — image is CORRUPT or TAMPERED ───────────── ! ── Delete the bad file ───────────────────────────────────────── NetsTuts_R1#delete bootflash:isr4300-universalk9.16.12.04.SPA.bin Delete filename [isr4300-universalk9.16.12.04.SPA.bin]? Delete bootflash:isr4300-universalk9.16.12.04.SPA.bin? [confirm] ! ── Diagnose before retrying ──────────────────────────────────── ! ── 1. Re-check the MD5 on the TFTP server itself ──────────────── ! $ md5sum /srv/tftp/isr4300-universalk9.16.12.04.SPA.bin ! If server MD5 ≠ Cisco's MD5 → re-download from cisco.com ! If server MD5 = Cisco's MD5 → transfer was corrupted ! ── 2. Check network for packet loss before retrying ───────────── ! ── 3. Re-download image from cisco.com if in doubt ────────────── ! ── NEVER BOOT AN IMAGE WITH A MISMATCHED MD5 ────────────────────
verify /md5
flash:[filename] multiple times; inconsistent results
indicate hardware issues). The MD5 algorithm detects any
single-bit change in the file — you cannot "mostly" pass MD5.
Either it matches exactly or the file is wrong.
6. Step 5 — Update the Boot System Statement
With the new image in flash and MD5 verified, update the boot configuration to point to the new image. This involves removing (or replacing) the old boot statement and adding the new one before the reload.
Router — Update Boot Statement (ISR 4000)
! ── Check current boot statements ──────────────────────────────── NetsTuts_R1#show running-config | include boot boot-start-marker boot system bootflash:isr4300-universalk9.16.09.06.SPA.bin boot-end-marker ! ── Remove old boot statement ──────────────────────────────────── NetsTuts_R1(config)#no boot system bootflash:isr4300-universalk9.16.09.06.SPA.bin ! ── Add new boot statement ─────────────────────────────────────── NetsTuts_R1(config)#boot system bootflash:isr4300-universalk9.16.12.04.SPA.bin ! ── Add the old image as a FALLBACK (best practice) ───────────── NetsTuts_R1(config)#boot system bootflash:isr4300-universalk9.16.09.06.SPA.bin ! ── Verify boot statements in running-config ───────────────────── NetsTuts_R1#show running-config | include boot system boot system bootflash:isr4300-universalk9.16.12.04.SPA.bin ← 1st (new) boot system bootflash:isr4300-universalk9.16.09.06.SPA.bin ← 2nd (fallback) ! ── Confirm config-register is correct ────────────────────────── NetsTuts_R1#show version | include register Configuration register is 0x2102
boot system
statement creates an automatic fallback — if the new image
is corrupt or fails to load for any reason, IOS automatically
tries the second statement and boots the old image. This is
a critical safety net in production. Without it, a failed
boot of the new image drops the device to ROMMON, requiring
manual intervention. With the fallback, the device self-heals
by loading the previous known-good image, keeping the network
operational until you can diagnose the issue.
Catalyst Switch — Update Boot Statement
! ── Check current boot statements ──────────────────────────────── NetsTuts_SW1#show running-config | include boot boot system flash:c2960-lanbasek9-mz.152-7.E6.bin ! ── Remove old boot statement ──────────────────────────────────── NetsTuts_SW1(config)#no boot system flash:c2960-lanbasek9-mz.152-7.E6.bin ! ── Add new boot statement ─────────────────────────────────────── NetsTuts_SW1(config)#boot system flash:c2960-lanbasek9-mz.152-7.E9.bin ! ── Add fallback to old image ──────────────────────────────────── NetsTuts_SW1(config)#boot system flash:c2960-lanbasek9-mz.152-7.E6.bin ! ── Verify ─────────────────────────────────────────────────────── NetsTuts_SW1#show running-config | include boot system boot system flash:c2960-lanbasek9-mz.152-7.E9.bin ← primary boot system flash:c2960-lanbasek9-mz.152-7.E6.bin ← fallback
Save Configuration Before Reload
! ── CRITICAL: save running-config — the new boot statements must ─ ! ── be in startup-config or they are lost on reload ────────────── NetsTuts_R1#copy running-config startup-config Destination filename [startup-config]? Building configuration... [OK] NetsTuts_SW1#copy running-config startup-config Building configuration... [OK] ! ── Verify the boot statements are in the startup-config ───────── NetsTuts_R1#show startup-config | include boot system boot system bootflash:isr4300-universalk9.16.12.04.SPA.bin boot system bootflash:isr4300-universalk9.16.09.06.SPA.bin ! ── Both confirmed in startup-config ─────────────────────────────
copy running-config startup-config
here and then reload, the device uses the startup-config that
still has the old boot system statement (or none at all), and
may not boot the new image. Always verify the boot statements
are present in show startup-config before issuing
the reload command.
7. Step 6 — Reload and Verify the New Version
Schedule and Execute the Reload
! ── Optional: schedule a reload with a delay (allows remote sessions ! to disconnect gracefully and gives you a window to abort) ────── NetsTuts_R1#reload in 5 Reload scheduled in 5 minutes by admin on vty0 (192.168.1.50) Proceed with reload? [confirm] ! ── To cancel a scheduled reload ──────────────────────────────── NetsTuts_R1#reload cancel *** *** --- SHUTDOWN ABORTED --- *** ! ── Immediate reload ───────────────────────────────────────────── NetsTuts_R1#reload System configuration has been modified. Save? [yes/no]: no ← type 'no' — we already saved manually; don't overwrite Proceed with reload? [confirm] [press Enter] ! ── Console output during reload ──────────────────────────────── *Mar 7 14:35:00.001: %SYS-5-RELOAD: Reload requested by admin on vty0. Reload Reason: Reload Command. System Bootstrap, Version 16.x ... Self decompressing the image: ##############... ... Cisco IOS XE Software, Version 16.12.04 ← new version loading
copy running-config startup-config. If you
answer yes, IOS does one final save — which is safe if the
running-config is correct, but if anything changed in the
running-config during the upgrade process that you did not
intend to keep, answering yes saves those changes. The safer
discipline is to save explicitly when you intend to save,
and say no to this prompt. Use reload in [minutes]
for production changes — it gives you a brief window to abort
if you suddenly realize something is wrong before the reload
executes.
Verify the New Version with show version
! ── After reload completes — verify new IOS version ───────────── NetsTuts_R1#show version Cisco IOS XE Software, Version 16.12.04 ← ✓ new version Cisco IOS Software [Gibraltar], ISR Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.12.4, RELEASE SOFTWARE (fc5) Technical Support: http://www.cisco.com/techsupport Copyright (c) 1986-2020 by Cisco Systems, Inc. Compiled Sun 05-Jan-20 13:48 by mcpre Cisco IOS-XE software, Copyright (c) 2005-2020 by cisco Systems, Inc. ... cisco ISR4321/K9 (1RU) processor with 1647778K/6147K bytes of memory. Processor board ID FLM2044W0LT Configuration register is 0x2102 ← ✓ correct register ! ── Verify on the switch ──────────────────────────────────────── NetsTuts_SW1#show version Cisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 15.2(7)E9 ← ✓ RELEASE SOFTWARE (fc3) ... Configuration register is 0xF ← note: switches use 0xF
Full Post-Upgrade Verification Sequence
! ── 1. Confirm version ─────────────────────────────────────────── NetsTuts_R1#show version | include Version Cisco IOS XE Software, Version 16.12.04 ! ── 2. Confirm running image path ──────────────────────────────── NetsTuts_R1#show version | include System image System image file is "bootflash:isr4300-universalk9.16.12.04.SPA.bin" ← ✓ ! ── 3. Confirm boot statements survived reload ─────────────────── NetsTuts_R1#show running-config | include boot system boot system bootflash:isr4300-universalk9.16.12.04.SPA.bin boot system bootflash:isr4300-universalk9.16.09.06.SPA.bin ! ── 4. Confirm config-register ─────────────────────────────────── NetsTuts_R1#show version | include register Configuration register is 0x2102 ! ── 5. Confirm all interfaces came back up ─────────────────────── NetsTuts_R1#show ip interface brief GigabitEthernet0/0/0 192.168.1.1 YES NVRAM up up GigabitEthernet0/0/1 10.0.12.1 YES NVRAM up up ! ── 6. Confirm routing protocols re-established ────────────────── NetsTuts_R1#show ip ospf neighbor Neighbor ID Pri State Dead Time Address Interface 2.2.2.2 1 FULL/DR 00:00:37 10.0.12.2 Gi0/0/1 ! ── 7. Optional: delete old image to reclaim flash space ───────── ! ── Only AFTER confirming new version is running correctly ──────── ! ── And AFTER removing the fallback boot statement ──────────────── NetsTuts_R1(config)#no boot system bootflash:isr4300-universalk9.16.09.06.SPA.bin NetsTuts_R1#copy running-config startup-config NetsTuts_R1#delete bootflash:isr4300-universalk9.16.09.06.SPA.bin Delete filename [isr4300-universalk9.16.09.06.SPA.bin]? Delete bootflash:isr4300-universalk9.16.09.06.SPA.bin? [confirm]
8. Emergency Recovery — ROMMON TFTP Download
If the device fails to boot after an upgrade — either because the image was corrupt, the boot statement pointed to a non-existent file, or flash was accidentally wiped — ROMMON provides a TFTP boot option. This is the last-resort procedure before returning the device to Cisco.
ROMMON Recovery via tftpdnld (ISR Routers)
! ── Device is stuck at rommon 1 > ─────────────────────────────── ! ── Set ROMMON environment variables for TFTP ─────────────────── rommon 1 > IP_ADDRESS=192.168.1.1 rommon 2 > IP_SUBNET_MASK=255.255.255.0 rommon 3 > DEFAULT_GATEWAY=192.168.1.254 rommon 4 > TFTP_SERVER=192.168.1.100 rommon 5 > TFTP_FILE=isr4300-universalk9.16.12.04.SPA.bin rommon 6 > GE_PORT=0 ← use GigabitEthernet0 (management port) ! ── Initiate TFTP download ─────────────────────────────────────── rommon 7 > tftpdnld IP_ADDRESS: 192.168.1.1 IP_SUBNET_MASK: 255.255.255.0 DEFAULT_GATEWAY: 192.168.1.254 TFTP_SERVER: 192.168.1.100 TFTP_FILE: isr4300-universalk9.16.12.04.SPA.bin GE_PORT: 0 Invoke this command for disaster recovery only. WARNING: all existing data in all partitions on flash will be lost! Do you wish to continue? y/n: [n]: y Receiving isr4300-universalk9.16.12.04.SPA.bin !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! [OK - 521347072/521347072 bytes] File reception completed. Booting flash:isr4300-universalk9.16.12.04.SPA.bin
tftpdnld command writes the image directly
to flash from ROMMON — it does NOT require IOS to be running.
The warning "all existing data in all partitions on flash will
be lost" is important: on some platforms (particularly ISR
1900/2900/3900), tftpdnld formats flash before
writing. Backup your config first if possible. On ISR 4000
platforms, tftpdnld writes to a specific partition and
preserves the startup-config in most cases. After the download
completes, ROMMON boots the image automatically. You will still
need to re-enter boot system statements and
copy running-config startup-config once IOS loads.
Catalyst Switch ROMMON Recovery (switch: prompt)
! ── Switch stuck at switch: prompt — flash is empty or corrupt ─── switch: set IP_ADDR 192.168.1.10 switch: set NETMASK 255.255.255.0 switch: set DEFAULT_ROUTER 192.168.1.1 switch: set TFTP_SERVER 192.168.1.100 switch: set TFTP_FILE c2960-lanbasek9-mz.152-7.E9.bin switch: tftp_init switch: ether_init ! ── Download and boot ──────────────────────────────────────────── switch: boot tftp://192.168.1.100/c2960-lanbasek9-mz.152-7.E9.bin Loading c2960-lanbasek9-mz.152-7.E9.bin from 192.168.1.100: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! [OK] Booting image...
Upgrade Troubleshooting Reference
| Symptom | Most Likely Cause | Resolution |
|---|---|---|
TFTP transfer shows %Error opening tftp://... |
TFTP server unreachable, wrong IP, UDP 69 blocked by firewall, or wrong source interface | Ping TFTP server first. Check firewall rules. Try copy tftp: flash: with explicit source: ip tftp source-interface [int]. See also SSH Configuration for SCP as a more secure alternative. |
Transfer starts but stalls with many dots (...) |
Network packet loss, TFTP server overloaded, or slow WAN link causing timeouts | Abort (Ctrl+C), delete partial file, diagnose network with ping/MTR, retry on better path |
%Error: Not enough space on device |
Flash does not have enough free space for the new image | Delete old image or other unused files. Verify with show flash: free bytes vs image size |
| MD5 mismatch after transfer | Transfer corruption, wrong image file on TFTP server, or flash write error | Delete the file, verify MD5 on TFTP server, check for network packet loss, retry transfer |
| Device boots old image after reload | Boot system statement saved but points to old image, or no boot system statement saved | Check show startup-config | include boot. Add/fix boot system statement, save, reload |
| Device drops to ROMMON after reload | Boot system statement points to a filename that does not exist in flash, or image is corrupt | From ROMMON: set correct filename and boot flash:[correct-filename], or use tftpdnld |
show version shows wrong version after reload |
Old image loaded as fallback (new image failed), or boot statement not saved before reload | Verify which image is actually running with show version | include System image. Re-check and fix boot statements |
| Interfaces down after upgrade | New IOS version uses different interface naming or a licence issue disabled some features | Check show ip interface brief. Re-apply no shutdown on affected interfaces. Verify licence with show licence |
9. Complete Upgrade Workflow & Key Points
End-to-End Upgrade Checklist
PRE-UPGRADE ✔ Download correct IOS image from cisco.com for your exact platform ✔ Record MD5 hash from the Cisco download page ✔ Place image in TFTP server root directory ✔ Verify TFTP service is running (UDP 69 listening) ✔ Back up device running-config to TFTP ✔ Check current IOS version: show version ✔ Check flash space: show flash: / show bootflash: ✔ Confirm TFTP reachability: ping [tftp-ip] ✔ Confirm config-register: 0x2102 (not 0x2142) ✔ Schedule maintenance window (reload = service disruption) DURING UPGRADE ✔ Copy image: copy tftp: bootflash: (or flash:) ✔ Verify file size matches: show bootflash: / show flash: ✔ Verify MD5: verify /md5 bootflash:[filename] [hash] ✔ Confirm MD5 matches Cisco's published value ✔ Update boot statement: remove old, add new (+ fallback to old) ✔ Save: copy running-config startup-config ✔ Confirm boot statements in startup-config ✔ Reload: reload (or reload in [minutes]) POST-UPGRADE ✔ Verify version: show version | include Version ✔ Verify running image: show version | include System image ✔ Verify boot statements: show running-config | include boot system ✔ Verify config-register: show version | include register ✔ Verify all interfaces up: show ip interface brief ✔ Verify routing protocols: show ip ospf neighbor / show ip route ✔ Run traffic/connectivity tests ✔ Wait 24–48 hours before deleting old image ✔ Delete old image + remove fallback boot statement + save
Key Points & Exam Tips
- MD5 verification is non-negotiable. Always run
verify /md5 flash:[image]after every TFTP transfer and compare against Cisco's published hash. A corrupt image may appear to boot initially but crash the device under load or introduce stability issues that are extremely difficult to diagnose. - Boot system statement order is a priority list. IOS tries each statement sequentially and boots the first image it successfully opens. New image first, old image as fallback — this order provides both an automatic upgrade and a self-healing fallback with zero additional effort.
- Save before reload — always. Boot system statements in the running-config are lost on reload if not saved. The sequence is: update boot statement →
copy running-config startup-config→ verify in startup-config →reload. No exceptions. - ISR 4000 uses
bootflash:; older ISR and Catalyst useflash:. Using the wrong filesystem prefix causes "file not found" errors. Always confirm the flash location withshow versionordir flash:/dir bootflash:before starting. - Never delete the old image until the new version is confirmed stable. The old image + fallback boot statement is your insurance policy. Remove it only after the device has run under real load for at least one business day.
- TFTP has no authentication or encryption. It is suitable for management-network-only file transfers. Never transfer IOS images over the public internet via TFTP — use SCP (
copy scp: flash:) for encrypted, authenticated file transfers in security-sensitive environments. See SSH Configuration for enabling SSH and SCP on the device. - The
installmode on IOS-XE 16.x+ (install add,install activate,install commit) provides in-service software upgrade (ISSU) on supported platforms — some models can upgrade without a full reload. The traditional .bin method in this lab applies to all platforms; install mode is the modern approach for high-availability environments. - On the CCNA exam: know the correct order of operations (copy → verify MD5 → update boot statement → save → reload → verify), the
verify /md5command syntax, the correct config-register value for normal operation (0x2102), and how to interpretshow versionoutput to confirm which image is running and where it was loaded from.
tftpdnld
procedure for re-imaging a completely failed flash. For
automating IOS upgrades across multiple devices simultaneously
using Ansible's ios_command and ios_config
modules see
Ansible Playbook —
Automate IOS Configuration. For using NAPALM's Python
library to manage IOS image deployment programmatically see
Python NAPALM Library.
For securing the file transfer itself with encryption, replace
TFTP with SCP — see
AAA Configuration
which covers enabling SSH and SCP on Cisco IOS.