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 |
Outputs a character to the debug port. |
|
Gets a list of possible RAM banks. |
|
Does any required setup for each RAM bank. |
|
Gets a list of possible ROM banks. |
|
Does any required setup for each ROM bank. |
|
Gets a list of required I/O mappings. |
|
Reserves physical RAM if required. |
|
Gets a list of configuration parameters. |
|
Does any final setup required before booting the kernel. |
|
Allocates RAM during boot. |
|
Gets MMU PDE permissions for a mapping. |
|
Gets MMU PTE permissions for a mapping. |
|
Called when a page table entry is updated. |
|
Enables the MMU. |
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.
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
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.
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
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:
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.
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
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:
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():
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.
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.
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.
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.
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.
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.
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.
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.
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.
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.