#ifndef IFSFILE_H
#define IFSFILE_H
#ifdef __cplusplus
extern "C" {
#endif
// standard C includes
#include <stdint.h>
#include <stdlib.h>
// compiler-specific glue
#ifdef _WIN32
#ifndef __BYTE_ORDER__
#define __ORDER_BIG_ENDIAN__ 4321
#define __ORDER_LITTLE_ENDIAN__ 1234
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ // all Windows machines are little endian
#endif // !__BYTE_ORDER__
#ifndef __builtin_bswap64
#ifdef _MSC_VER
#define __builtin_bswap64(x) _byteswap_uint64 ((unsigned long long) (x))
#endif // _MSC_VER
#endif // !__builtin_bswap64
#ifndef __builtin_bswap32
#ifdef _MSC_VER
#define __builtin_bswap32(x) _byteswap_ulong ((unsigned long) (x))
#endif // _MSC_VER
#endif // !__builtin_bswap32
#ifndef __builtin_bswap16
#ifdef _MSC_VER
#define __builtin_bswap16(x) _byteswap_ushort ((unsigned short) (x))
#endif // _MSC_VER
#endif // !__builtin_bswap32
#endif // _WIN32
#ifdef _MSC_VER
#define START_OF_PACKED_STRUCT() __pragma(pack(push)) __pragma(pack(1))
#define END_OF_PACKED_STRUCT() __pragma(pack(pop))
#define PACKED(thing) thing
#else // !_MSC_VER
#define START_OF_PACKED_STRUCT()
#define END_OF_PACKED_STRUCT()
#define PACKED(thing) thing __attribute__((packed))
#endif // _MSC_VER
// bitmapped flags used in the flags1 member of the startup header
#define STARTUP_HDR_FLAGS1_VIRTUAL (1 << 0)
#define STARTUP_HDR_FLAGS1_BIGENDIAN (1 << 1)
//#define STARTUP_HDR_FLAGS1_COMPRESS_MASK 0x1c
//#define STARTUP_HDR_FLAGS1_COMPRESS_SHIFT 0x02
//#define STARTUP_HDR_FLAGS1_COMPRESS_NONE 0x00
//#define STARTUP_HDR_FLAGS1_COMPRESS_ZLIB 0x04
//#define STARTUP_HDR_FLAGS1_COMPRESS_LZO 0x08
//#define STARTUP_HDR_FLAGS1_COMPRESS_UCL 0x0c
#define STARTUP_HDR_FLAGS1_TRAILER_V2 (1 << 5) // if set, then a struct startup_trailer_v2 follows the startup. If the image is compressed, then the compressed imagefs is followed by a struct image_trailer_v2
// bitmapped flags used in the flags member of the image header
#define IMAGE_FLAGS_BIGENDIAN (1 << 0) // header, trailer, dirents in big-endian format
#define IMAGE_FLAGS_READONLY (1 << 1) // do not try to write to image (rom/flash)
#define IMAGE_FLAGS_INO_BITS (1 << 2) // inode bits valid
#define IMAGE_FLAGS_SORTED (1 << 3) // dirent section is sorted (by pathname)
#define IMAGE_FLAGS_TRAILER_V2 (1 << 4) // image uses struct image_trailer_v2
// bitmapped flags superposed to a filesystem entry's inode number
#define IFS_INO_PROCESSED_ELF 0x80000000
#define IFS_INO_RUNONCE_ELF 0x40000000
#define IFS_INO_BOOTSTRAP_EXE 0x20000000
#if 0 // TODO: startup script compiler. Someday.
#define SCRIPT_FLAGS_EXTSCHED 0x01
#define SCRIPT_FLAGS_SESSION 0x02
#define SCRIPT_FLAGS_SCHED_SET 0x04
#define SCRIPT_FLAGS_CPU_SET 0x08
#define SCRIPT_FLAGS_BACKGROUND 0x20
#define SCRIPT_FLAGS_KDEBUG 0x40
#define SCRIPT_POLICY_NOCHANGE 0
#define SCRIPT_POLICY_FIFO 1
#define SCRIPT_POLICY_RR 2
#define SCRIPT_POLICY_OTHER 3
#define SCRIPT_TYPE_EXTERNAL 0
#define SCRIPT_TYPE_WAITFOR 1
#define SCRIPT_TYPE_REOPEN 2
#define SCRIPT_TYPE_DISPLAY_MSG 3
#define SCRIPT_TYPE_PROCMGR_SYMLINK 4
#define SCRIPT_TYPE_EXTSCHED_APS 5
#define SCRIPT_CHECKS_MS 100
#define SCRIPT_SCHED_EXT_NONE 0
#define SCRIPT_SCHED_EXT_APS 1
#define SCRIPT_APS_SYSTEM_PARTITION_ID 0
#define SCRIPT_APS_SYSTEM_PARTITION_NAME "System"
#define SCRIPT_APS_PARTITION_NAME_LENGTH 15
#define SCRIPT_APS_MAX_PARTITIONS 8
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
typedef PACKED (struct) bootscriptcmd_header_s
{
uint16_t size; // size of cmd entry
uint8_t type;
uint8_t spare;
} bootscriptcmd_header_t;
END_OF_PACKED_STRUCT () // restore default alignment
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
typedef union bootscriptcmd_s
{
PACKED (struct) script_external
{
bootscriptcmd_header_t hdr;
uint8_t cpu; // CPU (turn into runmask)
uint8_t flags;
union script_external_extsched
{
uint8_t reserved[2];
PACKED (struct)
{
uint8_t id;
uint8_t reserved[1];
} aps;
} extsched; // extended scheduler
uint8_t policy; // POLICY_FIFO, POLICY_RR, ...
uint8_t priority; // priority to run cmd at
uint8_t argc; // # of args
uint8_t envc; // # of environment entries
char args[0]; // executable, argv, envp (null padded to 32-bit align)
} external;
PACKED (struct) script_waitfor_reopen
{
bootscriptcmd_header_t hdr;
uint16_t checks;
char fname[0]; // char fname[] (null padded to 32-bit align)
} waitfor_reopen;
PACKED (struct) script_display_msg
{
bootscriptcmd_header_t hdr;
char msg[0]; // char msg[] (null padded to 32-bit align)
} display_msg;
PACKED (struct) script_procmgr_symlink
{
bootscriptcmd_header_t hdr;
char src_dest[0]; // <src_name>, '\0', <dest_name> '\0' (null padded to 32-bit align)
} procmgr_symlink;
PACKED (struct) script_extsched_aps
{
bootscriptcmd_header_t hdr;
uint8_t parent;
uint8_t budget;
uint16_t critical;
uint8_t id;
char pname[0]; // char pname[] (null padded to 32-bit align)
} extsched_aps;
} bootscriptcmd_t;
END_OF_PACKED_STRUCT () // restore default alignment
#endif // 0
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
typedef PACKED (struct) fsentry_s
{
PACKED (struct) fsentry_header_s
{
uint16_t size; // size of dirent
uint16_t extattr_offset; // if zero, no extattr data
uint32_t ino; // if zero, skip entry
uint32_t mode; // mode and perms of entry
uint32_t gid;
uint32_t uid;
uint32_t mtime;
} header;
PACKED (union) fsentry_specific_u
{
PACKED (struct) fsentry_file_s // when (mode & S_IFMT) == S_IFREG
{
uint32_t offset; // offset from header
uint32_t size;
char *path; // null terminated path (no leading slash)
uint8_t *UNSAVED_databuf; // file data blob buffer (convenience pointer, NOT SAVED IN THE IFS)
} file;
PACKED (struct) fsentry_dir_s // when (mode & S_IFMT) == S_IFDIR
{
char *path; // null terminated path (no leading slash)
} dir;
PACKED (struct) fsentry_symlink_s // when (mode & S_IFMT) == S_IFLNK
{
uint16_t sym_offset; // offset to 'contents' from 'path'
uint16_t sym_size; // strlen (contents)
char *path; // null terminated path (no leading slash)
char *contents; // null terminated symlink contents
} symlink;
PACKED (struct) fsentry_device_s // when (mode & S_IFMT) == S_IF<CHR|BLK|FIFO|NAM|SOCK>
{
uint32_t dev;
uint32_t rdev;
char *path; // null terminated path (no leading slash)
} device;
} u;
bool UNSAVED_was_data_written; // whether this entry's data was written to the image (convenience member, NOT SAVED IN THE IFS)
} fsentry_t;
END_OF_PACKED_STRUCT () // restore default alignment
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
typedef PACKED (struct) startup_header_s // size 256 bytes
{
// I - used by the QNX IPL
// S - used by the startup program
uint8_t signature[4]; // [I ] Header signature, "\xeb\x7e\xff\x00"
uint16_t version; // [I ] Header version, i.e. 1
uint8_t flags1; // [IS] Misc flags, 0x21 (= 0x20 | STARTUP_HDR_FLAGS1_VIRTUAL)
uint8_t flags2; // [ ] No flags defined yet (0)
uint16_t header_size; // [ S] sizeof(struct startup_header), i.e. 256
uint16_t machine; // [IS] Machine type from elfdefinitions.h, i.e. 0x003E --> _ELF_DEFINE_EM(EM_X86_64, 62, "AMD x86-64 architecture")
uint32_t startup_vaddr; // [I ] Virtual Address to transfer to after IPL is done, here 0x01403008 (appears in "Entry" column for "startup.*")
uint32_t paddr_bias; // [ S] Value to add to physical address to get a value to put into a pointer and indirected through, here 0 (no indirections)
uint32_t image_paddr; // [IS] Physical address of image, here 0x01400f30 (appears in "Offset" column for "startup-header" which is the first entry/start of file)
uint32_t ram_paddr; // [IS] Physical address of RAM to copy image to (startup_size bytes copied), here 0x01400f30 (same as above)
uint32_t ram_size; // [ S] Amount of RAM used by the startup program and executables contained in the file system, here 0x00cd6128 i.e. 13 459 752 dec. which is 13 Mb. i.e. IFS file size minus 0x9eee
uint32_t startup_size; // [I ] Size of startup (never compressed), here 0x02f148 or 192 840 bytes
uint32_t stored_size; // [I ] Size of entire image, here 0x00cd6128 (same as ram_size)
uint32_t imagefs_paddr; // [IS] Set by IPL to where the imagefs is when startup runs (0)
uint32_t imagefs_size; // [ S] Size of uncompressed imagefs, here 0x00ca6fe0 or 13 266 912 bytes
uint16_t preboot_size; // [I ] Size of loaded before header, here 0xf30 or 3888 bytes (size of "bios.boot" file))
uint16_t zero0; // [ ] Zeros
uint32_t zero[1]; // [ ] Zeros
uint64_t addr_off; // [ S] Offset to add to startup_vaddr, image_paddr, ram_paddr, and imagefs_paddr members, here zero (0)
uint32_t info[48]; // [IS] Array of startup_info* structures (zero filled)
} startup_header_t;
END_OF_PACKED_STRUCT () // restore default alignment
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
typedef PACKED (struct) startup_trailer_s
{
uint32_t cksum; // checksum from start of header to start of trailer
} startup_trailer_v1_t;
END_OF_PACKED_STRUCT () // restore default alignment
// NOTE: The checksums in this trailer will only be valid prior to entering startup.
// Because the startup binary is executed in-place, its data segment will change once the program is running.
// Hence, any checksum validation would need to be done by the boot loader / IFS.
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
typedef PACKED (struct) startup_trailer_v2_s
{
uint8_t sha512[64]; // SHA512 from start of header to start of trailer
uint32_t cksum; // checksum from start of header to start of this member
} startup_trailer_v2_t;
END_OF_PACKED_STRUCT () // restore default alignment
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
typedef PACKED (struct) image_header_s
{
uint8_t signature[7]; // image filesystem signature, i.e. "imagefs"
uint8_t flags; // endian neutral flags, 0x1c
uint32_t image_size; // size from start of header to end of trailer (here 0xca6fe0 or 13 266 912)
uint32_t hdr_dir_size; // size from start of header to last dirent (here 0x12b8 or 4792)
uint32_t dir_offset; // offset from start of header to start of first dirent (here 0x5c or 92)
uint32_t boot_ino[4]; // inode of files for bootstrap pgms (here 0xa0000002, 0, 0, 0)
uint32_t script_ino; // inode of file for script (here 3)
uint32_t chain_paddr; // offset to next filesystem signature (0)
uint32_t spare[10]; // zerofill
uint32_t mountflags; // default _MOUNT_* from sys/iomsg.h (0)
char mountpoint[4]; // default mountpoint for image ("/" + "\0\0\0")
} image_header_t;
END_OF_PACKED_STRUCT () // restore default alignment
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
typedef PACKED (struct) image_trailer_v1_s
{
uint32_t cksum; // checksum from start of header to start of trailer
} image_trailer_v1_t; // NOTE: this is the same structure as startup_trailer_v1_t
END_OF_PACKED_STRUCT () // restore default alignment
// NOTE: the checksums in this trailer will only be valid until the first non-startup bootstrap binary (e.g., startup-verifier, procnto, ...) is invoked.
// Because bootstrap binaries execute in-place, their data segments will change once the programs are running.
// Hence, any checksum validation would need to be done either by the boot loader / IFS or by the startup.
START_OF_PACKED_STRUCT () // we need byte-alignment for this struct
typedef PACKED (struct) image_trailer_v2_s
{
uint8_t sha512[64]; // SHA512 from start of image header to start of trailer
uint32_t cksum; // checksum from start of header to start of this member
} image_trailer_v2_t; // NOTE: this is the same structure as startup_trailer_v2_t
END_OF_PACKED_STRUCT () // restore default alignment
// undefine the helpers we no longer need
#undef START_OF_PACKED_STRUCT
#undef END_OF_PACKED_STRUCT
#undef PACKED
#ifdef __cplusplus
}
#endif
#endif // IFSFILE_H