Boot Table Functions

Describes how to implement the functions that the bootstrap implementation must provide.

The boot table function entries are summarised in the following table. Each is identified by its TBootTableEntry enumerator that defines its position in the table. Click the enumerator symbol for more detail on what the function must do.

Enumerator symbol

Summary description

BTF_WriteC

Outputs a character to the debug port.

BTF_RamBanks

Gets a list of possible RAM banks.

BTF_SetupRamBank

Does any required setup for each RAM bank.

BTF_RomBanks

Gets a list of possible ROM banks.

BTF_SetupRomBank

Does any required setup for each ROM bank.

BTF_HwBanks

Gets a list of required I/O mappings.

BTF_Reserve

Reserves physical RAM if required.

BTF_Params

Gets a list of configuration parameters.

BTF_Final

Does any final setup required before booting the kernel.

BTF_Alloc

Allocates RAM during boot.

BTF_GetPdePerm

Gets MMU PDE permissions for a mapping.

BTF_GetPtePerm

Gets MMU PTE permissions for a mapping.

BTF_PTUpdate

Called when a page table entry is updated.

BTF_EnableMMU

Enables the MMU.

BTF_WriteC

What the function should do

On non-debug bootstrap builds, where CFG_DebugBootRom is set to FALSE, the function should return immediately without doing anything.

On debug bootstrap builds, where CFG_DebugBootRom is set to TRUE, the function should output a single character to the debug port.

It may be necessary to examine the TRomHeader::iDebugPort field to determine the correct destination for the character. The function should not modify any registers, but may change flags.

This function can be called with the MMU either disabled or enabled. Different I/O port addresses will normally be required in these two cases. To simplify handling of this the following macro is provided:

GET_ADDRESS    Rd,    PHYSICAL,    LINEAR

Where Rd specifies any ARM general purpose register. PHYSICAL is the physical address of the peripheral, LINEAR is its linear address.

On the direct memory model, the PHYSICAL address is always loaded into Rd. On the moving or multiple memory models the macro performs a runtime check of the CP15 control register to determine whether the MMU is enabled. If the MMU is enabled, then the LINEAR address is loaded into Rd, otherwise the PHYSICAL address is loaded.

Note that CFG_DebugBootRom is set in the platform specific configuration header file.

Entry conditions

  • R0 bottom 8 bits contain the character to be output

  • R10 points to the super page, represented by the SSuperPageBase struct defined in os/kernelhwsrv/kernel/eka/include/kernel/kernboot.h

  • R12 points to the ROM header, a TRomHeader object

  • R13 points to a valid stack.

BTF_RamBanks

What the function should do

This function should return a pointer to a list of RAM banks that are present.

The list should be a sequence of two-word entries. Each entry has the following format:

The list is terminated by an entry that has a zero MAXSIZE.

Of the 32 flag bits, only one is currently defined; all undefined flags should be zero. Flag 0, which is bit 0 of the first word is the RAM_VERBATIM flag and is interpreted as follows:

  • If clear, the specified physical address range may or may not contain RAM, and may be only partially occupied. In this case generic bootstrap code will probe the range to establish if any RAM is present, and if so, which parts of the range are occupied. This process is accompanied by calls to BTF_SetupRamBank. In order for the probing algorithm to work MAXSIZE must be a power of 2 (greater than or equal to 64K), and BASE must be a multiple of MAXSIZE.

  • If set, the specified physical range is known to be fully occupied by RAM, and furthermore, that all memory controller setup for that range has already been completed. In this case BTF_SetupRamBank will not be called for this range.

Note that all banks declared in this list and subsequently found to be occupied will be treated as standard RAM available for any purpose. For this reason, internal RAM or TCRAM banks are not generally included in the list.

Entry conditions

  • R10 points to the superpage, represented by the SSuperPageBase struct defined in os/kernelhwsrv/kernel/eka/include/kernel/kernboot.h

  • R12 points to the ROM header, a TRomHeader object

  • R13 points to a valid stack

  • the MMU is disabled.

Exit conditions

  • R0 should contain the base address of the list of banks

  • R0 -R3 and flags may be modified, but no other registers should be modified.

BTF_SetupRamBank

What the function should do

The function should do any required setup for each RAM bank.

This function is called twice for each RAM bank that does not have the RAM_VERBATIM flag set (see the reference to the flag bits in the description of BTF_RamBanks).

The first call is prior to RAM bus width detection, and the second call is after width detection.

This function is only required if the system has a complex and very variable RAM setup, for example several banks of potentially different widths. Typical systems have one or two banks of RAM of known width and all memory controller initialisation can be done in theInitialiseHardware() function; in this case this function can simply return without performing any operation.

Entry conditions

  • R1 holds the physical base address of a bank

  • R3 = 0xFFFFFFFF for the first call

    R3 = 0x0000000Y for the second call, where the bottom 4 bits represent the validity of each of the 4 byte lanes (bit 0=1 if D0-7 are valid, bit 1=1 if D8-15 are valid, etc.)

  • R10 points to the super page, represented by the SSuperPageBase struct defined in os/kernelhwsrv/kernel/eka/include/kernel/kernboot.h

  • R12 points to the ROM header, a TRomHeader object

  • R13 points to a valid stack

  • the MMU is disabled.

Exit conditions

Other than flags, no registers should be modified.

BTF_RomBanks

What the function should do

This function should return a pointer to a list of XIP ROM banks that are present. It is not called if the bootstrap is found to be running in RAM; in this case it is assumed that all XIP code is in RAM.

The list should be a sequence of four-word entries. Each entry has the following format:

The list is terminated by a zero value four-word entry.

Only the first, second and fourth words of each entry are actually used by the rest of the bootstrap. The third is there mainly to support autodetection schemes.

The ROM_BANK macro can be used to declare ROM bank entries.

Entry conditions

  • R10 points to the super page, represented by the SSuperPageBase struct defined in os/kernelhwsrv/kernel/eka/include/kernel/kernboot.h

  • R12 points to the ROM header, a TRomHeader object

  • R13 points to a valid stack

  • the MMU is disabled.

Exit conditions

  • R0 should contain the base address of the list of ROM banks.

  • R0 -R3 and flags may be modified, but no other registers should be modified.

BTF_SetupRomBank

What the function should do

The function should do any required setup for each ROM bank.

It is called once immediately after the call to BTF_RomBanks and then it is subsequently called again for each ROM bank in the list returned by BTF_RomBanks. It is not called if the bootstrap is running in RAM.

This function is intended to support autodetection of the system ROM configuration. For example, the first call with R11 set to zero could be used to set the bus controller to 32 bit width to enable width detection to be performed on ROM banks other than the boot block. Subsequent per-bank calls could determine the width (possibly using an algorithm that repeatedly reads from the same address and checks which bits are consistent) and the size of the ROM bank. These would be written to the entry pointed by R11 and the bus controller set up correctly for that ROM bank. If the bank is absent, then the size in the structure pointed to by R11 is set to zero to remove it from the list.

Entry conditions

  • R10 points to the super page, represented by the SSuperPageBase struct defined in os/kernelhwsrv/kernel/eka/include/kernel/kernboot.h

  • On the first call:

    • R11 contains 0

    • R0 contains the base address of the list of ROM banks returned by BTF_RomBanks

    On subsequent calls:

    • R11 points to a RAM copy of the entry corresponding to the ROM bank currently being processed

  • R12 points to the ROM header, a TRomHeader object

  • R13 points to a valid stack

  • the MMU is disabled.

Exit conditions

For calls where R11 is non-zero, the entry pointed to by R11 may be modified by this function call.

If the entry size for a bank is set to zero, then that bank is assumed not to exist, and is removed from the list of ROM banks.

Registers R0 -R4 and flags may be modified by this function; all other registers should be preserved.

BTF_HwBanks

What the function should do

This function should return a pointer to a list of required I/O mappings.

The list should be a sequence of one-word and two-word entries, terminated by a zero-filled word. The entries in the list are defined using the macros for declaring I/O mappings: HW_MAPPING, HW_MAPPING_EXT, HW_MAPPING_EXT2, and HW_MAPPING_EXT3.

In the template port, this is implemented in os/kernelhwsrv/bsptemplate/asspandvariant/template_variant/bootstrap/template.s. Find the symbol GetHwBanks:

GetHwBanks    ROUT
        ADR        r0, %FT1
        MOV        pc, lr
        ...
        DCD            0                                            ; terminator

The pointer in the boot table to this list of I/O mappings is defined by the symbol GetHwBanks.

BootTable
    ...
    DCD    GetHwBanks                ; get list of HW banks
    ...

To support Level 2 cache (either L210 or L220), you need to add the base address of the Level 2 cache controller to the list of hardware banks. For example:

GetHwBanks  ROUT
        ADR     r0, %FT1
        MOV     pc, lr
        ...
        HW_MAPPING  L210CtrlBasePhys, 1, HW_MULT_1M
        ...
        DCD     0                                 ; terminator

See also theInitialiseHardware() function.

Entry conditions

  • R10 points to the super page, represented by the SSuperPageBase struct defined in os/kernelhwsrv/kernel/eka/include/kernel/kernboot.h

  • R12 points to the ROM header, a TRomHeader object

  • R13 points to a valid stack

  • the MMU is disabled.

Exit conditions

  • R0 should contain the base address of the list of banks

  • R0 -R3 and flags may be modified, but no other registers should be modified.

BTF_Reserve

What the function should do

The function reserves physical RAM if required.

It is called before the bootstrap's memory allocator (BTF_Alloc) is initialised to allow physical RAM to be reserved for any platform specific purpose.

There are two methods available for reserving physical RAM:

  1. Use the generic bootstrap function ExciseRamArea(), implemented in os/kernelhwsrv/kernel/eka/kernel/arm/bootutils.s. This removes a specified region from the list of RAM blocks present in the system. Subsequently, the excised area will no longer be treated as RAM. If this method is used, then the excised areas must be a multiple of 64K in size and aligned to a 64K boundary.

    The following entry conditions apply when calling ExciseRamArea():

    • R0 = physical base address of the area to be excised

    • R1 = size of area to be excised

    • R9 = SSuperPageBase::iRamBootData

    • R10 points to the super page

    • R11 = 0

    • R13 points to a valid stack.

  2. Write a list of reserved RAM blocks to the address passed in R11. The list should consist of two-word entries, the first word being the physical base address of the block and the second word the size. The list is terminated by an entry with zero size. The listed blocks will still be recognised as RAM by the kernel but will be marked as allocated during kernel boot. The blocks in the list should be multiples of 4K in size and aligned to a 4K boundary.

If both methods are used simultaneously, then the ExciseRamArea() function will require recalculation of the value in R11 for the second method. The correct value can be found by loading R11 first with SSuperPageBase::iRamBootData, stepping forward 8 bytes at a time until an entry with a zero-filled second word is found, and then stepping on by a further 8 bytes.

Entry conditions

  • R10 points to the super page, represented by the SSuperPageBase struct defined in os/kernelhwsrv/kernel/eka/include/kernel/kernboot.h

  • r11 points to the place where the pre-allocated block list should be written

  • R12 points to the ROM header, a TRomHeader object

  • R13 points to a valid stack

  • the MMU is disabled.

Exit conditions

The function can modify R0, R1, R2,R3, R11 and the flags, but should preserve all other registers.

BTF_Params

What the function should do

The function should return the value of a run-time configurable boot parameter. The parameter is identified by one of the values of the TBootParam enumeration, which is passed in R0.

Typically, the function is implemented as follows:

GetParameters ROUT
    ADR    r1, ParameterTable
    B    FindParameter
ParameterTable    ; Include any parameters specified in TBootParam
                ; enum here if you want to override them.
    DCD    BPR_x, value    ; parameter number, parameter value
    DCD    -1                ; terminator

This implementation calls the generic function FindParameter(), which performs the necessary lookup of the parameter number in the table. The parameter table should consist of a list of two-word entries, the first word being the parameter number and the second the parameter value. The list should be terminated by a negative parameter number. The generic function searches this table for the parameter value, and if found, returns it in R0 as stated in Exit conditions.

Note that the address of this parameter table is also passed to the InitCpu() function by the InitialiseHardware() public function.

Each entry in the boot parameter table is identified by a TBootParam enumeration value that defines its position within that table. The entries have the following meaning:

Enumerator symbol

Summary description

BPR_InitialMMUCRClear

Mask of bits to clear in MMUCR in the InitCpu() generic function. Defaults to 0xFFFFFFFF, i.e. clear all bits.

BPR_InitialMMUCRSet

Mask of bits to set in MMUCR in the InitCpu() generic function after clearing those specified by BPR_InitialMMUCRClear. Defaults to a CPU-dependent value.

BPR_FinalMMUCRClear

Mask of bits to clear in MMUCR when the MMU is enabled. Defaults to 0, which means do not clear any bits.

BPR_FinalMMUCRSet

Mask of bits to set in MMUCR when the MMU is enabled after clearing those specified in BPR_FinalMMUCRSet. Defaults to a CPU-dependent value.

BPR_AuxCRClear

Mask of bits to clear in AUXCR in the InitCpu() Symbian platform generic function. Defaults to a CPU dependent value.

BPR_AuxCRSet

Mask of bits to set in AUXCR in the InitCpu() Symbian platform generic function after clearing those specified by BPR_InitialAUXCRClear. Defaults to a CPU-dependent value.

BPR_CAR

Initial value to set for coprocessor access register if present. Defaults to 0.

BPR_UncachedLin

Mandatory parameter on the direct memory model, not used on other memory models. The value is copied into SSuperPageBase::iUncachedAddress for use by any code which needs to do an uncached memory access, usually for memory controller synchronisation purposes. On systems with an MMU, this address will be mapped as an alias of the super page and must refer to the base address of a 1Mb region of unused virtual address space, aligned on a 1Mb boundary. On a system with no MMU, this address should be the physical address of some uncached memory.

BPR_PageTableSpace

Used only on the direct memory model on systems with an MMU. Specifies the amount of RAM to reserve for page tables. Defaults to 32K.

BPR_KernDataOffset

Used only on the direct memory model. Specifies the offset from the base of the super page to the base of the kernel .data section. Defaults to 8K.

BPR_BootLdrImgAddr

Mandatory parameter for bootloader configurations; not required for other configurations. Specifies the physical base address of the RAM-loaded image.

BPR_BootLdrExtraRAM

Only used on bootloader configurations. Specifies the amount of 'user' memory to reserve (this is in fact used to satisfy Epoc::AllocPhysicalRam requests, usually for video RAM) in the case where the RAM-loaded image is at the bottom of RAM and so the bootloader RAM is at the top. Defaults to 1MB.

Entry conditions

  • R0 contains the number identifying the required parameter; see the TBootParam enumerator defined in os/kernelhwsrv/kernel/eka/include/kernel/arm/bootdefs.h.

  • R10 points to the super page, represented by the SSuperPageBase struct defined in os/kernelhwsrv/kernel/eka/include/kernel/kernboot.h

  • r11 points to the place where the pre-allocated block list should be written

  • R12 points to the ROM header, a TRomHeader object

  • R13 points to a valid stack

  • the MMU is disabled.

Exit conditions

If the parameter value is specified, it should be returned in R0 and the N flag should be cleared.

If the parameter value is not specified, the N flag should be set.

Registers R0 , R1, R2 and the flags may be modified. All other registers should be preserved.

BTF_Final

What the function should do

The function should do any final setup required before booting the kernel. It is called at the end of the bootstrap, just before booting the kernel.

The function should:

  • Map any cache flushing areas required by the CPU.

    Processors that flush the data cache by reading dummy addresses or by allocating dummy addresses into the cache (e.g. StrongARM and XScale processors) will need a main cache flush area. If the processor has an alternate data cache (e.g. StrongARM and XScale mini data cache) a second flush area may be required for it. On the moving and multiple memory models the linear addresses used for these flushing areas are fixed (KDCacheFlushArea and KDCacheFlushArea +1MB respectively). On the direct memory model any unused linear address may be selected. The linear addresses used should be written into SSuperPageBase::iDCacheFlushArea and SSuperPageBase::iAltDCacheFlushArea. In addition, the fields SSuperPageBase::iDCacheFlushWrap and SSuperPageBase::iAltDCacheFlushWrap should be written with a power of 2 at least twice the cache size and no bigger than half the reserved address area. A value of 0x00080000 (512KB) is usually used.

  • Populate any super page or CPU page fields with platform-specific information used by the variant, for example addresses of CPU idle routines in the bootstrap. Routines can be placed in the bootstrap if known alignment is required for the routine.

Entry conditions

  • R10 points to the super page, represented by the SSuperPageBase struct defined in os/kernelhwsrv/kernel/eka/include/kernel/kernboot.h

  • r11 points to the kernel image header, a TRomImageHeader object

  • R12 points to the ROM header, a TRomHeader object

  • R13 points to a valid stack

  • the MMU is disabled.

Exit conditions

Registers R0 to R9 and flags may be modified; other registers should be preserved.

BTF_Alloc

What the function should do

Allocates RAM during boot.

This function is called at various points to initialise the memory allocator, or to allocate physical RAM. A generic implementation is provided for this function and this will normally be sufficient, so a typical implementation for this function reduces to:

DCD HandleAllocRequest

in the boot table. For systems with no MMU, the function name should be changed to AllocatorStub.

It is advisable not to override this function.

Entry conditions

  • R2 contains the type of allocation required; this is defined by one of the values of the TBootMemAlloc enumeration

  • R4 contains the size to allocate (as a log to base 2) for allocations of type BMA_Kernel

  • R10 points to the super page, represented by the SSuperPageBase struct defined in os\kernelhwsrv\kernel\eka\include\kernel\kernboot.h

  • R12 points to the ROM header, a TRomHeader object

  • R13 points to a valid stack

  • the MMU may be enabled or disabled.

The type of allocation required is defined by the value of the enumerator TBootMemAlloc, defined in os/kernelhwsrv/kernel/eka/include/kernel/arm/bootdefs.h. The allocation types are as follows:

Enumerator symbol

Summary description

BMA_Init

Called to initialise the memory allocator.

BMA_SuperCPU

Should return the physical address of the super page in R0.

BMA_PageDirectory

Should return the physical address of the page directory in R0.

BMA_PageTable

Allocate a new page table (1KB size and 1KB alignment) and return its physical address in R0. It is not necessary to clear the page table here.

BMA_Kernel

Allocate a page of size 2R4. This must be a valid processor page size; on ARM this means R4=12, 16 or 20. The returned physical address will be a multiple of 2R4. If no page of the requested size can be allocated a page of the largest possible smaller size will be allocated and R4 will be modified accordingly.
Note: If no page of any size can be allocated this call will fault the system.

BMA_Reloc

Called when the allocator data structures need to be relocated in memory. On entry R0 contains the offset to apply to all pointers (that is, the new address of data minus the old address). It is assumed that all the allocator data is contained in the super page or CPU page and that there are no pointers to areas which could be relocated independently.

Exit conditions

R0 and flags may be modified. For BMA_Kernel allocations, R4 may also be modified. All other registers should be preserved.

BTF_GetPdePerm

What the function should do

This function is called at various points to translate a standardised permission descriptor along with the size of mapping required to the PDE permission/attribute bits needed for such a mapping. A standardised permission descriptor can be either an index into the boot table (for any of the standard permission types) or the value generated by a BTP_ENTRY macro.

A generic implementation is provided for this function and it should not be necessary to override it. A typical implementation for this function then just reduces to:

DCD GetPdeValue

in the boot table.

Note that for systems with no MMU, this function is not required.

BTF_GetPtePerm

What the function should do

This function is called at various points to translate a standardised permission descriptor along with the size of mapping required to the PTE permission/attribute bits needed for such a mapping. A standardised permission descriptor can be either an index into the boot table (for any of the standard permission types) or the value generated by BTP_ENTRY macro.

A generic implementation is provided for this function and it should not be necessary to override it. In the boot table, a typical implementation for this function then reduces to:

DCD GetPteValue

Note that for systems with no MMU, this function is not required.

BTF_PTUpdate

What the function should do

This function is called whenever a PDE or PTE is updated. It performs whatever actions are required to make sure that the update takes effect. This usually means draining the write buffer and flushing the TLB (both TLBs on a Harvard architecture system).

A generic implementation is provided for this function and it should not be necessary to override it. In the boot table, a typical implementation for this function then reduces to:

DCD PageTableUpdate

Note that for systems with no MMU, this function is not required.

BTF_EnableMMU

What the function should do

This function is called to enable the MMU and thereby switch from operating with physical addresses to operating with virtual addresses.

A generic implementation is provided for this function and it should not be necessary to override it. In the boot table, a typical implementation for this function then reduces to:

DCD EnableMmu

Note that for systems with no MMU, this function is not required.