Unit DeviceTree

From Ultibo.org
Jump to: navigation, search

Return to Unit Reference


Description


Ultibo Flattened Device Tree (DTB) interface unit

Using Device Tree Blob (DTB) files for passing configuration information to the Linux kernel is now widely accepted as the standard method of providing platform specific information without it needing to be hard coded into the kernel at build time.

With this adoption of device tree by Linux it is becoming increasingly common for the only source of information about the runtime configuration of specific hardware to be found in the blob loaded and configured during startup by the firmware and passed to the kernel at the beginning of the boot process.

While Ultibo targets a much smaller range of devices than Linux and does not need the generic kernel model it still requires detailed configuration information in order to be able to interface with the full range of available devices.

It can also benefit from the ability to adapt to the runtime environment by checking for known device tree parameters while registering and initializing hardware and devices. Use of device tree is considered optional and Ultibo will operate correctly with or without the information provided, however some devices may be forced to operate in a fall back or default mode without the complete configuration.

Constants



DTB signature DTB_*
DTB_MAGIC = $D00DFEED;  


DTB version DTB_VERSION_*
DTB_VERSION_17 = 17;  
DTB_VERSION_16 = 16;  
 
DTB_VERSION_CURRENT = DTB_VERSION_17;  
DTB_VERSION_COMPATIBLE = DTB_VERSION_16;  


DTB token DTB_*_NODE
DTB_BEGIN_NODE = $00000001; The FDT_BEGIN_NODE token marks the beginning of a node’s representation, followed by the node’s unit name as extra data.
DTB_END_NODE = $00000002; The FDT_END_NODE token marks the end of a node’s representation
DTB_PROP = $00000003; The FDT_PROP token marks the beginning of the representation of one property, followed by extra data describing the property.
DTB_NOP = $00000004; The FDT_NOP token will be ignored by any program parsing the device tree
DTB_END = $00000009; The FDT_END token marks the end of the structure block


DTB offset DTB_*_OFFSET
DTB_NODE_OFFSET = 4; Token
DTB_PROPERTY_OFFSET = 12; Token + Value Length + Name Offset


DTB alignment DTB_*_ALIGNMENT
DTB_STRUCTURE_ALIGNMENT = 4;  
DTB_RESERVATION_ALIGNMENT = 8;  


DTB node DTB_NODE_*
Standard nodes
DTB_NODE_ROOT = '/';  
DTB_NODE_CPUS = 'cpus';  
DTB_NODE_MEMORY = 'memory';  
DTB_NODE_CHOSEN = 'chosen';  
DTB_NODE_ALIASES = 'aliases';  
Other nodes
DTB_NODE_SYMBOLS = '__symbols__';  
DTB_NODE_OVERRIDES = '__overrides__';  


DTB path DTB_PATH_*
DTB_PATH_SEPARATOR = '/';  


DTB type DTB_TYPE_*
DTB_TYPE_UNKNOWN = 0;  
DTB_TYPE_EMPTY = 1; Value is empty. Used for conveying true-false information.
DTB_TYPE_U32 = 2; A 32-bit integer in big-endian format
DTB_TYPE_U64 = 3; Represents a 64-bit integer in big-endian format
DTB_TYPE_STRING = 4; Strings are printable and null-terminated
DTB_TYPE_ENCODED_ARRAY = 5; Format is specific to the property. See the property definition.
DTB_TYPE_PHANDLE = 6; A <u32> value. A phandle value is a way to reference another node in the devicetree.
DTB_TYPE_STRINGLIST = 7; A list of <string> values concatenated together


DTB properties DTB_PROPERTY_*
Standard properties
DTB_PROPERTY_COMPATIBLE = 'compatible'; The compatible property value consists of one or more strings that define the specific programming model for the device (Type: <stringlist>)
DTB_PROPERTY_MODEL = 'model'; The model property value specifies the manufacturer’s model number of the device (Type: <string>)
DTB_PROPERTY_PHANDLE = 'phandle'; The phandle property specifies a numerical identifier for a node that is unique within the devicetree (Type: <u32>)
DTB_PROPERTY_STATUS = 'status'; The status property indicates the operational status of a device (Type: <string>)
DTB_PROPERTY_ADDRESS_CELLS = '#address-cells'; Specifies the number of <u32> cells to represent the address in the reg property (Type: <u32>)
DTB_PROPERTY_SIZE_CELLS = '#size-cells'; Specifies the number of <u32> cells to represent the size in the reg property (Type: <u32>)
DTB_PROPERTY_REG = 'reg'; The reg property describes the address of the device’s resources within the address space defined by its parent bus (Type: <prop-encoded-array>)
DTB_PROPERTY_VIRTUAL_REG = 'virtual-reg'; The virtual-reg property specifies an effective address that maps to the first physical address specified in the reg property of the device node (Type: <u32>)
DTB_PROPERTY_RANGES = 'ranges'; The ranges property provides a means of defining a mapping or translation between address spaces (Type: <empty> or <prop-encoded-array>)
DTB_PROPERTY_DMA_RANGES = 'dma-ranges'; The dma-ranges property is used to describe the direct memory access (DMA) structure of a memory-mapped bus (Type: <empty> or <prop-encoded-array>)
DTB_PROPERTY_NAME = 'name'; The name property is a string specifying the name of the node (Type: <string>)
DTB_PROPERTY_DEVICE_TYPE = 'device_type'; The device_type property was used in IEEE 1275 to describe the device (Type: <string>)
Additional properties for Interrupt Generating Devices
DTB_PROPERTY_INTERRUPTS = 'interrupts'; The interrupts property defines the interrupt or interrupts that are generated by the device (Type: <prop-encoded-array>)
DTB_PROPERTY_INTERRUPT_PARENT = 'interrupt-parent'; The interrupt-parent property provides an explicit definition of an interrupt parent (Type: <phandle>)
DTB_PROPERTY_INTERRUPTS_EXTENDED = 'interrupts-extended'; The interrupts-extended property lists the interrupt(s) generated by a device (Type: <phandle> <prop-encoded-array>)
Additional properties for Interrupt Controllers
DTB_PROPERTY_INTERRUPT_CELLS = '#interrupt-cells'; The #interrupt-cells property defines the number of cells required to encode an interrupt specifier for an interrupt domain (Type: <u32>)
DTB_PROPERTY_INTERRUPT_CONTROLLER = 'interrupt-controller'; The presence of an interrupt-controller property defines a node as an interrupt controller node (Type: <empty>)
Additional Interrupt Nexus properties
DTB_PROPERTY_INTERRUPT_MAP = 'interrupt-map'; An interrupt-map is a property on a nexus node that bridges an interrupt domain to a parent domain (Type: <prop-encoded-array>)
DTB_PROPERTY_INTERRUPT_MAP_MASK = 'interrupt-map-mask'; An interrupt-map-mask property is specified for a nexus node in the interrupt tree (Type: <prop-encoded-array>)
Additional Memory Node properties
DTB_PROPERTY_INITIAL_MAPPED_AREA = 'initial-mapped-area'; Specifies the address and size of the Initial Mapped Area (Type: <prop-encoded-array>)
Additional Chosen Node properties
DTB_PROPERTY_BOOTARGS = 'bootargs'; A string that specifies the boot arguments for the client program (Type: <string>>)
DTB_PROPERTY_STDOUT_PATH = 'stdout-path'; A string that specifies the full path to the node representing the device to be used for boot console output (Type: <string>>)
DTB_PROPERTY_STDIN_PATH = 'stdin-path'; A string that specifies the full path to the node representing the device to be used for boot console input (Type: <string>>)
DTB_PROPERTY_INITRD_START = 'initrd-start'; The starting address of the initial ram disk (Type: <u32>)
DTB_PROPERTY_INITRD_END = 'initrd-end'; The ending address of the initial ram disk (Type: <u32>)
Additional CPUs Node properties
DTB_PROPERTY_CLOCK_FREQUENCY = 'clock-frequency'; Specifies the current clock speed of the CPU in Hertz (Type: <prop-encoded-array>)
DTB_PROPERTY_TIMEBASE_FREQUENCY = 'timebase-frequency'; Specifies the current frequency at which the timebase and decrementer registers are updated (Type: <propencoded-array>)
DTB_PROPERTY_ENABLE_METHOD = 'enable-method'; Describes the method by which a CPU in a disabled state is enabled (Type: <stringlist>)
DTB_PROPERTY_CPU_RELEASE_ADDR = 'cpu-release-addr'; The cpu-release-addr property is required for cpu nodes that have an enable-method property value of "spin-table" (Type: <u64>)
 
DTB_PROPERTY_POWER_ISA_VERSION = 'power-isa-version'; A string that specifies the numerical portion of the Power ISA version string (Type: <string>)
DTB_PROPERTY_CACHE_OP_BLOCK_SIZE = 'cache-op-block-size'; The block size in bytes upon which cache block instructions operate (Type: <u32>)
DTB_PROPERTY_RESERVATION_GRANULE_SIZE = 'reservation-granule-size'; The reservation granule size supported by this processor in bytes (Type: <u32>)
DTB_PROPERTY_MMU_TYPE = 'mmu-type'; Specifies the CPU’s MMU type (Type: <string>)
 
DTB_PROPERTY_TLB_SPLIT = 'tlb-split'; Specifies that the TLB has a split configuration (Type: <empty>)
DTB_PROPERTY_TLB_SIZE = 'tlb-size'; Specifies the number of entries in the TLB (Type: <u32>)
DTB_PROPERTY_TLB_SETS = 'tlb-sets'; Specifies the number of associativity sets inthe TLB (Type: <u32>)
DTB_PROPERTY_D_TLB_SIZE = 'd-tlb-size'; Specifies the number of entries in the data TLB (Type: <u32>)
DTB_PROPERTY_D_TLB_SETS = 'd-tlb-sets'; Specifies the number of associativity sets in the data TLB (Type: <u32>)
DTB_PROPERTY_I_TLB_SIZE = 'i-tlb-size'; Specifies the number of entries in the instruction TLB (Type: <u32>)
DTB_PROPERTY_I_TLB_SETS = 'i-tlb-sets'; Specifies the number of associativity sets in the instruction TLB (Type: <u32>)
 
DTB_PROPERTY_CACHE_UNIFIED = 'cache-unified'; Specifies the cache has a unified organization (Type: <empty>)
DTB_PROPERTY_CACHE_SIZE = 'cache-size'; Specifies the size in bytes of a unified cache (Type: <u32>)
DTB_PROPERTY_CACHE_SETS = 'cache-sets'; Specifies the number of associativity sets in a unified cache (Type: <u32>)
DTB_PROPERTY_CACHE_BLOCK_SIZE = 'cache-block-size'; Specifies the block size in bytes of a unified cache (Type: <u32>)
DTB_PROPERTY_CACHE_LINE_SIZE = 'cache-line-size'; Specifies the line size in bytes of a unified cache (Type: <u32>)
DTB_PROPERTY_I_CACHE_SIZE = 'i-cache-size'; Specifies the size in bytes of the instruction cache (Type: <u32>)
DTB_PROPERTY_I_CACHE_SETS = 'i-cache-sets'; Specifies the number of associativity sets in the instruction cache (Type: <u32>)
DTB_PROPERTY_I_CACHE_BLOCK_SIZE = 'i-cache-block-size'; Specifies the block size in bytes of the instruction cache (Type: <u32>)
DTB_PROPERTY_I_CACHE_LINE_SIZE = 'i-cache-line-size'; Specifies the line size in bytes of the instruction cache (Type: <u32>)
DTB_PROPERTY_D_CACHE_SIZE = 'd-cache-size'; Specifies the size in bytes of the data cache (Type: <u32>)
DTB_PROPERTY_D_CACHE_SETS = 'd-cache-sets'; Specifies the number of associativity sets in the data cache (Type: <u32>)
DTB_PROPERTY_D_CACHE_BLOCK_SIZE = 'd-cache-block-size'; Specifies the block size in bytes of the data cache (Type: <u32>)
DTB_PROPERTY_D_CACHE_LINE_SIZE = 'd-cache-line-size'; Specifies the line size in bytes of the data cache (Type: <u32>)
DTB_PROPERTY_NEXT_LEVEL_CACHE = 'next-level-cache'; If present, indicates that another level of cache exists. (Type: <phandle>)
 
DTB_PROPERTY_CACHE_LEVEL = 'cache-level'; Specifies the level in the cache hierarchy (Type: <u32>)
Other Additional properties
DTB_PROPERTY_SERIAL_NUMBER = 'serial-number'; Serial Number (Type: <string>)
DTB_PROPERTY_ALLOC_RANGES = 'alloc-ranges'; Allocated Ranges (Type: <prop-encoded-array>)
DTB_PROPERTY_RESETS = 'resets'; Resets (Type: <prop-encoded-array>)
DTB_PROPERTY_CLOCK_CELLS = '#clock-cells'; Number of clock cells (Type: <u32>)
DTB_PROPERTY_LINUX_INITRD_START = 'linux,initrd-start'; The starting address of the initial ram disk (Type: <u32>)
DTB_PROPERTY_LINUX_INITRD_END = 'linux,initrd-end'; The ending address of the initial ram disk (Type: <u32>)


DTB property type DTB_*_PROPERTY_TYPE*
DTB_MAX_PROPERTY_TYPE = 60;  


Type definitions



DTB header

PDTBHeader = ^TDTBHeader;

TDTBHeader = packed record

Magic:LongWord; The value 0xd00dfeed (big-endian)
TotalSize:LongWord; The total size in bytes of the devicetree data structure (big-endian)
StructureOffset:LongWord; The offset in bytes of the structure block from the beginning of the header (big-endian)
StringsOffset:LongWord; The offset in bytes of the strings block from the beginning of the header (big-endian)
ReservationOffset:LongWord; The offset in bytes of the memory reservation block from the beginning of the header (big-endian)
Version:LongWord; The version of the devicetree data structure (big-endian)
CompatibleVersion:LongWord; The lowest version of the devicetree data structure with which the version used is backwards compatible (big-endian)
BootCPUID:LongWord; The physical ID of the system’s boot CPU (big-endian)
StringsSize:LongWord; The length in bytes of the strings block section of the devicetree blob (big-endian)
StructureSize:LongWord; The length in bytes of the structure block section of the devicetree blob (big-endian)

DTB reservation

PDTBReservation = ^TDTBReservation;

TDTBReservation = packed record

Address:UInt64; Physical address of a reserved memory region
Size:UInt64; Size in bytes of a reserved memory region

DTB node

PDTBNode = ^TDTBNode;

TDTBNode = packed record

Token:LongWord; Token (big-endian)
Name:array[0..0] of Char; The name stored as a null-terminated string, shall include the unit address if any.

DTB property

PDTBProperty = ^TDTBProperty;

TDTBProperty = packed record

Token:LongWord; Token (big-endian)
ValueLength:LongWord; The length of the property value in bytes
NameOffset:LongWord; The offset into the strings block of the property name stored as a null-terminated string
Value:array[0..0] of Byte; The property value as an array of bytes of value length

DTB property char

PDTBPropertyChar = ^TDTBPropertyChar;

TDTBPropertyChar = packed record

Token:LongWord; Token (big-endian)
ValueLength:LongWord; The length of the property value in bytes
NameOffset:LongWord; The offset into the strings block of the property name stored as a null-terminated string
Value:array[0..0] of Char; The property value as a string of value length

DTB property longWord

PDTBPropertyLongWord = ^TDTBPropertyLongWord;

TDTBPropertyLongWord = packed record

Token:LongWord; Token (big-endian)
ValueLength:LongWord; The length of the property value in bytes
NameOffset:LongWord; The offset into the strings block of the property name stored as a null-terminated string
Value:array[0..0] of LongWord; The property value as an array of longwords of value length (big-endian)

DTB property quadWord

PDTBPropertyQuadWord = ^TDTBPropertyQuadWord;

TDTBPropertyQuadWord = packed record

Token:LongWord; Token (big-endian)
ValueLength:LongWord; The length of the property value in bytes
NameOffset:LongWord; The offset into the strings block of the property name stored as a null-terminated string
Value:array[0..0] of UInt64; The property value as an array of quadwords of value length (big-endian)

DTB property type

TDTBPropertyType = record

Name:String;  
Encoding:LongWord;  

DTB logoutput

TDTBLogOutput = procedure(const AText:String; Data:Pointer);

DTB code value

TDTBDecodeValue = function(Node,Handle:THandle; Value:Pointer; Size:LongWord; Data:Pointer):String;


Public variables


None defined

Function declarations



Initialization functions

procedure DeviceTreeInit;
Description: Initialize the Device Tree unit
Note Called only during system startup


Device tree functions

function DeviceTreeValidate(Address:PtrUInt; var Size:LongWord):Boolean;
Description: Check the data at the supplied address to determine if it is a valid Device Tree Blob
Address The address to be validated
Size On return contains the total size of the Device Tree Blob if valid
Return True if the address points to a valid Device Tree Blob, False if not.
Note Does not overwrite passed Size unless the DTB is valid


function DeviceTreeNextNode(Parent,Previous:THandle):THandle;
Description: Find the next DTB node within the Device Tree
Parent Handle of the parent node to search in, INVALID_HANDLE_VALUE to search the entire tree
Previous Handle of the node to start from, INVALID_HANDLE_VALUE to start from the root node
Return The handle of the next node in the tree or INVALID_HANDLE_VALUE if no node was found


function DeviceTreeNextProperty(Node,Previous:THandle):THandle;
Description: Find the next DTB property within the specified node of the Device Tree
Node Handle of the node to search in
Previous Handle of the property to start from, INVALID_HANDLE_VALUE to start from the first property
Return The handle of the next property in the node or INVALID_HANDLE_VALUE if no property was found


function DeviceTreeGetNode(const Path:String; Parent:THandle):THandle;
Description: Get the handle of the node matching the specified path, optionally within a specified parent
Path The path of the node to find, relative to parent node or fully qualified if parent not specified (eg /chosen or /cpus/cpu0).
Parent Handle of the parent node to search in, INVALID_HANDLE_VALUE to search the entire tree.
Return The handle of the node which matches the path or INVALID_HANDLE_VALUE if no node was found


function DeviceTreeGetProperty(Node:THandle; const Name:String):THandle;
Description: Get the handle of the property matching the specified name
Node Handle of the node to search in
Name The name of the node to find (eg compatible)
Return The handle of the property which matches the name or INVALID_HANDLE_VALUE if no property was found


function DeviceTreeGetNodeName(Handle:THandle):String;
Description: Get the name of the specified node
Handle The handle of the node to get the name of
Return The name of the specified node or an empty string if the node was not valid


procedure DeviceTreeSplitNodeName(Handle:THandle; var NodeName,UnitAddress:String);
Description: Split the name of a node into node name and unit address
Handle The handle of the node to split the name of
NodeName The node name on return or an empty string if the node was not valid
UnitAddress The unit address on return (If applicable)


function DeviceTreeGetNodeParent(Handle:THandle):THandle;
Description: Get the parent node of the specified node
Handle The handle of the node to get the parent of
Return The handle of the parent node or INVALID_HANDLE_VALUE if the node was not valid


function DeviceTreeGetNodeRegCells(Handle:THandle; var Address,Size:LongWord):Boolean;
Description: Get the #address-cells and #size-cells values that apply to reg properties of the specified node
Handle The handle of the node to get the cell sizes for
Address The #address-cells value on return (or the default value if not found)
Size The #size-cells value on return (or the default value if not found)
Return True if the cell sizes were found or False if the node was not valid
Note The address and size values applicable to a given node will be those from a parent node, not those found in the node itself (if present).

Used by early stage boot stage processing which must limit the use of strings and other memory allocations. This function uses a memory compare for names.


function DeviceTreeGetNodeRangeCells(Handle:THandle; var ParentAddress,NodeAddress,NodeSize:LongWord):Boolean;
Description: Get the #address-cells and #size-cells values that apply to range properties of the specified node
Handle The handle of the node to get the cell sizes for
ParentAddress The #address-cells value from the parent on return (or the default value if not found)
NodeAddress The #address-cells value from this node on return (or the default value if not found)
NodeSize The #size-cells value from this node on return (or the default value if not found)
Return True if the cell sizes were found or False if the node was not valid
Note Range properties use the address value from the parent node and the address and size values from the node itself to determine the size of each range.

Used by early stage boot stage processing which must limit the use of strings and other memory allocations. This function uses a memory compare for names.


function DeviceTreeGetPropertyName(Handle:THandle):String;
Description: Get the name of the specified property
Handle The handle of the property to get the name of
Return The name of the specified property or an empty string if the property was not valid


procedure DeviceTreeSplitPropertyName(Handle:THandle; var UniquePrefix,PropertyName:String);
Description: Split the name of a property into property name and unique prefix
Handle The handle of the property to split the name of
UniquePrefix The unique prefix on return (If applicable)
PropertyName The property name on return or an empty string if the property was not valid


function DeviceTreeGetPropertyValue(Handle:THandle):Pointer;
Description: Get a pointer to the raw value of the specified property
Handle The handle of the property to get the value of
Return A pointer to the specified property value or nil if the property was not valid
Note The returned value points to the memory block where device tree is stored and should not be modified or freed


function DeviceTreeGetPropertyLength(Handle:THandle):LongWord;
Description: Get the length of the raw value of the specified property
Handle The handle of the property to get the value length of
Return The length of the specified property value in bytes or -1 if the property was not valid


function DeviceTreeGetPropertyString(Handle:THandle):String;
Description: Get the value of the specified property as a string
Handle The handle of the property to get the value of
Return A string representation of the value or an empty string if the property was not valid


function DeviceTreeGetPropertyLongWord(Handle:THandle):LongWord;
Description: Get the value of the specified property as a longword
Handle The handle of the property to get the value of
Return A longword representation of the value or 0 if the property was not valid


function DeviceTreeGetPropertyQuadWord(Handle:THandle):UInt64;
Description: Get the value of the specified property as a quadword
Handle The handle of the property to get the value of
Return A quadword representation of the value or 0 if the property was not valid


RTL Device tree functions

function SysDeviceTreeRead(const Path,Name:String; Buffer:Pointer; var Size:LongWord):LongWord;
Description: Implementation of DeviceTreeRead API
Note Not intended to be called directly by applications, use DeviceTreeRead instead.


function SysDeviceTreeRead32(const Path,Name:String; var Value:LongWord):LongWord;
Description: Implementation of DeviceTreeRead32 API
Note Not intended to be called directly by applications, use DeviceTreeRead32 instead.


function SysDeviceTreeRead64(const Path,Name:String; var Value:UInt64):LongWord;
Description: Implementation of DeviceTreeRead64 API
Note Not intended to be called directly by applications, use DeviceTreeRead64 instead.


function SysDeviceTreeReadString(const Path,Name:String; var Value:String):LongWord;
Description: Implementation of DeviceTreeReadString API
Note Not intended to be called directly by applications, use DeviceTreeReadString instead.


Device tree helper functions

function DeviceTreeGetBootArgs:PChar;
Description: Return a character pointer to the location of the command line in the device tree blob
Note Intended primarily for use by early boot stage processing which must limit the use of strings and other memory allocations

For normal use see DeviceTreeGetNode and DeviceTreeGetProperty


function DeviceTreeGetRamdisk(var Address:PtrUInt; var Size:UInt64):Boolean;
Description: Return the address and size of the initial ram disk specified in the device tree blob
Address Used to return the address value
Size Used to return the size value
Return True if an initial ram disk was specified in the device tree, False if not.
Note Intended primarily for use by early boot stage processing which must limit the use of strings and other memory allocations

For normal use see DeviceTreeGetNode and DeviceTreeGetProperty


function DeviceTreeGetMemory(Index:LongWord; var Range:LongWord; var Address:PtrUInt; var Size:UInt64):Boolean;
Description: Return the address and size of a memory block specified in the device tree blob
Index The index of the memory block to return (The first block is 0)
Range Used to return the page range value (If applicable)
Address Used to return the address value
Size Used to return the size value
Return True if the memory block requested was found in the device tree, False if not.
Note Intended primarily for use by early boot stage processing which must limit the use of strings and other memory allocations

For normal use see DeviceTreeGetNode and DeviceTreeGetProperty


function DeviceTreeGetReservation(Index:LongWord; var Address:PtrUInt; var Size:UInt64):Boolean;
Description: Return the address and size of a memory reservation specified in the device tree blob
Index The index of the memory reservation to return (The first reservation is 0)
Address Used to return the address value
Size Used to return the size value
Return True if the memory reservation requested was found in the device tree, False if not.


function DeviceTreeLogTree:LongWord;
Description: Print information about all nodes and properties in the device tree
Return ERROR_SUCCESS if completed or another error code on failure


function DeviceTreeLogTreeEx(Node:THandle; Output:TDTBLogOutput; Decode:TDTBDecodeValue; Data:Pointer):LongWord;
Description: Print information about one or all nodes and properties in the device tree with custom value decode callback
Node The node to print information about (INVALID_HANDLE_VALUE for all nodes)
Output The log output callback to print information to (nil to use the default output)
Decode The callback to decode a value into a string (nil to use the default decode)
Data A pointer to call specific data which should be passed to the callbacks (Optional)
Return ERROR_SUCCESS if completed or another error code on failure


Return to Unit Reference