[Previous] [Contents] [Index] [Next]

Controlling How Neutrino Starts

This chapter includes:

What exactly happens when you start up your system depends on the hardware; this chapter gives a general description.


Note: You need to log in as root in order to change any of the files that the system runs when it starts up.

What happens when you boot?

When you boot your system, the CPU is reset, and it executes whatever is at its reset vector. This is usually a BIOS on x86 boxes, but on other platforms it might be a ROM monitor, or it might be a direct jump into some IPL code for that board. After a ROM monitor runs, it generally jumps to the IPL, and a BIOS might do this as well -- or it might jump directly to the start of the OS image.


Startup


Booting a Neutrino system.


The IPL copies the boot image into memory and jumps to the startup. The startup code initializes the hardware, fills the system page with information about the hardware, loads callout routines that the kernel uses for interacting with the hardware, and then loads and starts the microkernel and process manager, procnto. IPL and startup for a board are generally part of a Board Support Package (BSP) for a particular board.

After procnto has completed its initialization, it runs the commands supplied in the boot script, which might start further customization of the runtime environment either through a shell script or through some program written in C, C++, or a combination of the two.

On a non-x86 disk-booted system, that's pretty well how it happens: most customization is done in the boot script or in a shell script that it calls. For more details, see Making an OS Image in Building Embedded Systems.

For an x86 BIOS boot, this becomes more complex:


BIOS startup


Booting a Neutrino system with an x86 BIOS.


After gaining control, the BIOS configures the hardware, and then it scans for BIOS extension signatures (0x55AA). It calls each BIOS extension (e.g. a network card with a boot ROM or hard disk controller) until one of them boots the system. If none of the BIOS extensions boots the system, the BIOS presents some (usually strange) failure message.

For the network boot case, the boot ROM (usually bootp) downloads an image from a server, copies it into memory, then jumps to the start of the image. The boot image generally needs to run a network stack, and starts some sort of network filesystem to retrieve or access additional programs and files.

You can use the mkifs utility to create the OS image. For a sample buildfile for this sort of image, see the Examples appendix.

For a disk-based boot of a Neutrino desktop system, the process of booting, and especially system initialization, is more complex. After the BIOS has chosen to boot from the disk, the primary boot loader (sometimes called the partition loader) is called. This loader is "OS-agnostic;" it can load any OS. The one installed by Neutrino installations displays the message:

Press F1-F4 to select drive or select partition 1,2,3? 1

After a short timeout, it boots whatever OS system is in the partition prompted for. This loader is /boot/sys/ipl-diskpc1. You can write a loader onto a disk by using dloader.

Loading a Neutrino image

When you choose a QNX partition, the secondary boot loader (sometimes called the OS loader) starts. This loader is Neutrino-specific and resides on the QNX partition. It displays the message:

Hit Esc for .altboot

If you let it time out, the loader loads the operating system image file from /.boot; if you press Escape, the loader gets the image from /.altboot instead. As the loader reads the image, it prints a series of periods. If an error occurs, the loader prints one of the following characters, and the boot process halts:

S
No OS signature was found.
D or ?
An error occurred reading the disk.

The only difference between the default installed images is that /.boot uses DMA for accessing the EIDE controller, while /.altboot doesn't.

You can find the buildfiles for these images in /boot/build:

You can't rename, unlink, or delete /.boot and /.altboot, although you can change the contents or copy another file to these files. For example, these commands don't work:

mv /.altboot oldaltboot
mv newboot /.altboot

but these do:

cp /.altboot oldaltboot
cp newboot /.altboot

Note: If you modify your boot image, it's a good idea to copy your working image from /.boot to /.altboot, then put your new image in /.boot. That way, if you make a mistake, you can press Escape when you next boot, and you'll have a working image for recovery.

diskboot

The buildfile for the default .boot image, qnxbasedma.build, includes these lines:

[+script] startup-script = {
    # To save memory make everyone use the libc in the boot image!
    # For speed (less symbolic lookups) we point to libc.so.2 instead
    # of libc.so
    procmgr_symlink ../../proc/boot/libc.so.2 /usr/lib/ldqnx.so.2

    # Default user programs to priority 10, other scheduler (pri=10o)
    # Tell "diskboot" this is a hard disk boot (-b1)
    # Tell "diskboot" to use DMA on IDE drives (-D1)
    # Start 4 text consoles buy passing "-n4" to "devc-con" (-o)
    # By adding "-e" Linux ext2 filesystem will be mounted as well.
    [pri=10o] PATH=/proc/boot diskboot -b1 -D1 -odevc-con,-n4
}

This script starts the system by running diskboot, a program that's used on disk-based systems to boot Neutrino. For the entire qnxbasedma.build file, see the Examples appendix.


Note:
  • You can pass options to diskboot (to control how the system boots) and even to device drivers. In this buildfile, diskboot passes the -n4 option to devc-con to set the number of virtual consoles.
  • You can set up your machine to not use diskboot. For a sample buildfile, see the Examples appendix.

When diskboot starts, it prompts:

Press the space bar to input boot options...

Most of these options are for debugging purposes. The diskboot program looks for a Neutrino partition to mount, then runs a series of script files to initialize the system:


diskboot


Initialization done by diskboot.


The main script for initializing the system is /etc/system/sysinit; you usually keep local system initialization files in the /etc/rc.d directory. For example, if you want to run extra commands at startup on a node, say to mount an NFS drive, you might create a script file named rc.local, make sure it's executable, and put it in the /etc/rc.d directory. For more information, see the description of rc.local later in this chapter.

Here's what diskboot does:

  1. It starts the system logger, slogger. Applications use slogger to log their system messages; you can use sloginfo to view this log.
  2. Next, diskboot runs seedres to read the PnP BIOS and fill procnto's resource database.
  3. Then, diskboot starts pci-bios to support the PCI BIOS.
  4. After that, diskboot starts devb-eide or other disk drivers.
    Note: If you want to pass any options to devb-eide or other drivers, pass them to diskboot in your buildfile.

  5. Next, diskboot looks for filesystems (i.e. partitions and CDs) to mount, which it does by partition type. It recognizes:

    These are mounted as /fs/cdx for CD-ROMs, and /fs/hdx-type-y, where x is a disk number (e.g. /fs/cd0, /fs/hd1), and y is added for uniqueness as it counts upwards. For example, the second DOS partition on hard drive 1 would be /fs/hd1-dos-2.

    By default, one QNX 4 partition is mounted as / instead. This is controlled by looking for a .diskroot file on each QNX 4 partition. If only one such partition has a .diskroot file specifying a mountpoint of /, that partition is unmounted as /fs/hdx-type-y and is then mounted as /; if more than one is found, then diskboot prompts you to select one.

    The .diskroot file is usually empty, but it can contain some commands. For more information, see below.

  6. Optionally, diskboot runs the fat embedded shell, fesh.
  7. Next, diskboot starts the console driver, devc-con.
  8. Finally, diskboot runs the main system-initialization script, /etc/system/sysinit.

.diskroot

The diskboot program uses the .diskroot file to determine which QNX 4 partition to mount as /. The .diskroot file can be one of:

The recognized tokens are:

mount or mountpt
Where to mount this partition. For example:
mount = /home
  
opt or options
Mount options, either specifically for this mountpoint, or generic. For example:
options = ro noexec
  

For more information, see the documentation for mount and specific drivers in the Utilities Reference, and mount() and mount_parse_generic_args() in the Neutrino Library Reference.

desc or description
The diskboot program recognizes and parses these tokens, but it currently ignores the information.
type
The diskboot program recognizes the strings qnx4, ext2, and dos, but currently ignores this token. It determine the type based on partition numbers, as described for diskboot, above.

/etc/system/sysinit

The /etc/system/sysinit file is a script that starts up the main system services. In order to edit this file, you must log in as root.


Note: Before you change the sysinit script, make a backup copy of the latest working version. If you need to create the script, remember to make it executable before you use it (see chmod in the Utilities Reference).

The sysinit script does the following:

  1. It starts slogger, if it isn't yet running.
  2. The script starts the pipe manager, pipe. This manager lets you pass the output from one command as input to another; for more information, see "Redirecting input and output" in Using the Command Line.
  3. Next, sysinit starts mqueue, which manages message queues and named semaphores.
  4. If this is the first time you've rebooted after installing the OS, sysinit runs /etc/rc.d/rc.setup-once, which creates various directories and swap files.
  5. Next, sysinit sets the _CS_TIMEZONE configuration string to the value stored in /etc/TIMEZONE. If this file doesn't exist, sysinit sets the time zone to be UTC, or Coordinated Universal Time (formerly Greenwich Mean Time). For more information, see "Setting the time zone" in Configuring Your Environment.
  6. If /etc/rc.d/rc.rtc exists and is executable, sysinit runs it to set up the realtime clock.

    We recommend that you set the hardware clock to UTC time and use the _CS_TIMEZONE configuration string or the TZ environment variable to specify your time zone. The system displays and interprets local times and automatically determines when daylight saving time starts and ends.

    This means that you can have dial-up users in different time zones on the same computer, and they can all see the correct current local time. It also helps when transmitting data from time zone to time zone. You stamp the data with the UTC time stamp, and all of the computers involved should have an easy time comparing time stamps in one time zone to time stamps in another.

    Some operating systems, such as Windows, set the hardware clock to local time. If you install Windows and Neutrino on the same machine, you should set the hardware clock to local time by executing the following command as root and putting it into /etc/rc.d/rc.rtc:

    rtc -l hw
      

    If you're using Photon, you can just uncheck The hardware clock uses UTC/GMT in phlocale; if you do that, the program creates a rc.rtc file for you that contains the above command.

  7. After setting up the clock, sysinit sets the HOSTNAME environment variable to be the name of the host system. It gets this name from the hostname command, or from /etc/HOSTNAME if that doesn't succeed.
    Note: A hostname can consist only of letters, numbers, and hyphens, and must not start or end with a hyphen. For more information, see RFC 952.

  8. Then, sysinit runs /etc/rc.d/rc.devices to enumerate your system's devices (see "Device enumeration," below). This starts io-net as well as various other drivers, depending on the hardware detected.
  9. If /etc/system/config/useqnet exists and io-net is running, sysinit initializes Neutrino native networking (see the Using Qnet for Transparent Distributed Processing chapter in this guide, and npm-qnet.so in the Utilities Reference).
  10. Next, sysinit runs the system-initialization script, /etc/rc.d/rc.sysinit (see below).
  11. If that fails, sysinit tries to become a sh or, if that fails, a fesh, so that you at least have a shell if all else fails.

Device enumeration

Neutrino uses a device enumerator manager process, enum-devices, to detect all known hardware devices on the system and to start the appropriate drivers. It's called by the /etc/rc.d/rc.devices script, which /etc/system/sysinit invokes.

The enum-devices manager uses a series of configuration files to specify actions to take when the system detects specific hardware devices. After it reads the configuration file(s), enum-devices queries its various enumerators to discover what devices are on the system. It then matches these devices against the device IDs listed in the configuration files. If the device matches, the action clauses associated with the device are executed. You can find the enumerator configuration files in the /etc/system/enum directory.

Here's some sample code from a configuration file:

device(pci, ven=2222, dev=1111)
    uniq(sernum, devc-ser, 1)
    driver(devc-ser8250,  "-u$(sernum) $(ioport1),$(irq)" )

This code directs the enumerator to do the following when it detects device 1111 from vender 2222:

  1. Set sernum to the next unique serial device number, starting at 1.
  2. Start the devc-ser8250 driver with the provided options (the device enumerator sets the ioport and irq variables).

To detect new hardware, you can extend the enumerator configuration files in the following ways:

The enumerator reads and concatenates the contents of all configuration files under the chosen directory before it starts processing.

For details on the different command-line options and a description of the syntax for the configuration files, see enum-devices in the Utilities Reference.

/etc/rc.d/rc.sysinit

The /etc/system/sysinit script runs /etc/rc.d/rc.sysinit to do local initialization of your system.


rc.sysinit


Initialization done by /etc/rc.d/rc.sysinit.


The rc.sysinit script does the following:

  1. It starts a secure random-number generator, random, to provide random numbers for use in encryption and so on.
  2. If the /var/dumps directory exists, rc.sysinit starts the dumper utility to capture (in /var/dumps) dumps of processes that terminate abnormally.
  3. If /etc/host_cfg/$HOSTNAME/rc.d/rc.local exists and is executable, rc.sysinit runs it. Otherwise, if /etc/rc.d/rc.local exists and is executable, rc.sysinit runs it. There isn't a default version of this file; you must create it if you want to use it. For more information, see "rc.local," below.
  4. Finally, rc.sysinit runs tinit. By default, the system starts Photon, but if you create a file called /etc/system/config/nophoton, then rc.sysinit tells tinit to use text mode. For more information, see "tinit," below.

rc.local

As described above, rc.sysinit runs /etc/host_cfg/$HOSTNAME/rc.d/rc.local or /etc/rc.d/rc.local, if the file exists and is executable.

You can use the rc.local file to customize your startup by:

For example, you can:

Don't use the rc.local file to to set up environment variables, because there's another shell that starts after this script is run, so any environment variable that you set in this file disappears by the time you get a chance to log in.


Note: After you've created rc.local, make sure that you set the executable bit on the file with the command:
chmod +x rc.local

tinit

The tinit program initializes the terminal, as follows:

  1. If the -p option is specified, tinit starts Photon.
  2. Otherwise, tinit looks at /etc/config/ttys and runs login or shells, based on the contents of the file.

Troubleshooting

Here are some problems you might encounter while customizing how your system starts up:

The applications I put in rc.local don't run.
Check the following:

[Previous] [Contents] [Index] [Next]