A collection of tools to extract files from QNX filesystem images and standalone QNX compressed-ELF files. The suite supports QNX Compressed-EFS, QNX IFS (Image File System), and individual compressed ELF payloads using LZO, UCL, and zlib where applicable.
- efsdump - QNX Compressed-EFS filesystem extractor
- ifsdump - QNX IFS (Image File System) extractor
- decompress-qnx-elf - Standalone QNX compressed-ELF decompressor for files beginning with
"iwlyfmbp"
QNX Compressed-EFS is a specialized filesystem format used in QNX real-time operating systems, particularly in embedded devices. Unlike regular EFS, this variant compresses file data using either LZO or UCL compression algorithms to reduce storage requirements in resource-constrained environments.
The QNX Compressed-EFS filesystem is organized in a hierarchical structure:
Flash Image
├── Partition 0 (Boot partition)
│ ├── Boot Info (QSSL_F3S signature)
│ ├── Unit Info (alignment, unit size)
│ └── Units (logical blocks)
│ ├── Unit 1
│ ├── Unit 2
│ └── ...
└── Partition 1 (Application partition)
├── Boot Info
├── Unit Info
└── Units
Located at the beginning of each partition, contains:
sig[8]: Filesystem signature ("QSSL_F3S")rev_major,rev_minor: Version informationunit_total: Total number of logical unitsunit_spare: Number of spare unitsroot: Extent pointer to root directory
Describes the layout and alignment of logical units:
unit_pow2: Log2 of unit size (typically 16 = 64KB units)endian: Endianness indicatorboot: Pointer to boot info structure
Each logical unit contains multiple extents with headers:
text_offset_hi,text_offset_lo: 48-bit offset to file datatext_size: Size of the file/directory datanext: Pointer to next extent in chainstatus[3]: Status flags including extent type
Directory entries contain metadata about files and subdirectories:
struct_size: Size of the directory entrynamelen: Length of the filenamestat: File statistics (mode, uid, gid, timestamps)first: Pointer to first extent containing file dataname: Variable-length filename
The filesystem uses different extent types:
EXTTYPE_XIP(0): Execute-in-place extentsEXTTYPE_SYS(1): System/metadata extentsEXTTYPE_DIR(2): Directory entriesEXTTYPE_FILE(3): File data extents
Files in the compressed-EFS use one of two compression methods:
Files are identified as compressed by examining the first 8 bytes for the magic signature "iwlyfmbp".
sig[8]: Magic signature "iwlyfmbp"usize: Uncompressed file sizecmptype: Compression type (0=LZO, 1=UCL)blksize: Block size for decompression
Compressed files are divided into blocks:
next: Offset to next block (0 = last block)usize: Uncompressed size of this blockprev,pusize: Previous block metadata
Compressed headers and block headers are parsed as little-endian values. File data is streamed through extent chains directly; current efsdump no longer creates temporary compressed payload files.
The filesystem uses a directory-centric traversal model where:
- Root Directory: The filesystem starts with a root directory entry pointed to by
boot_info.root - Directory Contents: Each directory entry contains an extent chain (
firstpointer) that lists its contents - Extent Chains: Following the
nextpointers in extent headers traverses all items within a directory - Recursive Structure: Subdirectories have their own extent chains containing their contents
1. Start at root directory (from boot_info.root)
2. Read directory entry
3. Follow first extent pointer to get directory contents
4. For each extent in the chain (following next pointers):
a. If extent type is DIR:
- Parse as directory entry
- If it's a subdirectory, recursively process its contents
- If it's a file, extract the file data
b. Move to next extent in chain
5. Continue until all extents processed
read_partition(): Reads partition boot info and unit structureread_dirent(): Reads directory entries with endianness conversionread_stat(): Reads file statisticsswap16(),swap32(): Endianness conversion utilities
traverse_directory(): Entry point for filesystem traversalread_directory_contents(): Reads contents of a directory using extent chainsfind_file_extent(): Locates file data extents
extract_file_data(): Main file extraction dispatcherextract_compressed_file_data(): Handles LZO/UCL compressed filesextent_reader_read(): Streams raw or compressed payload bytes across chained file extents
- LZO decompression:
lzo1x_decompress_safe() - UCL decompression:
ucl_nrv2b_decompress_safe_8()
-
Initialization
- Parse command line arguments
- Initialize LZO and UCL libraries
- Open filesystem image
-
Partition Discovery
- Read all partitions from the image
- Parse boot info and unit structures
- Build logical unit mapping
-
Directory Traversal
- Start from root directory of each partition
- Use directory-centric approach to read contents
- Follow extent chains to enumerate all files/directories
-
File Extraction
- Detect compression by examining file headers
- Stream file data across extent chains
- Decompress using appropriate algorithm (LZO/UCL)
- Write extracted files to target directory
-
Cleanup
- Free allocated memory
- Close file handles
# Extract all partitions to current directory
./efsdump filesystem.bin
# Extract to specific directory
./efsdump -d /tmp/extracted filesystem.bin
# List all partitions in image
./efsdump -l filesystem.bin
# Extract specific partition
./efsdump -p 0 filesystem.bin
# List contents without extracting
./efsdump -c filesystem.bin
# Verbose extraction
./efsdump -v filesystem.bin| Option | Long Option | Description |
|---|---|---|
-d DIR |
--directory DIR |
Extract to directory DIR (default: current directory) |
-l |
--list-partitions |
List all partitions in the image |
-p NUM |
--partition NUM |
Extract only partition NUM (0-based, default: all) |
-c |
--list-contents |
List contents without extracting files |
-v |
--verbose |
Enable verbose output |
-h |
--help |
Show help message |
# First, see what partitions are available
./efsdump -l unknown_image.bin
# List contents of first partition
./efsdump -p 0 -c unknown_image.bin
# Extract with verbose output to see what's happening
./efsdump -v -d extracted unknown_image.bin# Extract only the application partition (usually partition 0)
./efsdump -p 0 -d app_files image.bin# Verbose listing to understand filesystem structure
./efsdump -v -c image.bin
# Extract with full debugging output
./efsdump -v -d debug_output image.binFound 2 partition(s) in image.bin:
Partition 0:
Boot Info: QSSL_F3S (Rev 3.0), 48 units
Root: unit=1, index=3
Partition 1:
Boot Info: QSSL_F3S (Rev 3.0), 29 units
Root: unit=1, index=3
d ./bin
f ./bin/mkfilesystems.sh (1006 bytes)
f ./bin/puptool (14369 bytes)
d ./etc
f ./etc/passwd (373 bytes)
f ./etc/services (2048 bytes)
d ./etc/ntp
f ./etc/ntp/ntp.conf (256 bytes)
Format: <type> <path> [(<size> bytes)]
d: directoryf: file
Shows detailed information about:
- Partition boot info and unit structure
- Directory traversal process
- File extraction details
- Compression information
- Block-by-block decompression progress
Current efsdump includes several safeguards for malformed or partially erased dumps:
- Bounded parsing and checked binary reads for core metadata structures
- Directory traversal cycle detection
- File extent cycle detection
- Streaming extraction to avoid buffering entire files in memory
- Non-fatal handling for unreadable trailing/erased logical units
- Per-file errors do not abort the whole filesystem extraction
Some files inside QNX Compressed-EFS images are standalone compressed ELF payloads. These files start with the magic signature "iwlyfmbp" and contain a little-endian compression header followed by LZO or UCL compressed blocks. decompress-qnx-elf decompresses one such file directly without requiring a filesystem image.
# Positional output path
./decompress-qnx-elf test_elf/app app.elf
# Output path via option
./decompress-qnx-elf -o ntpd.elf test_elf/ntpd
# Verbose block-level decompression details
./decompress-qnx-elf -v test_elf/sdi sdi.elf| Option | Long Option | Description |
|---|---|---|
-o FILE |
--output FILE |
Write decompressed ELF to FILE |
-v |
--verbose |
Print block-level details |
-h |
--help |
Show help message |
The output is the decompressed ELF file. For example, the sample inputs in test_elf/ decompress to QNX 32-bit ELF executables:
./decompress-qnx-elf test_elf/app test_elf/app.elf
file test_elf/app.elfQNX IFS (Image File System) is the primary filesystem format used in QNX operating systems for creating bootable system images. Unlike EFS, IFS stores the entire filesystem as a single continuous image with an integrated directory structure, making it ideal for embedded systems that need fast boot times and efficient storage.
The QNX IFS image is organized as a linear structure:
QNX IFS Image
├── Startup Header (optional)
│ ├── Signature (0x00ff7eeb)
│ ├── Boot configuration
│ ├── System parameters
│ └── Compression information
├── Compressed/Raw Image Data
│ ├── Startup code (if present)
│ └── Filesystem payload
└── Image Filesystem
├── Image Header ("imagefs" signature)
├── Directory Table
├── File Data Blocks
└── Image Trailer (checksum)
Optional header found at the beginning of bootable images:
signature: Magic number 0x00ff7eebversion: Header version informationflags1,flags2: Control flags including compression and endiannessstartup_size: Size of startup code in bytesstored_size: Total size of stored imageimagefs_paddr: Physical address of image filesystemimagefs_size: Size of image filesystempaddr_bias: Physical address bias for relocation
Core filesystem header with "imagefs" signature:
signature[7]: Magic signature "imagefs"flags: Filesystem flags (endianness, readonly, etc.)image_size: Total size of the image filesystemhdr_dir_size: Size of header + directory tabledir_offset: Offset to directory table from header startboot_ino[4]: Inode numbers for boot filesscript_ino: Inode number for boot scriptmountpoint: Variable-length mount point string
Common attributes for all filesystem entries:
size: Size of this directory entry structureextattr_offset: Offset to extended attributesino: Inode numbermode: File type and permissions (standard Unix mode bits)gid,uid: Group and user IDsmtime: Modification timestamp
Regular file entries in the directory table:
attr: Common attributes (image_attr)offset: Offset to file data from image startsize: Size of file data in bytespath: Variable-length file path string
Directory entries in the directory table:
attr: Common attributes (image_attr)path: Variable-length directory path string
Symbolic link entries:
attr: Common attributes (image_attr)sym_offset: Offset within path string to symlink targetsym_size: Size of symlink target stringpath: Variable-length path string containing both link path and target
Device file entries (character, block, FIFO, etc.):
attr: Common attributes (image_attr)dev: Device numberrdev: Raw device number for special filespath: Variable-length device path string
IFS uses standard Unix file type indicators in the mode field:
S_IFREG(0100000): Regular fileS_IFDIR(0040000): DirectoryS_IFLNK(0120000): Symbolic linkS_IFCHR(0020000): Character deviceS_IFBLK(0060000): Block deviceS_IFIFO(0010000): Named pipe (FIFO)S_IFNAM(0050000): Named special file
IFS images can be compressed using multiple algorithms:
Compression is indicated by flags in the startup header:
flags1 & STARTUP_HDR_FLAGS1_COMPRESS_MASKdetermines compression type- Supported types: None (0), zlib (4), LZO (8), UCL (12)
- zlib: Standard deflate compression using gzip-compatible format
- LZO: High-speed compression optimized for decompression performance
- UCL: Ultra-compact compression for minimal storage requirements
- Read startup header to determine compression type
- Copy uncompressed startup code to temporary file
- Decompress remaining image data using appropriate algorithm
- Process the decompressed filesystem normally
Unlike EFS, IFS uses a linear directory table approach:
- Single Directory Table: All entries stored sequentially in one table
- Variable-Length Entries: Each entry has a size field for proper parsing
- Path-Based Organization: Full paths stored with each entry
- Type-Based Processing: Entry type determined by mode field
1. Locate image header using "imagefs" signature
2. Calculate directory table position (header + dir_offset)
3. Read directory entries sequentially:
a. Read image_attr structure
b. Read remaining entry data based on size field
c. Process entry based on file type (mode & S_IFMT)
d. Advance to next entry
4. Continue until all entries processed
find_pattern(): Locates specific byte patterns in filesswap16(),swap32(): Endianness conversion utilitieszero_ok(): Validates zero fields in headerscheck_name(): Filters files based on command line patterns
display_shdr(): Shows startup header informationdisplay_ihdr(): Shows image header informationdisplay_attr(): Shows file attribute detailsdisplay_file(): Shows file entry information
process_file(): Handles regular file entriesprocess_dir(): Handles directory entriesprocess_symlink(): Handles symbolic link entriesprocess_device(): Handles device file entries
extract_file(): Extracts individual files to filesystemcreate_directories(): Creates directory structure recursivelycopy_bytes(): Efficiently copies file data
- zlib decompression:
gzread()using gzip streams - LZO decompression:
lzo1x_decompress()with block format - UCL decompression:
ucl_nrv2b_decompress_8()with block format
-
Initialization
- Parse command line arguments and options
- Open input image file or stdin
- Initialize compression libraries if needed
-
Header Discovery
- Search for startup header signature (0x00ff7eeb)
- Validate zero fields and handle endianness
- Display startup information if found
-
Compression Handling
- Detect compression type from startup flags
- Create temporary file for decompressed data
- Decompress image using appropriate algorithm
- Switch to processing decompressed image
-
Image Processing
- Locate image header using "imagefs" signature
- Parse image header and validate structure
- Calculate directory table position
-
Directory Traversal
- Read directory entries sequentially
- Process each entry based on file type
- Extract or display files as requested
-
Cleanup and Verification
- Read and display checksums from image trailer
- Validate startup trailer if present
- Close files and free allocated memory
# List image contents (default behavior)
./ifsdump image.ifs
# Extract all files to current directory
./ifsdump -x image.ifs
# Extract to specific directory
./ifsdump -d /tmp/extracted -x image.ifs
# Extract specific file by name
./ifsdump -f filename image.ifs
# List contents only (explicit)
./ifsdump -l image.ifs
# Verbose extraction with debugging
./ifsdump -v -x image.ifs| Option | Long Option | Description |
|---|---|---|
-d DIR |
--directory DIR |
Extract to directory DIR (default: current directory) |
-f FILE |
--file FILE |
Extract named file only |
-u FILE |
--uncompress FILE |
Save uncompressed image to FILE |
-x |
--extract |
Extract all files |
-l |
--list |
List contents without extracting |
-b |
--basename |
Extract to basenames of files |
-m |
--md5 |
Display MD5 checksums (placeholder) |
-z |
--no-zero-check |
Disable zero field validation |
-v |
--verbose |
Enable verbose output |
-h |
--help |
Show help message |
# List all contents to understand structure
./ifsdump image.ifs
# Get detailed information with verbose output
./ifsdump -v image.ifs
# Extract everything to examine
./ifsdump -v -d extracted image.ifs# Extract a single file
./ifsdump -f bin/sh image.ifs
# Extract multiple specific files
./ifsdump -f libc.so -f ld.so image.ifs
# Extract all to directory with basenames only
./ifsdump -b -d flat_extract -x image.ifs# Save decompressed image for faster repeated access
./ifsdump -u decompressed.ifs image.ifs.gz
# Process compressed image with verbose decompression info
./ifsdump -v -x compressed_image.ifs# Show detailed header and compression information
./ifsdump -v image.ifs
# Disable zero field checking for corrupted images
./ifsdump -z -v image.ifs
# Extract with full debugging output
./ifsdump -v -d debug_output -x image.ifsImage startup_size: 141624320 (0x8710400)
Image stored_size: 213133056 (0xcb42700)
Compressed size: 71508732 (0x44322fc)
Offset Size Name
0x00000000 0x00000001 *.boot
0x00000001 0x00000100 Startup-header flags1=0xf flags2=0 paddr_bias=0
0x00000101 0x00047008 startup.*
0x00047109 0x00000059 Image-header mountpoint=/
0x00047165 0x00000cf8 Image-directory
---- ---- Root-dirent
0x0004785d 0x00001234 bin/sh
0x00048a91 0x00004567 lib/libc.so
0x0004cff8 0x00000123 etc/hosts
Shows detailed information about:
- Startup header fields and compression settings
- Image header details and mount information
- Directory entry attributes (permissions, ownership, timestamps)
- Decompression progress and block-by-block status
- File extraction details with full paths
Checksums: image=0x12345678 startup=0x87654321
- GCC compiler
- zlib1g-dev (zlib compression library) - Required for ifsdump
- liblzo2-dev (LZO compression library) - Required for efsdump, ifsdump, and decompress-qnx-elf
- libucl-dev (UCL compression library) - Required for efsdump, ifsdump, and decompress-qnx-elf
sudo apt-get install build-essential zlib1g-dev liblzo2-dev libucl-dev# Build all tools
make all
# Build individual tools
make efsdump
make ifsdump
make decompress-qnx-elf
# Build with debugging symbols
make debug
# Check for required dependencies
make check-deps
# Run test suite
make test
# Run syntax/warning checks
make lint# Install to system directories
sudo make install
# Install to custom prefix
make install DESTDIR=/usr/local- The image may not be a QNX EFS filesystem
- The image may be corrupted or truncated
- Try examining with a hex editor to verify QSSL_F3S signature
- The image may not contain a QNX IFS with startup header
- Try searching for "imagefs" signature directly
- The image may be a raw IFS without startup wrapper
- Ensure compression libraries are properly installed
- Check library versions are compatible
- Verify library packages include development headers
- This indicates UCL decompression failure
- The file may be corrupted or use a different compression variant
- Some files may use unsupported compression parameters
- Check that all required compression libraries are installed
- Verify the compression type is supported (zlib, LZO, UCL)
- For
ifsdump, try using-zto disable zero field validation
- Verify the input starts with the magic string
"iwlyfmbp" - Confirm the input is the compressed file itself, not an already decompressed ELF
- Use
xxd -l 16 <file>orhexdump -C <file> | headto inspect the header
- The compressed stream ended before the declared uncompressed size
- The source file or filesystem image may be truncated
- Re-run with
-vto identify the failing compressed block
- This was a known issue that has been fixed in the current version
- Ensure you're using the latest version with proper path handling
Use verbose mode (-v) to get detailed information about:
- Header parsing and validation process
- Compression detection and decompression progress
- Directory structure and file attributes
- Extraction process and any errors encountered
- QNX Neutrino Documentation
- QNX Image File System Documentation
- Python QNX Mount Implementation - Reference for EFS structures
- zlib Library
- LZO Compression Library
- UCL Compression Library
efsdump.c- QNX Compressed-EFS extractor source codeifsdump.c- QNX IFS extractor source codedecompress-qnx-elf.c- Standalone QNX compressed-ELF decompressorREADME.md- This documentationMakefile- Build configuration
- Added
decompress-qnx-elffor standalone"iwlyfmbp"compressed ELF payloads - Added
make lintand expanded.gitignorefor local build/extraction artifacts - Updated
efsdumpto stream extraction through extent chains instead of buffering whole files or writing temporary compressed payloads - Added file extent and directory traversal cycle detection
- Hardened EFS metadata parsing with checked reads and explicit error policy
- Formalized QNX compressed-ELF header/block parsing as little-endian
- Fixed aligned directory-name heap overwrite and large compressed-file extraction across more than 100 extents
- Added comprehensive QNX IFS support with ifsdump tool
- Refactored ifsdump.c to match efsdump.c structure and style
- Added support for zlib, LZO, and UCL compression in IFS images
- Unified build system and documentation for filesystem extraction tools
- Added comprehensive test suite and dependency checking
- Initial release with full QNX Compressed-EFS support
- Directory-centric filesystem traversal implementation
- Support for LZO and UCL compression
- Command-line interface with multiple extraction modes
- Proper directory hierarchy preservation
- Verbose debugging and listing capabilities
MIT License - See source code for details.