Investigating IBM LTO tape drive firmware
Posted on So 20 September 2026 in Reverse engineering
Hardware
Processor is identified as a 400MHz IBM PowerPC 405S, 32-bit big-endian by the embedded devicetree file.
132MiB of physical memory is mapped at 0x10000000.
There is a PLB running at 200MHz hosting a DMA engine and the OPB.
The OPB runs at 100MHz and claims any addresses > 0xA0000000 and the following devices live in this space:
- pirq interrupt controller @ 0xA0000600
- n16550 serial controller @ 0xEF600300
- axon ethernet rgmii @ 0xEF600790
- axon ethernet controller @ 0xEF600800
- 128MiB CFI NOR flash @ 0xF8000000, partitioned into 96MiB nvdfs and 32MiB bootimg
There is evidence of more unknown peripherals:
- 0xA0000F90
- 0xA0001000
- 0xA0010000
- 0xA0800000 maybe DDR SDRAM PHY
- 0xD0000000
- 0xEF640000
General image
Tape firmware container with "IBMTpDrv" magic.
Header format in 4 byte fields unless noted otherwise:
jump_instruction / image_size / checksum? / fw_version (4 char) / 0 / 0 / product_id (EBCDIC, 8 bytes) / IBMTpDrv magic ( 8 bytes) / ?? / ?? / ?? / ?? / directory_offset / directory_size / payload_start / ?? / ?? / ??
Section directory with variable number of slots (default 16 slots), each 32-byte, usually at offset 0x80.
Entry format in 4-byte fields:
name / attributes / file_offset / stored_size / memory_address / memory_size / ?? (0) / ?? (0)
- file_offset is counted from start of the file
Typical sections are fcod/text/roda/vmal/vmli/ramf/pcod/data/kmem/bss/stac/ocmd.
- fcod starts at offset 0 and contains the complete file header
Trailers, TLV coded, are stored after each stored section and not included in the directory. They appear as (usually 20 byte) gaps in the offsets+size covered by the directory.
Example: [80 00 00 04 VV VV VV VV][40 00 00 04 VV VV VV VV][00 00 00 00].
Schema is [TT 00 LL LL VV * length], LL LL is masked with 1F FF.
- not chained, both checksums only check the section they are placed after
- tag 0x80 = BE u32 sum mod 2^32
- tag 0x40 = GF(2^8) table transform T[i]=[i·38 i·CF i·38 i] mod 0x11D, init 0
There is a global trailer at the end of the file backwards TLV scheme starting from end of file, mirror of the section trailer scheme, with chained coverage.
New tags in global trailer:
- 0x20/0x10 : 256-byte objects, probably crypto signatures like RSA2048
- F0/F1 32-byte slots, at end, tombstone, all zeroes
Validator functions in code:
- ImageTableValidate (per-section, exact size match)
- ImageFileValidate (global backward walk, declared±0x80, required mask 0x50000000 = {0x40, 0x10}, sentinel 0x60000).
Two validator copies: fcod (10a026xx) file-level, pcod (112048xx) section-level clone. GF(2^8) table @ 11A10000 = in BSS, used by pcod, runtime-initialized.
fcod @ 0x00 → 0x10A00000 ~18kb
Startup code, includes global file header
Functions right at the start of section set up CPU/TLB/memory map, after that there are functions concerned with firmware update, e.g. checking the firmware image, erasing flash, writing flash, NOR flash unlock and communication, serial logging, flash verify.
The fcod section looks very minimal and self-contained and contains a DTB right at the end:
- PowerPC 405S, ibm,jag5 / ibm,ltox
- 132MB RAM @ 0x10000000
- flash 0xF8000000 128MB
- nvdfs 96MB + bootimg 32MB partitions
text @ 0x4834 → 0x11220000 ~4.5kb
FCOD functions for booting the Linux kernel, like checking ELF images, initrd, devicetree and doing CPU and memory setup.
roda @ 0x5A78 → 0x11300000 ~2kb
Lots of strings for fcod that make it easy to identify firmware update code and kernel bootloader.
vmal @ 0x61D0 → 0x11300744 ~7.5kb
Loaded directly after roda. All zeroes.
vmli @ 0x8000 → 10B00000 ~1.6MB
- last 4 bytes are a BE32 size in bytes
- Entry stub b + 0x250 / 0x280
- magic LTOxMCP @ +4
- GOT @ pcod +0xA5B0 (in main image terms pcod file off 0x644BE4 + 0xA5B0 = 0x64F194..0x64F1E4), self-referential r30=PC+0x125B0.
- Bootloader with minimal DTB and gzipped Linux kernel
- no standard uImage, zImage, etc.
- Supposedly standard linker layout for embedded PPC Linux without bootloader?
ramf @ 0x1A3558 → 10D00000 ~4.6MB initrd.
- last 4 bytes are BE32 size in bytes
- XZ-compressed CPIO archive (initrd)
- reported as defective by xzcat due to length bytes at the end
- minimalist environment, /bin is busybox, sysv-like init with shell scripts, network config with shell scripts
- based on RHEL7? glibc 2.17
- /drv contains tape drive operating software
- /nvd is the "nvdfs" partition from earlier, formatted with ubifs, contains non-volatile files
- dropbear is part of debug build, missing form production
Tape drive software
- /drv/dcode.exe is a BE32 PPC ELF executable, operates most of the drive
- /drv/scode.bin is loaded by dcode.exe
- scode.bin contains lots of drive debug and manufacturing diagnostics code with lots of strrings that indicate function
pcod @ 0x00644BE4 → 0x11200000 exactly 128kb
Nested IBMTpDrv container (dir @ 0x50, 16 32-byte slots, magic is the same)
Sections :
- text @ 0x2DE4 → 11A00000,
- roda @ 0x6048 → 11A10000,
- data @ 0x6FB8 → 11A20000,
- bss → 11A30000 +0x201000,
- rese @ 0x0001FFFC→ 0xFFFFFFFC
- ocmt → 0x07FD0000
- ocmb → 0x06000000
- comm → 0x00000000
- ocmd → 0x06000000 (flash controller offset?).
Functionality:
- Adler-32 (zlib NMAX 5552, unroll 16) found in pcod, likely inflate consumer.
- Flash writing and serial output
data @ 0x00664BF8 → 0x11400000 4 bytes
4 bytes of zeroes, last section warked as stored with file contents
memory only sections
(Linux) kernel memory, BSS section, Stack section, and ocmd may be the flash controller registers.
- kmem → 0x10000000 size 0x00A00000
- bss → 0x11500000 size 0x0061001C
- stac → 0x11C00000 size 0x00010000
- ocmd → 0x06000000 size 0x00000104
TODO
IBM 3592 Hardware Reference / Maintenance Information 3592 SCSI Reference documents a lot of vendor-unique behavior, log pages, and diagnostic commands.
IBM Redbooks on TS1150 / TS4500
ITDT (IBM Tape Diagnostic Tool) check out drive dumps
IBM patents on tape servo, LTM/DSP, and formatter design — IBM patents their tape work heavily and the figures are often block diagrams of the real silicon.
FCC/teardown photos