System Files:QFILEIML

From Try-AS/400
Revision as of 18:57, 8 August 2026 by Friedkiwi (talk | contribs) (Document the QFILEIML / IMD1 container: layout, directory, payload addressing, contents (via create-page on MediaWiki MCP Server))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

QFILEIML is one of the two large container files found on AS/400 SAVSYS and Licensed Internal Code installation media. It holds the machine's loadable microcode: IOP and adapter firmware, service processor firmware, and a quantity of SLIC modules. Its internal format is identified by the four-byte magic IMD1 and is a container of LIDs.

The companion file QFILEMCD holds SLIC proper, via a directory called COPYDIR. Both files use the same 32-byte LID directory record, and a record present in both is byte-for-byte identical, so the two are two views of one packaging scheme rather than two unrelated formats.

The name is not documented by IBM as far as is known here. IML almost certainly stands for Initial Microprogram Load — the phase in which the machine's microcode is brought up, before OS/400 itself exists — which matches the file's contents. Treat the expansion as an inference.

Everything below was determined by inspection of a V4R4 image and should be read as applying to that release. The figures quoted are from a single QFILEIML of 81,287,680 bytes (77.5 MiB), build label v4r4m01204.0.03.

File layout

Offset Contents
0x000 Magic C9 D4 C4 F1, which is IMD1 in EBCDIC, followed by a short and largely unexplored header
0x200 Licensed Internal Code banner in EBCDIC, carrying the LIC product identifiers
0x400 Directory header: a four-byte preamble, the literal string Directory., two zero bytes, then a 16-byte build label
0x420 The directory: a run of 32-byte LID records
varies Terminator record, identifier 0xC5D5C440 (END  in EBCDIC)
0x5400 Payload area

The first sixteen bytes of the file are:

00000000: c9d4 c4f1 0000 0000 ff00 0200 00e0 0000

The banner at 0x200 reads, in EBCDIC:

LICENSED INTERNAL CODE - PROPERTY OF IBM 5763999, 5716999, 5769999
(C) COPYRIGHT IBM CORP. 1980, 1998. ALL RIGHTS RESERVED. ...

The three seven-digit numbers are LIC product identifiers, and the same three appear in QFILEMCD. The build label at 0x410 is v4r4m01204.0.03, likewise identical between the two files, which is a convenient way to confirm that a given QFILEIML and QFILEMCD came off the same media.

The directory

The directory begins at 0x420 and runs, in this image, for 632 records before the END  terminator at 0x5320. The record layout is documented at Data Structures:LID and is not repeated here.

Of the 632 records:

  • 341 carry the compressed flag.
  • 631 name an SLS staging address in the FFFFFFFFxx band. Exactly one does not: LID 80900818 stages at 000000024A 000000.
  • 7 have payloads that are themselves runs of LID records — see Directory extents below.

Payload addressing

Note! This is the single point on which it is easiest to go wrong, and doing so silently produces plausible-looking nonsense.

The offset field in each record is not an offset into QFILEIML. It is a load-source LBA, describing where the payload sits on the installation medium, and it has no useful meaning inside the container file.

Reading it as a file offset is superficially attractive and definitively wrong. Doing so on this image yields 608 overlapping extents out of 632, a maximum extent of 34,550 blocks against a 158,765-block file, and a minimum offset of block 3, which lands inside the header. That the lengths happen to sum to approximately the file size is a coincidence and should not be taken as confirmation.

The actual rule is simpler: payloads are stored sequentially, in directory order, immediately after the directory, each one length blocks long. There are no gaps and no padding between them.

This is exact rather than approximate. The lengths sum to 158,723 blocks against a 158,765-block file, placing the start of data at block 42 — that is, 0x5400, immediately past the directory terminator — and the payloads then tile to the final byte of the file with nothing left over.

To locate a payload, therefore, walk the directory from the beginning and accumulate lengths; do not index by the offset field.

Contents

Laid out correctly, the payloads fall into two clear populations, distinguishable without decompression by looking for 32-bit stwu r1,-x(r1) prologues versus 64-bit std stores:

Population Count Identification
32-bit PowerPC 75 stwu prologues present, no std at all
64-bit PowerPC AS (SLIC) 210 std present, no stwu at all
Neither 347 Compressed payloads, data, tables, and directory extents

The split is clean — no payload shows both — which is what makes the heuristic trustworthy. The 32-bit population is the interesting one: the main processor of these machines is 64-bit PowerPC AS, so 32-bit code in this file is by definition destined for something else. That is the IOP, adapter and service processor microcode.

Service processor firmware

LID 80900702 is service processor Licensed Internal Code: 128 KiB, stored uncompressed, staged at SLS FFFFFFFF9A 001000. Its EBCDIC strings include a 9400 Licensed Internal Code banner, a 1998 copyright, and a table of component tags of the form SP MOPT1, SP SPCI1, SP SBL, SP SM and so on, alongside build identifiers such as AJSFGWC3 and AJSRWP32. Its code is unambiguously 32-bit.

This confirms a long-standing claim in the trade press that AS/400 service processor firmware is loaded from the load source rather than residing wholly in flash on the card.

The picture is more subtle than "the service processor firmware is in this file", however. Scanning all 632 payloads for the LIC banner, a SP  component tag table and a 32-bit-only instruction profile finds roughly 19 such images, ranging from 34 KiB to 395 KiB, with differing component-tag sets — which is what one would expect of capability tiers across a hardware range where the service processor is entirely invisible to the user.

Those images separate cleanly into two families by their build identifier prefix, and no image carries both prefixes:

Family Count Build ID prefix Distinguishing markers
Service processor 16 AJS… 8 to 24 SP  component tags per image
I/O offload (MFIOP) 6 AJG… No SP  tags at all; several carry an ATM marker, i.e. ATM networking code

Both families share a common runtime library — tags CUANSI, CUCONV, CUIO, CUMEMORY, CUMISC, CUSTO, plus SRASCOMN for RAS common code — which is why their vocabulary overlaps and why the build-ID prefix, rather than the string content, is the reliable discriminator.

What is not in the file

Notably, the service processor's own supervisor is absent. All 632 payloads were searched for rfi (0x4C000064), which any PowerPC exception-returning kernel must contain, and for exception vector tables at the architectural 0x100, 0x200 and subsequent offsets of every 4 KiB boundary. Exactly one payload contains a single rfi in 289 KiB, which is a data coincidence, and no payload has a vector table.

Consistent with that, LID 80900702 begins mid-function, with a function tail rather than an entry point, and manipulates no privileged state anywhere: no mtmsr, no segment or TLB or cache operations, and only LR, CTR and XER touched. It does contain 31 sc supervisor calls.

The conclusion is that the service processor runs a resident supervisor of its own, held in flash on the card, and that this file supplies only loadable task modules that sit on top of it. That is consistent with the hardware — the operator panel carries its own flash, and SLIC has an explicit message for instructing the service processor to IPL itself.

Directory extents

Seven payloads are not data but further runs of 32-byte LID records, largely duplicating entries from the root directory byte for byte. The two largest hold 294 and 133 records. They appear to be indexes rather than nested containers, and a tool walking this file should recognise them so as not to mistake an index for a firmware image. A payload whose first few records parse as plausible LID records, with identifiers matching known LIDs, is an extent.

Compression

341 of the 632 payloads are flagged compressed. The codec is the LZW variant used throughout SLIC and is described at Data Structures:LID#The compressed flag. It has not been needed to read the service processor firmware, which is stored plain, but it stands between the reader and roughly half the file.

Tooling

No IBM-supplied tool for reading this file outside the machine is known. A parser must, at minimum:

  1. check the IMD1 magic at offset 0;
  2. read 32-byte records from 0x420 until an identifier of 0xC5D5C440 or zero;
  3. compute the payload start as file size in blocks minus the sum of all lengths, rather than trusting the offset field;
  4. lay payloads out sequentially in directory order.

Step 3 is what makes extraction correct, and it is worth asserting: if the computed start is not 42 on a V4R4 image, something has been misread.

Open questions

  • The meaning of the header bytes at 0x0040x1FF, and of the four-byte preamble before Directory..
  • The meaning of most LID identifier families.
  • Why 31 payloads carry the compressed flag yet begin with plainly readable 32-bit code.
  • Whether the load-source LBAs in the offset field can be used to reconstruct the physical layout of the original installation medium.
  • Classification of the remaining 32-bit payloads: several are adapter microcode, but others may be operator panel or SPCN code.

See also

Weblinks

  • MC Press Online, which carries older documentation describing service processor microcode as being loaded from the load source

Footnotes