Transferring an OS image to an x86_64 target platform

Updated: October 26, 2022

A QNX system can be self-contained in a single boot file—the IFS. You can boot the IFS on x86_64 target platforms using standard disk boot methods.

However, you may want to create a Power-Safe filesystem on the target. The following requirements are examples of when this type of filesystem is required:
  • You require a persistent, writable file system (the IFS is read-only).
  • You want to decrease the size of the IFS for a faster boot time.
  • You want to make it easier to add executables and libraries to the target without rebuilding an IFS.
The Power-Safe filesystem resides on a storage device on the target (e.g., a hard drive, SSD drive, MMC chip, or NVMe chip). The file system can also be made bootable, which means that after it's placed on the storage device, a separate boot medium (e.g., a USB stick) is not longer needed.

BIOS systems

  1. Create the IFS. Every BSP comes with an example buildfile that creates a simple IFS.

    For example, run the following command from the BSP images directory to create the IFS x86_64-generic.bin using the buildfile x86_64-generic.build. It specifies the file extension .bin, but you can use any value (for example, there are BSPs that use .ifs and .raw).

    mkifs -r../install -vv x86_64-generic.build x86_64-generic.bin

    Alternatively, in the IDE, create the IFS using the right-click menu for the BSP project.

  2. Create the Power-Safe filesystem (QNX Neutrino) image as shown in following example buildfile (named bios_root.build).
    # Set the size of the filesystem image in disk sectors (not filesystem blocks)
    # The size must be a multiple of 8 and can be any value that can fit on the media
    # For this example, the media is 400 MB
    [num_sectors=409600]
    
    # In QNX Neutrino 6, inodes have to be pre-allocated at format time
    [num_inodes=50000]
    
    # The blocksize is typically set based on how the filesystem is expected to be used
    # If the filesystem will contain many very small files, reduce the specified blksize,
    # because each file occupies a whole number of blocks. Default to 4KiB as that size
    # ensures everything is 4KiB aligned and may work better with some solid-state
    # devices.
    [blksize=4096]
    
    # Include the boot IFS in the image, in /.boot
    # In this example, x86_64-generic.bin is the image that you
    # build from the BSP and primary_boot.ifs is its name in the image
    # You can choose any name for the boot IFS in /.boot, as long as it is the only file
    /.boot/primary_boot_image.bin=x86_64-generic.bin
    
    # Optionally, include any other files you want in the filesystem image
    /usr/bin/traceprinter=${QNX_TARGET}/x86_64/usr/bin/traceprinter
    /usr/bin/awk=${QNX_TARGET}/x86_64/usr/bin/awk
    
    # Optionally, include a complete directory without specifying individual file names
    # For example, include all files for screen graphics
    /usr/lib/graphics/intel-drm=${QNX_TARGET}/x86_64/usr/lib/graphics/intel-drm
    The following example command uses this buildfile to create the bios_root.img file, which contains the filesystem:
    mkqnx6fsimg -vv bios_root.build bios_root.img
    The output bios_root.img file is num_sectors long (819200 * 512 bytes) and contains the following items:
    • boot IFS as /.boot/primary_boot_image.bin
    • two files in /usr/bin
    • an entire tree from the SDP as /usr/lib/graphics/intel-drm
  3. Use diskimage to prepend the filesystem with a partition table and primary bootstrap and adjust the secondary bootloader to match the image. The following example illustrates a diskimage configuration file (bios_disk.cfg):
    # Set the disk CHS geometry. The following values should work on all
    # HDDs and sets the cylinder size to 1 MiB
    # Although the usual value for sectors_per_trk is 63, here is it
    # set to 32 to allow for a convenient cylinder size of 1 MiB
    [heads=64]
    [sectors_per_track=32]
    [sector_size=512]
    
    # The lines above create a 1 MiB cylinder size and the following line
    # sets the corresponding total disk image size to 400 MiB.  Adjust as necessary
    [cylinders=400]
    
    # List the partitions and provide the image files to use. diskimage
    # re-sizes the partition automatically to fit the image file, if one is provided
    
    # Specify the partition information using the MBR format
    [partition=1 type=177 boot=true] "bios_root.img"
    The following example commands create the fully bootable HDD image bios_disk.img that specifies the partition images that appear in the disk image.

    For Windows hosts, you must run sh to get a prompt (for example, sh-4.3$) before you run the command.

    diskimage -o bios_disk.img -c bios_disk.cfg 
              -b $QNX_TARGET/x86_64/boot/sys/ipl-diskpc1-nomsg
              -s 131072
    Where:
    • The -b option specifies the primary loader (IPL1), but you can specify ipl-diskpc1 instead.
    • The -s specifies the buffer size to use. Specifying a value like the one in the example can shorten the amount of time it takes to make the image.

    The output file bios_disk.img is somewhat larger than the bios_root.img file specified in diskimage configuration file (bios_disk.cfg).

  4. Transfer the image to the disk on your target. For example:
    • Attach the target device to your host system and copy the file using the dd utility (Linux and macOS), or RawWrite or Win32DiskImager (Windows).
    • If you can place the bootable image (for example, bios_disk.img) on a CD or USB stick, use it to boot the target, and then transfer the image to the primary HDD or other boot media. You could also use a network-based method to transfer the image.

UEFI systems

UEFI implementations differ from board to board. The following procedure illustrates transferring an OS image to an ASRock Beebox. (Because the Beebox does not provide a serial connection, to access the console, you need to use adapters to create USB-to-serial connections.)

  1. Create the IFS. Every BSP comes with an example buildfile that creates a simple IFS.

    For example, run the following command from the BSP images directory to create the IFS x86_64-uefi.efi using the buildfile x86_64-uefi.build. It specifies the file extension .efi, but you can use any value (for example, there are BSPs that use .ifs, .raw, and .bin).

    mkifs -r../install -vv x86_64-uefi.build x86_64-uefi.efi

    Alternatively, in the IDE, create the IFS using the right-click menu for the BSP project.

  2. Create the Power-Safe filesystem (QNX Neutrino) image as shown in following example buildfile (named uefi_root.build).
    # Set the size of the filesystem image in disk sectors (not filesystem blocks)
    # The size must be a multiple of 8 and can be any value that can fit on the media
    # For this example, the media is 400 MB
    [num_sectors=409600]
    
    # In QNX Neutrino 6, inodes have to be pre-allocated at format time
    [num_inodes=50000]
    
    # The blocksize is typically set based on how the filesystem is expected to be used
    # If the filesystem will contain many very small files, reduce the specified blksize,
    # because each file occupies a whole number of blocks. Default to 4KiB as that size
    # ensures everything is 4KiB aligned and may work better with some solid-state
    # devices.
    [blksize=4096]
    
    # Optionally, include any other files you want in the filesystem image
    /usr/bin/traceprinter=${QNX_TARGET}/x86_64/usr/bin/traceprinter
    /usr/bin/awk=${QNX_TARGET}/x86_64/usr/bin/awk
    
    # Optionally, include a complete directory without specifying individual file names
    # For example, include all files for screen graphics
    /usr/lib/graphics/intel-drm=${QNX_TARGET}/x86_64/usr/lib/graphics/intel-drm
    The following example command uses this buildfile to create the uefi_root.img file, which contains the filesystem:
    mkqnx6fsimg -vv uefi_root.build uefi_root.img
    The output uefi_root.img file is num_sectors long (819200 * 512 bytes) and contains the following items:
    • two files in /usr/bin
    • an entire tree from the SDP as /usr/lib/graphics/intel-drm
  3. Generate the UEFI boot partition. In the following example buildfile uefi_boot.build, the boot image name is the one used for Intel Gordon Ridge MRB. For the name used by your board, see its BSP documentation.
    #The EFI boot partition only needs to be large enough to hold the IFS
    [num_sectors=51200]
    
    #Create the boot image with the name required by your board's firmware
    EFI/BOOT/BOOTX64.EFI=x86_64-uefi.efi
  4. Create a FAT partition (FAT12, FAT16 or FAT32). For example:
    mkfatfsimg -vv uefi_boot.build uefi_boot.img
  5. Use diskimage to prepend the filesystem with a partition table and primary bootstrap. For UEFI, the partition table is GPT, but in most cases it could also be MBR.

    The following example illustrates a diskimage configuration file (uefi_disk.cfg):

    # Set the disk CHS geometry. The values below should work on all
    # HDDs and sets the cylinder size to 1 MiB
    # Although the usual value for sectors_per_trk is 63, here is it
    # set to 32 to allow for a convenient cylinder size of 1 MiB
    [heads=64]
    [sectors_per_track=32]
    [sector_size=512]
    
    # The lines above create a 1 MiB cylinder size and the following line
    # sets the corresponding total disk image size to 400 MiB.  Adjust as necessary
    [cylinders=400]
    
    # Generate a GPT with the required "UEFI System Partition"
    [partition=1 type_guid={C12A7328-F81F-11D2-BA4B-00A0C93EC93B} name="boot" boot=true] "uefi_boot.img"
    [partition=2 type_guid="qnx6"] "uefi_root.img"

    The string C12A7328-F81F-11D2-BA4B-00A0C93EC93B in this example is the full GUID for an EFI system partition; you could use the short identifier efi instead. For information about GUIDs for partition types, see <gpt_guid.h> or the entry for the diskimage configuration file in the Utilities Reference.

    The following example commands create the fully bootable HDD image uefi_disk.img that specifies the partition images that appear in the disk image.

    For Windows hosts, you must run sh to get a prompt (for example, sh-4.3$) before you run the command.

    diskimage -g -o uefi_disk.img -c uefi_disk.cfg

    The output file uefi_disk.img is somewhat larger than the uefi_root.img file specified in diskimage configuration file (uefi_disk.cfg).

  6. Transfer the image to the disk on your target. For example:
    • Attach the target device to your host system and copy the file using the dd utility (Linux and macOS), or RawWrite or Win32DiskImager (Windows).
    • If you can place the bootable image (for example, uefi_disk.img) on a CD or USB stick, use it to boot the target, and then transfer the image to the primary HDD or other boot media. You could also use a network-based method to transfer the image.