A comprehensive collection of tools to extract files from QNX filesystem images. This suite includes extractors for both QNX Compressed-EFS and QNX IFS (Image File System) formats, supporting various compression methods (LZO, UCL, zlib) commonly found in QNX embedded systems.
- efsdump - QNX Compressed-EFS filesystem extractor
- ifsdump - QNX IFS (Image File System) extractor
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[2]
: 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_DIR
(0): Directory entriesEXTTYPE_FILE
(1): File data extentsEXTTYPE_SYS
(2): System/metadata extentsEXTTYPE_XIP
(3): Execute-in-place 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 block
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 (
first
pointer) that lists its contents - Extent Chains: Following the
next
pointers 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 filesextract_raw_file_data()
: Handles uncompressed files
- 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
- 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.bin
Found 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
QNX 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_MASK
determines 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.ifs
Image 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 both tools
- libucl-dev (UCL compression library) - Required for both tools
sudo apt-get install build-essential zlib1g-dev liblzo2-dev libucl-dev
# Build both tools
make all
# Build individual tools
make efsdump
make ifsdump
# Build with debugging symbols
make debug
# Check for required dependencies
make check-deps
# Run test suite
make test
# 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)
- Try using
-z
flag to disable zero field validation
- 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 codeREADME.md
- This documentationMakefile
- Build configuration
- 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 both 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.