The bootstrap file

QNX SDP8.0Building Embedded SystemsConfigurationDeveloper

The first section of the buildfile is the bootstrap file. This inline file specifies the processor architecture, the name of the startup program, the OS kernel, and some environment variables.

The first section of the buildfile example presented above in Buildfile structure and contents is:
[image=0x80200000]
[virtual=aarch64le,elf] .boot = {
  startup-honeycomb_lx2 -W 
  PATH=/proc/boot:/sbin:/bin:/usr/bin:/usr/sbin:/usr/libexec 
  LD_LIBRARY_PATH=/proc/boot:/lib:/usr/lib:/lib/dll:/lib/dll/pci 
  procnto-smp-instr -v
}
If we parse this section, we find the following:
  • The image attribute specifies the offset in memory where the bootable image starts.
  • The virtual attribute specifies a virtual addressing model for the image to be built. (QNX doesn't currently support a physical addressing model.)
  • aarch64le specifies that the target system CPU is a little-endian AArch64 processor (see Specifying the board architecture below).
  • elf specifies the IFS layout of Executable and Linkable Format (ELF). The other common layout for ARM processors is bin for binary.
  • .boot introduces an inline file (inside the brace brackets).

Specifying the board architecture

When you build your OS image, you build it for a specific board architecture. You can use the PROCESSOR environment variable or the buildfile virtual attribute to indicate this architecture to mkifs, which then uses this information to learn the path to the components it needs to build your OS image.
  • If you don’t set PROCESSOR before you run mkifs and you don't set the virtual attribute in your buildfile, mkifs sets PROCESSOR to x86_64 and builds an image for an x86_64 board.
  • If you set PROCESSOR before you run mkifs but you don't set the virtual attribute in your buildfile, mkifs uses the value you specified for PROCESSOR and builds an image for that board architecture.
  • Even if you set PROCESSOR, if you set the virtual attribute in your buildfile, mkifs uses the value specified by the virtual attribute: it updates PROCESSOR and builds an image for that board architecture.

    For example, if you set PROCESSOR to x86_64 and the virtual attribute to aarch64le, mkifs updates PROCESSOR to aarch64le and builds an image for an ARM 64-bit, little-endian board.

The settings that mkifs uses to determine the board architecture for an image it will build are as follows:
PROCESSOR virtual Source of value mkifs uses
Not set Not set x86_64 (default)
Set Not set PROCESSOR
Not set Set virtual (updates PROCESSOR)
Set Set virtual (updates PROCESSOR)

Optional modules

You can use the buildfile [module=...] modifier to bind a module into procnto when you build the image. In this release, no kernel modules are shipped so this modifier isn't needed.

Compressing the OS image

You can use the [+compress] attribute to compress the entire image, except the startup code and the startup header, which are needed to decompress the image.

To compress the OS image, simply add the attribute after the IFS layout specification. For example:
[virtual=aarch64le,elf +compress] .boot = {

The startup program will handle the decompression. Compressing the image can be useful when optimizing the boot. It reduces the time needed to copy the image but adds the time needed to decompress it. For more information, see the Boot Optimization Guide.

The initialization code and the next program

The inline file in the bootstrap section of the buildfile specifies the initialization code and the path for the next program to run after initialization (usually the OS).

The name for the inline boot file can be anything you choose, but QNX usually uses either .boot or .bootstrap. In this example, the .boot inline file consists of the following:
startup-honeycomb_lx2 -W 

PATH=/proc/boot:/sbin:/bin:/usr/bin:/usr/sbin:/usr/libexec 
LD_LIBRARY_PATH=/proc/boot:/lib:/usr/lib:/lib/dll 
procnto-smp-instr -v
Initialization code
The first line of the .boot inline file (e.g., startup-honeycomb_lx2 -W) specifies the file with the initialization code for the board (startup-*). This startup code is board-specific, so it is usually supplied with the BSP, and the hyphen in the file's name is usually followed by the name of the board on which it runs.
This code is the first code to run after the Inital Program Loader (IPL), U-Boot, or the bootloader (on disk-based x86 systems). It initializes the hardware, system page, and kernel callouts, then loads the next program in the IFS and transfers control to that program. This next program is usually some version of the OS kernel and process manager procnto.
Next program
The next lines of the .boot inline file specify the paths to the standard utilities and the standard libraries and provides these paths to the program to which the startup code will transfer control. In this case, it's procnto-smp-instr, which is the QNX OS kernel and process manager for multi-core processing, with instrumentation.
These lines also instruct procnto-smp-instr to set the _CS_PATH and _CS_LIBPATH configuration strings (see Environment variables), and set the verbosity level.

See the Utilities Reference for more information about procnto, including the options you can specify at startup.

Passing in options at startup

Some bootloaders allow you to pass, into the system image, options presented as command-line input. Most versions of startup that either use the Multiboot protocol or accept a Flattened Device Tree (FDT) in their environment will take advantage of a bootloader that uses these vehicles to pass command-line instructions to the system image. When you pass in options, you don't need to rebuild your IFS if you change the options. The startup reads the options in as though they were entered through the command line, and processes them after the options in the IFS so they can override these other options.

To pass in options:
  • Group them for each exectuable as though you were entering them through the command line.
  • Place the groups in the same order as the executables are listed in the inline file.
  • End each group with a two-hyphen termination marker: --
For example, suppose your buildfile's inline bootstrap file lists startup-*, kdumper and procnto as follows:
[virtual=aarch64le,elf] .bootstrap = {
    startup-armv8_fm -vvv
    kdumper 
    PATH=/proc/boot
    [module=qvm] KWHO=host procnto -vvvv
}
You could then specify options for these executables with a line in the FDT like this:
-P 1 -- -B -I -- -v --
which specifies options for:
  • startup-armv8_fm: the -P sets the maximum number of CPUs to 1 (one).
  • kdumper: the -B and -I options instruct kdumper to write the dump in the 64-bit ELF format in all cases, and to dump all the IFS contents.
  • procnto: the -v option enables one level of verbosity, meaning the kernel provides information that's useful for debugging.

For more information about these options, see the relevant utilities in the QNX OS Utilities Reference.

If an executable requires no options, you still need to add the separator; for example, if you change the above example to pass no options to kdumper, you would change the relevant line to:
-P 1 -- -- -v --

Notice that there is an option termination marker for each executable, even if there are no options specifed for that executable.

Note:

The location where you can place the options to be read in is architecture-, board-, and bootloader-specific, so check you board and bootloader documentation for more information.

Not all boards support this feature. For example, on some x86 boards, the Multiboot boot loader is implemented in a manner that precludes passing in command-line options.

Page updated: