Skip to content

[next] Add measured boot support to NILRT x64#1018

Open
amstewart wants to merge 23 commits into
ni:nilrt/master/nextfrom
amstewart:feat/next/device-encryption-nisystemformat
Open

[next] Add measured boot support to NILRT x64#1018
amstewart wants to merge 23 commits into
ni:nilrt/master/nextfrom
amstewart:feat/next/device-encryption-nisystemformat

Conversation

@amstewart

@amstewart amstewart commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Summary of Changes

  • Adds TPM tooling to all the NILRT base images, so that all images can handle locking/unlocking LUKS partitions.
  • Adds an initramfs for runmode, which is necessary to provide an unencrypted rootfs that understands how to locate, unlock, and switch_root into the real (encrypted rootfs).
  • Refactors the ni-systemformat recipe implementation to be more modular and (I hope) comprehensible in the long-term.
  • Adds a -e option to the nisystemformat -f (format) operation. When expressed, it will encrypt the rootfs with LUKS and bind the decryption key to the TPM PCR 7.
  • Generally simplifies and cleans up nisystemformat. Squashes the usage information down to a single concept - rather than keeping separate workflows for safemode and runmode.
  • This PR also rebases a couple conflicting commits that were commited to the scarthgap branch, but not master.
  • Bumped nisystemformat to version 2.0.0, since there have been many changes.

Limitations

  • Only encrypts the rootfs partition at this time (the configfs requires special handling which will come later.)
  • Only uses PCR 7 (secure boot) to bind the LUKS key (using other PCRs will come later.)
  • Does not handle kernel upgrades (later user story).

Justification

AB#3737965
AB#3752796
AB#3752799

Testing

TODO: Detail what testing has been done to ensure this submission meets requirements.

  • I have built the core package feed with this PR in place. (bitbake packagefeed-ni-core)
  • Hand-tested the BSI installation workflow with/without the nisystemformat -e option and validated that the runmode initramfs unlocks and boots into the encrypted rootfs (when it is encrypted).

Runmode bootlog

...
[    1.082824] Run /init as init process
[    1.082824]   with arguments:
[    1.082824]     /init
[    1.082825]   with environment:
[    1.082825]     HOME=/
[    1.082825]     TERM=linux
[    1.082825]     sys_reset=false
[    1.091939] (initramfs) INFO: /init
[    1.092028] (initramfs) INFO: Setting up root filesystem...
[    1.092064] (initramfs) DEBUG: Running /etc/init.d/ni-cryptdisks.sh start...
Opening LUKS partition /dev/sda4 as nirootfs
[    4.611374] random: crng init done
[    7.190142] (initramfs) DEBUG: Looking for nirootfs partition...
[    7.436621] (initramfs) DEBUG: Found nirootfs at /dev/mapper/nirootfs
[    7.481537] EXT4-fs (dm-0): mounted filesystem c285d0c0-c8e4-4a8f-bb54-f41c34db7ccb r/w with ordered data mode. Quota mode: none.
[    7.481753] (initramfs) DEBUG: Bind mounting virtual filesystems...
[    7.484319] (initramfs) DEBUG: Setting up /run in new root...
[    7.485579] (initramfs) INFO: Switching to root filesystem...
INIT: version 3.14 booting
[    8.132553] EXT4-fs (sda2): mounted filesystem 5f4fc05e-96ae-4948-81b7-0606d648d44a r/w with ordered data mode. Quota mode: none.
[    8.138720] EXT4-fs (sda3): mounted filesystem df67fb4f-a16d-40c2-93d3-1f2d4d19904a r/w with ordered data mode. Quota mode: none.
Starting udev
...

Runmode partition layout

admin@NI-cRIO-903x-VM-1934c4ab:~# lsblk -f
NAME      FSTYPE     FSVER LABEL         UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
sda                                                                                          
|-sda1    vfat             nigrub        0B5F-320A                                           
|-sda2    ext4             nibootfs      5f4fc05e-96ae-4948-81b7-0606d648d44a   72.7M    47% /boot
|                                                                                            /boot
|-sda3    ext4             niconfig      df67fb4f-a16d-40c2-93d3-1f2d4d19904a   11.7M     1% /etc/natinst/share
|                                                                                            /etc/natinst/share
`-sda4    crypto_LUK       nirootfs-luks de0edf06-2066-4734-960f-e63073d66e06                
  `-nirootfs
          ext4             nirootfs      c285d0c0-c8e4-4a8f-bb54-f41c34db7ccb    1.9G    44% /
sr0    

Procedure

Alex Stewart and others added 23 commits June 8, 2026 13:07
Add TPM utilities to all NILRT images via the ni-base packagegroup, and
re-add the security-tpm2 packagegroup from OE upstream to the ni-tpm
packagegroup.

We cannot use the whole ni-tpm packagegroup in -base because
pkggrp-security-tpm2 depends upon python3, which is only installed in
the runmode image.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
The new runmode initramfs needs an init system (PID 1). Build it into
the core feed so that it is represented in our SBOMs and packaging
infrastructure. But do not add it to a packagegroup so that it doesn't
get accidentally installed by a user with something else.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
* Add section headers to script for clarity.
* Re-order some constants for clarity.

No functional changes intended.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
Rename the 'arch' variable 'ARCH' to be more consistent with other
variables that are not populated by the user.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
Udev will populate the /dev/disks/* directories with symlinks to devices
based on their properties - including label. Using this tree to find the
`nirootfs` partition is more straightforward that using `lsblk`
comprehension and also works when `nirootfs` is a device-mapped
partition via LUKS or LVM.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
* Move the source files into a named directory, to prepare for expanding
  their structure.
* Reorder the recipe file to comply with the layer styleguide.
* Add recipe headers for clarity.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
The recipe RDEPENDS are split between assignments for no apparent
reason, combine them for clarity.

The main package FILES variable assigns standard file paths for no
apparent reason, remove the duplicate entries for clarity.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
Add a minimal Makefile implementation to nisystemformat, so that it is
easier to build and test changes on real targets.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
Some of the nisystemformat usage text contains options which are not
actually parsed or used. Remove them for correctness and clarity.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
The ``nisystemformat`` main script is very large and difficult to
follow. Break out its functionality into supporting shell libraries,
which are sourced by the main file.

Also revitalize the main (safemode) usage information in preparation for
future extension.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
The nisystemformat usage and command validation code has accumulated
technical cruft from the aborted RAUC implementation. And it present
three different usage documentations, depending on which mode you are
booted into - even though the actual code is the same behind the docs.

* For clarity, collapse the three usage texts into one, more manageable
  document.
* Move the ``set_mode`` function to usage.sh, where it is primarily
  used.
* Fix some incorrect validation text about a non-existent "-v" option.
* Move the non-RAUC filesystem type validation out into the main
  nisystemformat script for now - since that is where the
``supported_fstypes`` information is.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
The aborted RAUC content is cluttering up the nisystemformat script.
Remove it for clarity.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
Move the netconfig-related content into its own library, for clarity.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
The EXITCODES variable is declared read-only, which means that bash will
throw a warning if a script tries to import it twice, including through
another import. We could defend against that case by checking if it has
already been declared and then skipping redefinition. But it might be
reasonable to change/overwrite the EXITCODES during script execution (if
the script changes personality). So instead, just make it mutable.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
Break out the nisystemfromat 'format' command functions into their own
library, for clarity.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
Adjust the format.sh functions to make them a little more readable. Use
a trap to handle service restarts to ensure that we always attempt it in
case of a failure.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
Add a `-e` optiont to the `nisystemformat` script. When expressed, it
will attempt to encrypt the rootfs partition with LUKS and seal an
unlocking key to the current TPM state using the `ni-reseal-luks` tool.
Update the bb recipe file to accomodate the changes that have gone into
the source layout.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
The anonymous python function which set the INITRAMFS_FSTYPES was
removed. Set it explicitly to ensure that we get a cpio initramfs
archive which can be included in the runmode BSI.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
Some ARM targets use ext4 instead of ubifs.
So port ext4 changes from nilrt_os_common.

Signed-off-by: Chaitanya Vadrevu <chaitanya.vadrevu@emerson.com>
(cherry picked from commit bf67c4b)

Rebased to nilrt/master/next by moving Artemis logc into the format.sh
library file.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
Signed-off-by: Jeffrey Pautler <jeffrey.pautler@ni.com>
(cherry picked from commit 0b8e89b)

Rebased to nilrt/master/next by moving code into the various lib/ files
where it belongs. Since the master/next version of ni-systemformat
already uses EXIT codes 8 and 9, bumped the INSUFFICIENT_PRIVILEGES code
to 10.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
There have been several substantial changes to the ni-systemformat
scripting. Some of them, like the new EUID==0 check, could break
backwards compatibility in the public API. So bump the version to 2.0.0
to signal those changes.

Signed-off-by: Alex Stewart <alex.stewart@emerson.com>
@amstewart amstewart requested review from chaitu236 and jpautler June 8, 2026 21:12
@amstewart amstewart marked this pull request as ready for review June 8, 2026 21:13
Copilot AI review requested due to automatic review settings June 8, 2026 21:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces measured-boot-related plumbing for NILRT x64 by adding TPM/LUKS tooling to base images and refactoring nisystemformat into a modular implementation that can optionally LUKS-encrypt the rootfs and bind unlock to the TPM (PCR 7). It also adds/adjusts initramfs packaging to support unlocking and switching into an encrypted root filesystem at boot.

Changes:

  • Refactor nisystemformat into a main CLI plus library modules (usage, formatting, netconfig, encryption, exit codes).
  • Add -e encryption option to nisystemformat -f and wire in TPM/LUKS tooling.
  • Update Yocto packaging/packagegroups and init scripts to include TPM tools and generate targetinfo.ini.

Reviewed changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
recipes-ni/ni-systemformat/ni-systemformat/src/nisystemformat New modular top-level nisystemformat entrypoint wiring together library modules.
recipes-ni/ni-systemformat/ni-systemformat/src/lib/util.sh Common utilities (logging, retry, tempfiles, error handling).
recipes-ni/ni-systemformat/ni-systemformat/src/lib/usage.sh CLI parsing + usage/help text and argument validation.
recipes-ni/ni-systemformat/ni-systemformat/src/lib/netconfig.sh Network config save/restore around formatting.
recipes-ni/ni-systemformat/ni-systemformat/src/lib/format.sh Core formatting logic, service stop/start, and LUKS conversion hooks.
recipes-ni/ni-systemformat/ni-systemformat/src/lib/exit_codes.sh Centralized exit code mapping.
recipes-ni/ni-systemformat/ni-systemformat/src/lib/encryption.sh TPM presence checks for encryption mode.
recipes-ni/ni-systemformat/ni-systemformat/Makefile Build/install logic for the new modular layout.
recipes-ni/ni-systemformat/ni-systemformat/init/nitargetinfo Init script to cache targetinfo.ini from nisystemformat.
recipes-ni/ni-systemformat/ni-systemformat.bb Recipe refactor: new sources, version bump, deps, init script install.
recipes-ni/ni-systemformat/files/nisystemformat Removes legacy monolithic script (replaced by modular implementation).
recipes-core/packagegroups/packagegroup-ni-tpm.bb Adds additional TPM2 packagegroup dependency.
recipes-core/packagegroups/packagegroup-ni-base.bb Adjust x64 base image TPM/LUKS tooling dependencies.
recipes-core/packagegroups/packagefeed-ni-core.bb Adds initramfs dependency for x64 feed (currently duplicated).
recipes-core/images/nilrt-runmode-initramfs.bb Adjust initramfs output types configuration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

mountfs=ext4
fi

if [ "$ARCH" = "x86_64" ] || [ "$mountfs" = "ext4" ]; then

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.

function supported_fstypes()
{
if [ "$ARCH" = "armv7l" ]; then
if [ "$mountfs" = "ext4" ]; then # Adding $mountfs condition to properly report fstype for Artemis

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.

Comment on lines +100 to +124
log INFO "Encrypting $configfs_dev with LUKS..."
_convert_to_luks "$configfs_dev" "$NICONFIG_PARTLABEL" \
|| die UNKNOWN_ERROR "Failed to convert configfs partition to LUKS."
log INFO "DONE"
configfs_dev="$CONFIGFS_DEV" # update configfs_dev to point to the new mapper device
else
if cryptsetup isLuks "$configfs_dev" 2>/dev/null; then
log INFO "Converting $configfs_dev back to non-LUKS."
cryptsetup erase -q "${configfs_dev}"
fi
fi

# fstype is validated before calling format_config
case "$1" in
ubifs)
local partition_label="boot-config"
local volume_number="3"
local volume_label="config"
format_ubi_volume "$partition_label" "$volume_number" "$volume_label"
;;
ext4)
local volume_label="niconfig"
local options=""
mkfs.ext4 -q -F -I 256 -L $volume_label $options ${2:-$CONFIGFS_DEV}
;;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.

Comment on lines +339 to +341
if ! /etc/init.d/sshd stop; then
/etc/init.d/sshd status && [ $? -eq 3 ]
fi

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.

die_with_usage INVALID_ARGUMENT "No command-line arguments specified."
fi

while getopts "4cefhln:orst:" option

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-4 and -o were never really implemented. I had left them in because I didn't want to break backwards compatibility, but any code calling them will error in this version anyway. And we're bumping the ni-systemformat version to 2.0.0 anyway. So I'll just remove them.

Comment on lines +98 to +111
function with_retry() {
local cmd="$@" # command to execute (with args)
for attemptItr in `seq 1 "$COMMAND_RETRY_COUNT"`; do
if eval "$cmd"; then
return 0
fi

echo "$* failed with $? (attempt $attemptItr)" >&2
sleep "$COMMAND_RETRY_SLEEP"
done

echo "ERROR: $* failed ($COMMAND_RETRY_COUNT attempts)" >&2
return 1
}
Comment on lines +352 to +354
# Print the supported filesystem types for this system.
# The output is a comma-separated list of filesystem types,
# with no trailing comma.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.

Comment on lines +49 to +53
# Image-specific packages kept separately so they are not accidentally
# installed via a packagegroup dependency into the wrong image.
RDEPENDS:${PN}:append:x64 = "\
init-nilrt-runmode-initramfs \
"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.

Comment on lines 66 to +75
RDEPENDS:${PN} += "\
bash \
niacctbase \
"
# nisystemformat rdeps
RDEPENDS:${PN} += "\
coreutils \
e2fsprogs-mke2fs \
pkgconfig \
ni-netcfgutil \
niacctbase \
util-linux-lsblk \
util-linux-logger \
"
# legacy symlink location
install -d ${D}/usr/local/natinst/bin
ln -sf ${bindir}/nisystemformat ${D}/usr/local/natinst/bin/nisystemformat
# The nisystemformat binary can ban executed by anyone in the 'ni' group.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants