From reset to startup

Updated: April 19, 2023

Due to the different board architectures and processes handled by the board firmware, IPLs for x86 and ARM platforms are very different.

Despite their differences, IPLs for all board families have completed their work when they have loaded the IFS into memory and jumped to the startup code. They all have at least the following in common:

The figure below shows, at a high level, the sequence of components that initialize and boot a board, for each of the x86 and ARM platforms. Even though the startup code differs between the platforms, this code is considered the point of convergence, because it is the first OS code to run. The ARM sequence shows a Boot ROM, but some boards do not use Boot ROM or use a first-stage, low-level Boot ROM.

Figure 1. The boot processes for x86 and ARM platforms.

In the diagram above, the files with the first code to be executed are called _start for both the x86 and ARM platforms.

The linker file

For both x86 and ARM boards, the file with the assembly code at the reset vector is specified in the linker file (e.g., qnx-x86.lnk or qnx-arm.lnk). For example, assuming that the QNX ARM Estragon board is 32-bit little endian, qnx-arm-board_name.lnk might begin as follows:

TARGET(elf32-littlearm)
OUTPUT_FORMAT(elf32-littlearm)
ENTRY(_start-arm-board_name)
MEMORY
{
    stack_top      :    ORIGIN = 0x402f93FC,    LENGTH = 0x0
    stack_space    :    ORIGIN = 0x402f7400,    LENGTH = 0x2000
    ram            :    ORIGIN = 0x402f0400,    LENGTH = 0x7000

    /* TLB table must be aligned to 16K (0x4000) */
    tlb         :   ORIGIN = 0x40310000,    LENGTH = 0x4000

    /* dedicated for non-cacheble buffer */
    scratch     :   ORIGIN = 0x80000000,    LENGTH = 0x100000
}

SECTIONS
{
    .text : {
            _start.o(.text)
            *(.text)
            ...