MacIvory FEP File Formats

I've been playing around with the MacIvory FEP (Front-End Processor) to learn more about how the Symbolics Ivory environment gets started. Not everything is yet clear to me, but I wanted to record some information about the "cold load" environments files.

The Ivory chip uses 40-bit words, where 32 bits make up the "address" or immediate portion of the word and the upper 8 bits are a combination of type tagging and "cdr code" flags which allow for compact representation of lists and, in code, program counter sequencing flags to allow for half-word instructions to be compacted around full-word instructions in the stream.

A lot more information can be learned from a number of sources. The previous generation "3600" machine was disclosed pretty widely in the literature, and ideas like type-tagging and cdr-coding are very similar between the machines. Bitsavers has a few files scanned from internal documentation. Most informative are


In the MacIvory, the "front-end processor" role is mostly played by the Ivory chip itself, though of course the Macintosh system is an important part of the environment. I have not yet figured out all of the details around how the Ivory chip initializes itself and how the Macintosh brings it to life, but most of the Macintosh side has Think C sources provided with the distribution.

The FEP files that actually execute the low-level behavior come in three types. On the Mac side, IFEP Kernel and Device PROM are files that live in the Mac file system. These start with the ASCII bytes "IFEP prom". 

There are also similar files that resemble Ivory "world files". In the FEP file system, these include i328-kernel.fep.~44~ and start with a four-byte "magic number" 0x48 0x49 0x4a 0x63, or "HIJc" in ASCII.

Thirdly, some of the FEP functionality is segmented into FLOD "overlay" files which can be dynamically loaded using the Scan File command. For example, the i328-tests.flod which can be loaded to run memory tests. These start with an ASCII string "IFEP overlay"

Broadly speaking, the "IFEP prom" and "IFEP overlay" seem to share the same basic format. They are 8-bit byte oriented, but of course a large portion of the file is made up of 40-bit Ivory words, LSB first and tag byte last.

  • File type identification header. Either "IFEP prom" or "IFEP overlay".
  • 4 bytes indicating the "i-version" of the files. LSB first. 0x48 0x01 0x00 0x00 represents "328" decimal, as in "i328-kernel" or "i328-tests"
  • At this point, the "IFEP overlay" files contain two more 32-bit words (LSB first) identifying exactly the FEP "timestamp" and "version fingerprint" they are intended to overlay. In i328, these correspond to a "timestamp" 0x5c 0x39 0x31 0xae, which is the Lisp "universal time" 2922461532 or 1992-08-10T18:52:12 TAI which matches pretty closely the file timestamp of the various distribution files in the FEP0 directory. The "version fingerprint" 0xf3 0xe7 0x5a 0x93 does not have any interpretation that is obvious to me, but the overlay load routine compares this 32-bit value to one in the kernel and will reject the overlay if they do not match.
  • The IFEP overlay files also contain a sequence of "command descriptors" which describe the commands the file will add to the FEP command table when scanned. These characters are presumably in the Lisp Machine character set, but for alphanumerics, this matches ASCII.
    • 8-bit byte string-length for the command name
    • That number of 8-bit character bytes for the Command
    • 8-bit byte string-length for the command documentation string
    • That number of 8-bit character bytes for the command documentation
    • A 32-bit address (LSB first) for the command routine entry point.
  • After the command descriptors, a single 0x00 byte (which would indicate a zero-length name for the next command) appears to terminate the command descriptors, and at this point, the file format for the IFEP prom and IFEP overlay seem to converge again.
After that "header" portion, the IFEP prom and IFEP overlay files have a series of memory blocks: it seems generally to be two very small blocks of a word or two, followed by a large block with most of the file content, and possibly an additional block of perhaps a few dozen words.
  • A 32-bit address (LSB first)
  • A 32-bit word count (LSB first)
  • If the word count is negative (seems to be exactly 0xffffffff in my examples), the file has ended.
  • The word-count number of 40-bit words follow, arranged as 5 8-bit bytes, LSB first, tag byte last.
  • A 32-bit checksum, which should consist of a simple 32-bit sum of all of the 8-bit bytes (including the tag bytes) in the 40-bit words.
It seems that the final step in the loading of these files is a validity check of the memory address, followed by a Lisp function call to that address if it appears valid. I haven't quite figured out all of the Ivory assembly code for these routines. The FEP debugger is actually very helpful in disassembling functions, including function names, a bunch of strings including error messages, and list constants. 

Curiously, even this very low-level code appears to use keyword function calls, an implementation of "Flavors," and a Lispy condition system, though I am not sure these are the same implementation as the full Genera system. It includes reference counting for some of the flavor instances, and generally seems to use explicit memory management throughout. This makes sense as the garbage collection itself might have to be initialized. Most of the types and routines to handle characters, lists, strings, arrays, and file streams seem to be cut-down versions of the Genera ZetaLisp versions, defined in a dedicated FEP package. Presumably this is all part of the construction of a cold-load system that can bootstrap the full Genera worlds with a minimum of functionality.

I still have not figured out a number of basic pieces: in particular, the string constants themselves, while the debugger can print them, seem not to be present in the files, or even in parts of the memory that the debugger allows me to inspect. There are some routines that seem to refer to "compressed" data, which I have not yet understood.

Comments

Popular posts from this blog

Open Genera VLM on Linux

Restoring the Heathkit Jr 35

FPGA selection for beginners