System Arguments

The loader and kernel use a tagged format for defining system arguments. This tagged structure is designed to be small, and only describes data. The structure does not include any executable data. Instead, it contains references to this data that may be located immediately after the structure on a storage medium.

The tagged structure defines a prefix that is tagged by an 8-byte structure:


#![allow(unused)]
fn main() {
struct Tag {
    /// Ascii-printable name, not null-terminated, in little endian format.
    tag: u32,

    /// CRC16 of the data section, using CCITT polynomial.
    crc16: u16,

    /// Size of the data section, in 4-byte words.
    size: u16,
}
}

Tags are stored sequentially on disk, meaning a reader can skip over tags that it does not recognize. Furthermore, it can use a combination of crc16 and size to determine that it has found a valid section.

The size field is in units of 4-bytes. Therefore, a Tag that contains only four bytes of data (for a total of 12-bytes on disk including the Tag) would have a size value of 1.

XArg tag -- Xous Arguments Meta-Tag

The only ordering requirement for tags is that the first tag should be an XArg tag. This tag indicates the size of the entire structure as well as critical information such as the size of RAM.

Future revisions may add to this tag, however the size will never shrink.

OffsetSizeNameDescription
04Arg SizeThe size of the entire args structure, including all headers, but excluding any trailing data (such as executables)
44VersionVersion of the XArg structure. Currently 1.
84RAM StartThe origin of system RAM, in bytes
124RAM SizeThe size of system RAM, in bytes
164RAM NameA printable name for system RAM

XKrn tag -- Xous Kernel Description

This describes the kernel image. There must be exactly one XKrn tag in an arguments structure. This image will get mapped into every process within the final 4 megabytes, and therefore the text and data offsets must be in the range 0xffc0_0000 - 0xfff0_0000.

OffsetSizeNameDescription
04LOAD_OFFSETPhysical address (or offset) where the kernel is stored
44TEXT_OFFSETVirtual memory address where the kernel expects the program image to live. This should be 0xffd00000.
84TEXT_SIZESize of the text section. This indicates how many bytes to copy from the boot image.
124DATA_OFFSETVirtual memory address where the kernel expects the .data/.bss section to be. This should be above 0xffd00000 and below 0xffe00000
164DATA_SIZESize of the .data section
204BSS_SIZEThe size of the .bss section, which immediately follows .data
244ENTRYPOINTVirtual address of the _start() function

The kernel will run in Supervisor mode, and have its own private stack. The address of the stack will be generated by the loader.

IniE tag -- Initial ELF Programs

The IniE tag describes how to load initial processes. There is one IniE for each initial program. There must be at least one IniE tag.

This tag has the following values:

OffsetSizeNameDescription
04LOAD_OFFSETPosition in RAM relative to the start of the arguments block where this program is stored, or an absolute value if ABSOLUTE is 1.
44ENTRYPOINTVirtual memory address of the _start() function

Following this is a list of section definitions. Section definitions must be sequential in RAM -- that is, it is not permitted for SECTIONn_OFFSET to decrease. | Offset | Size | Name | Description | | ------ | ---- | --------------- | -------------------------------------------- | | n3+8 | 8 | SECTIONn_OFFSET | Virtual memory address of memory section n | | n3+12 | 3 | SECTIONn_SIZE | Size of memory section n | | n*3+15 | 1 | SECTIONn_FLAGS | Flags describing memory section n |

The fields size, flags, and offset together occupy 64 bits (8 bytes). The OFFSET is a full 32-bit address. The SIZE field is in units of bytes, however as it is only 24 bits, meaning the largest section size is 2^24 bytes.

The FLAGS field contains the following four bits. Any region may be marked NOCOPY, however RISC-V does not allow regions to be marked "Write-only":

BitBinaryNameDescription
00b0001NOCOPYNo data should be copied -- useful for .bss
10b0010WRITABLERegion will be allocated with the "W" bit
20b0100READABLERegion will be allocated with the "R" bit
30b1000EXECUTABLERegion will be allocated with the "X" bit

Programs cannot access the final four megabytes, as this memory is reserved for the kernel. It is an error if any section enters this memory region.

PNam Tag -- Program Names

PNam maps process IDs to process names. If multiple PNam tags exist within a block, the first one that is encountered should take precedence. This tag is a series of entries that take the following format:

Size (bytes)NameDescription
4PIDID of the process that this name describes
4LengthThe length of the data that follows
variesDataThe UTF-8 name string

Bflg Tag -- Boot Flags

This configures various bootloader flags. It consists of a single word of data with various flags that have the following meaning:

  • 0x00000001 NO_COPY -- Skip copying data to RAM.
  • 0x00000002 ABSOLUTE -- All program addresses are absolute. Otherwise, they're relative to the start of the config block.
  • 0x00000004 DEBUG -- Allow the kernel to access memory inside user programs, which allows a debugger to run in the kernel.

MREx Tag -- Additional Memory Regions

This tag defines additional memory regions beyond main system memory. This region omits main system memory, which is defined in the XArg tag. The format for this tag consists of a single word defining how many additional sections there are, followed by actual section entries:

OffsetSizeNameDescription
04CountThe number of additional memory entries

Each additional memory entry is 3 words of 4-bytes each:

OffsetSizeNameDescription
n*3 + 44StartThe start offset of this additional region
n*3 + 84LengthThe length of this additional region
n*3 + 124NameA 4-character name of this region that should be printable -- useful for debugging

Additional memory regions should be non-overlapping. Creating overlapping memory regions will simply waste memory, as the loader will allocate multiple regions to track the memory yet will only allow it to be shared once.