Ultra loader protocol defines a set of services and interfaces used by a bootloader to load a kernel/binary file.
The protocol doesn't require any kind of sections residing inside the kernel binary and fully relies on a loader-specific configuration file to define all the necessary load options and parameters. This allows all parameters to be changed dynamically without recompiling the kernel, and lets the same binary stay compatible with Ultra and any other protocol at the same time.
After handoff, the kernel is provided with a boot context that has the following structure:
struct ultra_boot_context {
uint8_t protocol_major;
uint8_t protocol_minor;
uint16_t reserved;
uint32_t attribute_count;
struct ultra_attribute_header attributes[];
};protocol_major- major version of the protocol, valid versions start at1protocol_minor- minor version of the protocol, valid versions start at0attribute_count- the number of attributes in theattributesarrayattributes- a contiguous array of attributes provided by the loader
The following C macro can be used to retrieve the next attribute from current:
#define ULTRA_NEXT_ATTRIBUTE(current) ((struct ultra_attribute_header*)(((uint8_t*)(current)) + (current)->size))ultra_attribute_header and other structures are described in the following sections.
The kernel is also provided with a protocol magic number ULTRA_MAGIC, which is defined as:
0x554c5442 - 'ULTB' in ASCII
The kernel entrypoint ends up looking something like this in C:
void kernel_entry(struct ultra_boot_context *ctx, uint32_t magic)The way the kernel receives this magic number is platform defined and is discussed in later sections.
If the kernel detects an invalid magic number, the ultra_boot_context* must be considered invalid, and it's recommended that the kernel aborts boot.
Current protocol version is defined as 1.0.
This section defines various options and features defined by the protocol. The actual way to enable/set an option is loader specific and is defined by its configuration file format.
Defines various kernel binary related options.
binary- (string) - shorthand alias forbinary/pathbinary/path- (string) - specifies the path to the kernel in a loader-defined format, if applicable.binary/allocate-anywhere(bool, optional, default=false) - allows the kernel physical memory mappings to be allocated anywhere in memory. Only valid for 64 bit higher-half kernels.
Defines various options related to the page table properties set up at handover.
page-table/levels- (integer, optional, default=4) - specifies the desired depth of the page tablepage-table/constraint- (string, optional, default="maximum") - specifies the constraint for the "levels" value, one of "maximum", "at-least", "exactly"page-table/null-guard- (bool, optional, default=false) - if set totrue, the first physical page is not identity mapped to prevent accidentalNULLaccesses.
Defines a command line to give to the kernel. This attribute is not generated if cmdline is set to null.
cmdline(string, optional, default=null) - kernel command line, passed viaultra_command_line_attribute.
Defines various options related to the address passed in the arch-specific SP register on handover.
stack(string/unsigned) - shorthand alias forstack/size. Also allows a literal "auto".stack/size(unsigned, optional, default=16K) - page aligned size of the stack to allocate.stack/allocate-at(string/unsigned, default=<implementation-defined>) - address where to allocate the stack
Defines options related to the video-mode set by the loader before handover.
If an exact resolution is requested (both width and height), the loader
sets that resolution and fails if no such mode exists. Otherwise the loader
picks an appropriate mode on its own: the display's native resolution if it can
be determined (e.g. via EDID), otherwise the mode the firmware is already in if
there is one, otherwise the highest available mode.
video-mode- (string, optional, default="auto") - shorthand."auto"lets the loader pick an appropriate mode as described above,nullor"unset"request no framebuffer at all, in which caseultra_framebuffer_attributeis not generated.video-mode/width- (unsigned, optional) - requests a specific framebuffer width. If set,heightmust be set too.video-mode/height- (unsigned, optional) - requests a specific framebuffer height. If set,widthmust be set too.video-mode/bpp(unsigned, optional, default=32) - requests a specific framebuffer bits per pixel value. If unset, the loader prefers 32 but falls back to the best available.video-mode/format(string, optional, default="auto") - requests a specific framebuffer format, one of"auto","rgb888","bgr888","rgbx8888","xrgb8888"(any case). Always matched exactly if specified.
Ultra protocol offers different types of modules: classic file-backed modules as well as raw RAM allocations.
The following options must be used to request a module:
kernel-as-module- (bool, optional, default=false) - requests the loader to pass the full kernel binary as a separate module, this can be used for parsing additional debug information, enforcing memory protection for program headers from an ELF file or any other purpose.module- (string) - shorthand alias formodule/pathmodule/type(string, optional, default="file") - one of "file" or "memory". File modules require a path argument and simply make the loader preload a file from disk into RAM. Memory modules are used to request general purpose contiguous zeroed memory allocations without any backing, and can be used for bootstrapping kernel allocators or any other purpose.module/size(unsigned/string, optional*, default="auto") - defines the size of the module. Mandatory for "memory" modules. Can be used to truncate or extend "file" modules, if this is bigger than the file size, the rest of the memory is zeroed.module/name- (string, optional, default=<implementation-defined>) - name of the module that the kernel receivesmodule/description- (string, optional, default=null) - free-form description of the module that the kernel receives via thedescriptionfield ofultra_module_info_attribute. No description is generated if unset or empty.module/path- (string, optional*) - specifies the path for the module to load in a loader-defined format, if applicablemodule/load-at(unsigned/string, optional, default="anywhere") - specifies the load address for the module or "anywhere"
Each directive generates a separate ultra_module_info_attribute
higher-half-exclusive- (bool, optional, default=false) - if set totrue, no identity mappings are provided for lower half. All loader-provided attributeaddressfields are relocated to higher half if present. Only applicable for higher-half kernels.setup-apm- (bool, optional, default=false) - if set totrue, requests the loader to set up a 32-bit protected mode interface for the APM. The kernel is provided withultra_apm_attributein case of successful installation.pass-uefi-info- (bool, optional, default=false) - if set totrueand the loader was booted via UEFI, requests the loader to pass the UEFI system table and firmware memory map to the kernel viaultra_uefi_info_attribute. Silently ignored on non-UEFI platforms.
This section describes the system state for each supported architecture that system software must expect after gaining control.
Page size is defined as 4096 bytes.
- A20 - enabled
- R/EFLAGS - zeroed, reserved bit 1 set
- IDTR - contents are unspecified
- GDTR - set to a valid GDT with at least ring 0 flat code/data descriptors
- Long/protected mode - set as determined by the kernel binary
- CS - set to a flat ring 0 code segment
- DS, ES, FS, GS, SS - set to a flat ring 0 data segment
Higher half is defined as 0xC000'0000
The kernel is considered higher half if it wants to be loaded at or above 0xC010'0000
- Paging enabled
- EIP - set to the entrypoint as specified by the kernel binary
- EAX, ECX, EDX, EBX, EBP, ESI, EDI - zeroed
- ESP - set to a valid stack pointer as determined by the configuration, aligned according to SysV ABI
- *ESP+8 -
ULTRA_MAGIC - *ESP+4 -
ultra_boot_context*
| virtual address | physical address | length of the mapping |
|---|---|---|
| 0x0000'0000 | 0x0000'0000 | up to 3 GiB |
| 0xC000'0000 | 0x0000'0000 | up to 1 GiB |
Only usable RAM within these windows is mapped (up to 3 GiB in the identity map and 1 GiB in the direct map). Reserved and device (MMIO) memory is intentionally left unmapped; the kernel must map such regions itself with the appropriate caching type.
The first mapping is not provided for the higher-half-exclusive mode.
Higher half is defined as 0xFF00'0000'0000'0000 or 0xFFFF'8000'0000'0000, depending on page-table/levels
The kernel is considered higher half if it wants to be loaded at or above 0xFFFF'FFFF'8000'0000
- RIP - set to the entrypoint as specified by the kernel binary
- RDI -
ultra_boot_context* - RSI -
ULTRA_MAGIC - RAX, RCX, RDX, RBX, RBP, R8, R9, R10, R11, R12, R13, R14, R15 - zeroed
- RSP - set to a valid stack pointer as determined by the configuration, aligned according to SysV ABI
- CR3 - a valid address of a PML4 with the following mappings:
Higher half base address depends on the value of page-table/levels with the following conditions:
0xFF00'0000'0000'0000- 'levels' = 5 with a matching constraint0xFFFF'8000'0000'0000- 'levels' = 4 with a matching constraint
| virtual address | physical address | length of the mapping |
|---|---|---|
| 0x0000'0000'0000'0000 | 0x0000'0000'0000'0000 | all usable RAM |
| 0xFFFF'8000'0000'0000 OR 0xFF00'0000'0000'0000 |
0x0000'0000'0000'0000 | all usable RAM |
| 0xFFFF'FFFF'8000'0000 | ????????????????????? | ????????????????????? |
The first two mappings cover all usable RAM regions from the memory map, both at their physical address and at the higher-half direct map base. Reserved and device (MMIO) memory is intentionally left unmapped; the kernel must map such regions itself with the appropriate caching type.
The first mapping is not provided for the higher-half-exclusive mode.
For higher half kernels loaded with allocate-anywhere set to true
the last mapping contains the kernel binary mappings with an arbitrary
physical base picked by the loader.
For all other kernels it is a direct mapping of the first 2 GiB of physical ram.
Address pointed to by CR3 is located somewhere within ULTRA_MEMORY_TYPE_LOADER_RECLAIMABLE.
Whether the memory is mapped using 4K/2M/4M/1G pages is unspecified.
The contents of all other registers are unspecified.
The state of all registers not listed here is unspecified.
The kernel should not assume that any device memory is actually mapped as such.
Normal memory is guaranteed to be accessible.
- MMU enabled
- Data and instruction caches enabled (
SCTLR_ELx.{C, I}set) - Exception level 1 OR 2
- If EL2:
FEAT_VHEis supported andHCR_EL2.{E2H, TGE}are set to{1, 1}
- If EL2:
- Current EL stack alignment checking is enabled
- SPSel set to
SP_ELx - DAIF set to
0b1111 - NZCV set to
0b000
All mapped Normal memory (the identity and direct-map windows) is mapped as
Normal, Inner & Outer Write-Back cacheable, Inner Shareable, using AttrIndx=0.
MAIR_ELx is set to the following guaranteed layout so that the kernel can map
device memory before establishing its own translation tables:
| AttrIndx | Memory type |
|---|---|
| 0 | Normal, Inner & Outer Write-Back cacheable (RA/WA) |
| 1 | Device-nGnRnE |
| 2 | Normal, Inner & Outer Non-cacheable |
The kernel is responsible for mapping device memory (MMIO, framebuffer, etc.)
itself, using AttrIndx=1 or AttrIndx=2 from the layout above, or by
reprogramming MAIR_ELx and its translation tables entirely.
- PC - set to the entrypoint as specified by the kernel binary
- x0 -
ultra_boot_context* - x1 -
ULTRA_MAGIC - x2..x29 - zeroed
- SP - set to a valid stack pointer as determined by the configuration, aligned according to the aarch64 ABI
- TTBR{0,1}_ELx - a valid address of a page table with the following mappings:
Higher half is defined as 0xFFF0'0000'0000'0000 or 0xFFFF'0000'0000'0000, depending on page-table/levels
The kernel is considered higher half if it wants to be loaded at or above 0xFFFF'FFFF'8000'0000
Higher half base address depends on the value of page-table/levels with the following conditions:
0xFFF0'0000'0000'0000- 'levels' = 5 with a matching constraint0xFFFF'0000'0000'0000- 'levels' = 4 with a matching constraint
| virtual address | physical address | length of the mapping |
|---|---|---|
| 0x0000'0000'0000'0000 | 0x0000'0000'0000'0000 | all usable RAM |
| 0xFFFF'0000'0000'0000 OR 0xFFF0'0000'0000'0000 |
0x0000'0000'0000'0000 | all usable RAM |
| 0xFFFF'FFFF'8000'0000 | ????????????????????? | ????????????????????? |
The first two mappings cover all usable RAM regions from the memory map, both at their physical address and at the higher-half direct map base. Reserved and device (MMIO) memory is intentionally left unmapped; the kernel must map such regions itself with the appropriate caching type.
The first mapping is not provided for the higher-half-exclusive mode.
For higher half kernels loaded with allocate-anywhere set to true
the last mapping contains the kernel binary mappings with an arbitrary
physical base picked by the loader.
For all other kernels it is a direct mapping of the first 2 GiB of physical ram.
Address pointed to by TTBR{0/1}_ELx is located somewhere within ULTRA_MEMORY_TYPE_LOADER_RECLAIMABLE.
The granule size, as well as the OA size of the mapped pages is unspecified and is up to the implementation.
The way the loader provides various information to the kernel is via attributes.
Guarantees about the attribute array & attributes:
- All attributes are guaranteed to be aligned on an 8 (or more if required) byte boundary.
- All attributes and
addressfields, as well as any loader-allocated memory that might be accessed by the kernel is guaranteed to be within the mapped address space range. E.g. for a 32-bit higher-half-exclusive kernel, all attributes and modules are guaranteed to be allocated under 1 GiB of physical memory so that they can be safely accessed by the kernel. - The location of any specific attribute within the array is not fixed unless specified otherwise (in the attribute description).
- All attributes of the same type are guaranteed to be a contiguous stream.
- Every attribute type can only appear in the attribute array once unless specified otherwise (in the attribute description).
- All attribute types are guaranteed to have
ultra_attribute_headeras the first member, this includes both current & future attributes. - It is safe to ignore any unknown attribute types.
- All currently defined attributes are guaranteed to keep the same layout
in the future protocol versions, but might have new members added at the end,
which shouldn't affect any valid software as the header
sizefield will be adjusted accordingly.
Every attribute has a distinct type and starts with the following header:
struct ultra_attribute_header {
uint32_t type;
uint32_t size;
};type- one of the following values (each type is detailed in the following sections):
#define ULTRA_ATTRIBUTE_INVALID 0
#define ULTRA_ATTRIBUTE_PLATFORM_INFO 1
#define ULTRA_ATTRIBUTE_KERNEL_INFO 2
#define ULTRA_ATTRIBUTE_MEMORY_MAP 3
#define ULTRA_ATTRIBUTE_MODULE_INFO 4
#define ULTRA_ATTRIBUTE_COMMAND_LINE 5
#define ULTRA_ATTRIBUTE_FRAMEBUFFER_INFO 6
#define ULTRA_ATTRIBUTE_APM_INFO 7
#define ULTRA_ATTRIBUTE_UEFI_INFO 8size- size of the entire attribute including the header. This size is often used for calculating the number of entries in a variable length attribute. This isn't always possible, because sometimes the size is increased on purpose to align entries to 8 bytes. Attributes like this are explicitly documented and provide a separate member that indicates the actual size of the variable size field.
This section describes all currently implemented attribute types and their structure.
Reserved. If encountered, must be considered a fatal error.
This attribute is guaranteed to be the first entry in the attribute array.
This attribute provides various information about the platform and has the following structure:
struct platform_info_attribute {
struct ultra_attribute_header header;
uint32_t platform_type;
uint16_t loader_major;
uint16_t loader_minor;
char loader_name[32];
uint64_t acpi_rsdp_address;
uint64_t higher_half_base;
uint8_t page_table_depth;
uint8_t reserved[7];
uint64_t dtb_address;
uint64_t smbios_address;
};header- standard attribute headerplatform_type- one of the following values:
#define ULTRA_PLATFORM_INVALID 0
#define ULTRA_PLATFORM_BIOS 1
#define ULTRA_PLATFORM_UEFI 2loader_major- major version of the loaderloader_minor- minor version of the loaderloader_name- null-terminated ASCII string with a human-readable name of the loaderacpi_rsdp_address- physical address of the RSDP structure, 0 if not applicable or not presenthigher_half_base- virtual address of the higher half basepage_table_depth- currently configured page table depthreserved- reserved for future usedtb_address- physical address of the device tree blob, 0 if not applicable or not presentsmbios_address- physical address of the SMBIOS entry point structure (either 32 or 64 bits as indicated by the signature), 0 if not applicable or not present
Reserved. If encountered, must be considered a fatal error.
The kernel was loaded using the BIOS services and platform.
The kernel was loaded using the UEFI services and platform.
Reserved for future use, must be ignored by the kernel.
This attribute is guaranteed to be the second entry in the attribute array.
This attribute provides various information about the kernel binary and has the following structure:
struct ultra_kernel_info_attribute {
struct ultra_attribute_header header;
uint64_t physical_base;
uint64_t virtual_base;
uint64_t size;
uint64_t partition_type;
// only valid if partition_type == ULTRA_PARTITION_TYPE_GPT
struct ultra_guid disk_guid;
union {
// only valid if partition_type == ULTRA_PARTITION_TYPE_GPT
struct ultra_guid partition_guid;
// only valid if partition_type == ULTRA_PARTITION_TYPE_PXE_V4
struct ultra_ipv4_addr pxe_v4;
// only valid if partition_type == ULTRA_PARTITION_TYPE_PXE_V6
struct ultra_ipv6_addr pxe_v6;
};
uint32_t disk_index;
uint32_t partition_index;
char fs_path[ULTRA_PATH_MAX];
};header- standard attribute headerphysical_base- physical address of the kernel base, page alignedvirtual_base- virtual address of the kernel base, page alignedsize- number of bytes taken by the kernel, page alignedpartition_type- one of the following values:
#define ULTRA_PARTITION_TYPE_INVALID 0
#define ULTRA_PARTITION_TYPE_RAW 1
#define ULTRA_PARTITION_TYPE_MBR 2
#define ULTRA_PARTITION_TYPE_GPT 3
#define ULTRA_PARTITION_TYPE_PXE_V4 4
#define ULTRA_PARTITION_TYPE_PXE_V6 5disk_guid- GUID of the disk that the kernel was loaded from, only valid forULTRA_PARTITION_TYPE_GPTpartition_guid- GUID of the partition that the kernel was loaded from, only valid forULTRA_PARTITION_TYPE_GPTpxe_server- the IP address of the PXE server the kernel was loaded from, only valid forULTRA_PARTITION_TYPE_PXEdisk_index- index of the disk the kernel was loaded from, always 0 forULTRA_PARTITION_TYPE_PXE_V{4,6}partition_index- index of the partition the kernel was loaded from, index >= 4 implies EBR partition N - 4 for an MBR disk, always 0 forULTRA_PARTITION_TYPE_PXE_V{4,6}fs_path- null terminated UTF-8 string, absolute POSIX path to the kernel binary on the partition
ULTRA_PATH_MAX is defined as 256 including the terminating NULL character.
Reserved. If encountered, must be considered a fatal error.
Unpartitioned device without an MBR/GPT header, the entire disk treated as one file system.
Standard MBR partition, either MBR or EBR.
Standard GPT partition, whether the device also contains a valid MBR is unspecified as GPT always takes precedence.
ultra_guid is defined as:
struct ultra_guid {
uint32_t data1;
uint16_t data2;
uint16_t data3;
uint8_t data4[8];
};Note that the structure is only guaranteed to be 8 byte aligned within ultra_kernel_info_attribute.
Preboot Execution Environment (network boot) media. The kernel was loaded over
the network via TFTP, pxe_v4/pxe_v6 contains the IP address of the server it was loaded from.
struct ultra_ipv4_addr {
uint8_t addr[4];
};
struct ultra_ipv6_addr {
uint8_t addr[16];
};type indicates which member of the union is valid. Note that the structure is
only guaranteed to be 8 byte aligned within ultra_kernel_info_attribute.
Reserved for future use, must be ignored by the kernel.
This attribute provides a physical memory map of the entire system. It has the following format:
struct ultra_memory_map_attribute {
struct ultra_attribute_header header;
struct ultra_memory_map_entry entries[];
};header- standard attribute headerentries- an array of non-overlapping and sorted in ascending order by address entries, where each entry has the following structure:
struct ultra_memory_map_entry {
uint64_t physical_address;
uint64_t size;
uint64_t type;
};physical_address- first byte of the physical range covered by this entrysize- size of this rangetype- one of the following values:
#define ULTRA_MEMORY_TYPE_INVALID 0x00000000
#define ULTRA_MEMORY_TYPE_FREE 0x00000001
#define ULTRA_MEMORY_TYPE_RESERVED 0x00000002
#define ULTRA_MEMORY_TYPE_ACPI_RECLAIMABLE 0x00000003
#define ULTRA_MEMORY_TYPE_ACPI_NVS 0x00000004
#define ULTRA_MEMORY_TYPE_LOADER_RECLAIMABLE 0xFFFF0001
#define ULTRA_MEMORY_TYPE_MODULE 0xFFFF0002
#define ULTRA_MEMORY_TYPE_KERNEL_STACK 0xFFFF0003
#define ULTRA_MEMORY_TYPE_KERNEL_BINARY 0xFFFF0004Reserved. If encountered, must be considered a fatal error.
General purpose memory free for use by the kernel.
Memory reserved by the firmware.
Memory tagged as ACPI reclaimable by the firmware. Usually contains ACPI tables.
Same as MEMORY_TYPE_RESERVED. Consult the ACPI specification for more information.
Memory reserved by the bootloader. Contains temporary GDT, all attributes, memory map itself, loader code, and everything else the loader has allocated the memory for. The actual location of all the aforementioned structures within this range is unspecified.
Can be reclaimed by the kernel when it no longer needs the loader-provided structures.
Memory region containing one or more kernel modules
Memory region reserved by the loader for the kernel stack. Not necessarily the same value as SP for higher half kernels.
Memory region reserved by the loader for the loaded kernel binary (not the ELF copy).
Reserved for future use. Must be considered same as ULTRA_MEMORY_TYPE_RESERVED if encountered by the kernel.
The number of memory map entries can be calculated using the following C macro:
#define ULTRA_MEMORY_MAP_ENTRY_COUNT(header) ((((header).size) - sizeof(struct ultra_attribute_header)) / sizeof(struct ultra_memory_map_entry))Every loaded kernel module gets a respective attribute of this type, this means
ultra_boot_context must contain as many attributes of this type as there are modules.
This attribute provides information necessary to locate a kernel module in memory and has the following structure:
struct ultra_module_info_attribute {
struct ultra_attribute_header header;
uint32_t reserved;
uint32_t type;
char name[64];
uint64_t address;
uint64_t size;
char description[];
};header- standard attribute headerreserved- for use by future versions of the protocol, must be ignoredtype- type of this module, can be one of the following values:
#define ULTRA_MODULE_TYPE_INVALID 0
#define ULTRA_MODULE_TYPE_FILE 1
#define ULTRA_MODULE_TYPE_MEMORY 2Reserved. If encountered, must be considered a fatal error.
File-backed module.
Contiguous zeroed memory module.
name- null-terminated ASCII name of the module, as specified in the configuration file or"__KERNEL__"for the autogenerated kernel binary module (if enabled)address- address of the loaded module, page alignedsize- size of the module as specified inmodule/size, the actual size in RAM is this value rounded up to page sizedescription- optional null-terminated ASCII description of the module, as specified in the configuration file
A module only carries a description if one was provided in the configuration file. Whether a description is present can be tested with the following C macro:
#define ULTRA_MODULE_HAS_DESCRIPTION(header) ((((header).size) - sizeof(struct ultra_module_info_attribute)) > 0)Note that the length of the description cannot be derived from header.size because the attribute is padded for alignment,
so str{n}len() or similar must be used to determine it.
This attribute forwards the configuration file command line to the kernel if one was provided and has the following structure:
struct ultra_command_line_attribute {
struct ultra_attribute_header header;
char text[];
};header- standard attribute headertext- null terminated ASCII command line, as specified in the configuration file
Length of the command line is not artificially limited in any way but must fit in the header.size field,
which is 32 bits wide.
Note that header.size is not necessarily equal to the length of the command line
because of alignment reasons.
This attribute provides framebuffer information if one was requested and has the following structure:
struct ultra_framebuffer_attribute {
struct ultra_attribute_header header;
struct ultra_framebuffer fb;
};header- standard attribute headerfb- describes the allocated framebuffer and has the following structure:
struct ultra_framebuffer {
uint32_t width;
uint32_t height;
uint32_t pitch;
uint16_t bpp;
uint16_t format;
uint64_t physical_address;
};width- the number of visible pixels per row in the framebufferheight- the number of rows of visible pixels in the framebufferpitch- the number of bytes that each row takes in memorybpp- width in bits of each visible pixelformat- the format of the allocated framebuffer, and is one of the following values:
#define ULTRA_FB_FORMAT_INVALID 0
#define ULTRA_FB_FORMAT_RGB888 1
#define ULTRA_FB_FORMAT_BGR888 2
#define ULTRA_FB_FORMAT_RGBX8888 3
#define ULTRA_FB_FORMAT_XRGB8888 4Framebuffer format types are very similar to DRM_FORMAT_* and are defined as follows:
Reserved. If encountered, must be considered a fatal error.
Standard RGB format.
Layout of each pixel (low to high memory address):
| bits | 0 ... 8 | 8 ... 16 | 16 ... 24 |
|---|---|---|---|
| color | BLUE | GREEN | RED |
bpp must be set to 24.
Standard BGR format.
Layout of each pixel (low to high memory address):
| bits | 0 ... 8 | 8 ... 16 | 16 ... 24 |
|---|---|---|---|
| color | RED | GREEN | BLUE |
bpp must be set to 24.
Standard RGBX format padded to 32 bits.
Layout of each pixel (low to high memory address):
| bits | 0 ... 8 | 8 ... 16 | 16 ... 24 | 24 ... 32 |
|---|---|---|---|---|
| color | UNUSED | BLUE | GREEN | RED |
bpp must be set to 32.
Standard XRGB format padded to 32 bits.
Layout of each pixel (low to high memory address):
| bits | 0 ... 8 | 8 ... 16 | 16 ... 24 | 24 ... 32 |
|---|---|---|---|---|
| color | BLUE | GREEN | RED | UNUSED |
bpp must be set to 32.
physical_address- address of the allocated framebuffer
This attribute provides APM information if one was requested (via setup-apm) and has the following structure:
struct ultra_apm_attribute {
struct ultra_attribute_header header;
struct ultra_apm_info info;
};header- standard attribute headerinfo- describes the established APM interface and the general APM info, and has the following structure:
struct ultra_apm_info {
uint16_t version;
uint16_t flags;
uint16_t pm_code_segment;
uint16_t pm_code_segment_length;
uint32_t pm_offset;
uint16_t rm_code_segment;
uint16_t rm_code_segment_length;
uint16_t data_segment;
uint16_t data_segment_length;
};version- the APM version number, as reported by the installation check callflags- the APM flags, as reported by the installation check callpm_code_segment- the 32-bit code segmentpm_code_segment_length- the length of the 32-bit code segmentpm_offset- offset to the entry point into the APM BIOSrm_code_segment- the 16-bit code segmentrm_code_segment_length- the length of the 16-bit code segmentdata_segment- the 32-bit data segmentdata_segment_length- the length of the data segment
For more information, consult the APM BIOS Specification.
This attribute provides the UEFI system table and firmware memory map to the kernel,
and is only generated on the UEFI platform when requested via pass-uefi-info. It has
the following structure:
struct ultra_uefi_info_attribute {
struct ultra_attribute_header header;
uint64_t system_table_address;
uint32_t descriptor_size;
uint32_t descriptor_version;
uint32_t firmware_width;
uint32_t reserved;
uint8_t memory_descriptors[];
};header- standard attribute headersystem_table_address- physical address of theEFI_SYSTEM_TABLEdescriptor_size- size in bytes of a singleEFI_MEMORY_DESCRIPTORinmemory_descriptors, as reported byGetMemoryMap(). This may be larger thansizeof(EFI_MEMORY_DESCRIPTOR), so always use this value (neversizeof) to stride the array.descriptor_version- version of theEFI_MEMORY_DESCRIPTORstructure, as reported byGetMemoryMap()firmware_width- the native width of the UEFI firmware in bits, either32or64. A kernel loaded at a different width than the firmware (e.g. a 64-bit kernel on 32-bit UEFI) must operate in mixed mode to call runtime services.reserved- for use by future versions of the protocol, must be ignoredmemory_descriptors- the raw firmware memory map, a contiguous array ofEFI_MEMORY_DESCRIPTORentries exactly as returned byGetMemoryMap(), eachdescriptor_sizebytes apart
The number of memory descriptors can be calculated using the following C macro:
#define ULTRA_UEFI_INFO_MEM_DESC_COUNT(info) ((((info).header.size) - sizeof(struct ultra_uefi_info_attribute)) / (info).descriptor_size)Note that, unlike the other count macros, this one takes the whole attribute (not just its header)
as it also needs descriptor_size.
Boot services have already been exited by the time the kernel receives control, so the system
table may only be used for runtime services (and the configuration tables reachable through it).
Any boot-services-only field (BootServices, the console handles/protocols, etc.) is invalid.
The memory map is the exact one that was passed to ExitBootServices(), so it is suitable for a
subsequent SetVirtualAddressMap() call.
All structure definitions and macros can be found in the ultra_protocol.h file
compatible with both C and C++.
The current reference implementation of the protocol in C can be found at https://github.com/UltraOS/Hyper