Create a Custom Machine
A Yocto machine describes the hardware targeted by a build. In meta-tegra, a machine selects the Jetson module and carrier-board assumptions, storage configuration, kernel device tree, NVIDIA flashing configuration, and other hardware-specific defaults.
Product-specific machine files belong in the product layer. They should not be added directly to meta-tegra. Keeping the machine in meta-myproduct lets us update the BSP independently and version the board configuration with the product.
Prerequisites
Before continuing, complete Create a Custom Layer. The BitBake environment must be loaded and meta-myproduct must be enabled in bblayers.conf.
This guide creates myproduct-agx-orin from the existing jetson-agx-orin-devkit machine. The custom machine name must be no more than 31 characters.
What you will have by the end of this Wiki
We will create a basic custom machine that inherits the complete AGX Orin development-kit configuration:
meta-myproduct/
├── conf/
│ ├── layer.conf
│ └── machine/
│ └── myproduct-agx-orin.conf
└── recipes-core/
└── images/
└── myproduct-image.bb
For this practical example, we will not change the device tree, pinmux, or flashing files. The custom machine will behave like the existing AGX Orin development-kit machine so that we can build it and validate it on the same hardware.
1. Inspect the available machines
Before creating a machine, inspect the definitions provided by the selected meta-tegra branch:
find \
"$YOCTO_WORKSPACE/bitbake-builds/meta-tegra-wrynose/layers/meta-tegra/conf/machine" \
-maxdepth 1 -type f -name '*.conf' -printf '%f\n' | sort
Reference output for Wrynose:
jetson-agx-orin-devkit-industrial.conf jetson-agx-orin-devkit.conf jetson-agx-thor-devkit.conf jetson-agx-thor-t4000.conf jetson-orin-nano-devkit-nvme.conf jetson-orin-nano-devkit.conf p3509-a02-p3767-0000.conf p3737-0000-p3701-0004.conf p3737-0000-p3701-0005.conf p3768-0000-p3767-0000.conf p3768-0000-p3767-0001.conf p3768-0000-p3767-0003.conf p3768-0000-p3767-0004.conf
The descriptive names identify supported NVIDIA development kits. Names such as p3737-0000-p3701-0005 identify a specific carrier-board and Jetson-module combination using NVIDIA part numbers.
You can also inspect the reusable include files:
find \
"$YOCTO_WORKSPACE/bitbake-builds/meta-tegra-wrynose/layers/meta-tegra/conf/machine/include" \
-maxdepth 1 -type f -name '*.inc' -printf '%f\n' | sort
Reference output for Wrynose:
agx-orin.inc agx-thor-t4000.inc agx-thor-t5000.inc orin-nano.inc orin-nx.inc p3737.inc p3768.inc p4071.inc tegra-common.inc tegra234.inc tegra264.inc
Files such as agx-orin.inc, orin-nx.inc, and orin-nano.inc contain common settings for a module family. Carrier includes such as p3737.inc and p3768.inc contain carrier-specific settings.
2. Choose the closest base configuration
The custom machine should reuse the configuration that most closely matches the real hardware. Consider:
- The Jetson module used by the product.
- The carrier board and its peripherals.
- The root filesystem storage device, such as SD card, eMMC, or NVMe.
There are two common approaches:
- Include a complete machine configuration. This is usually the best starting point when the hardware is the same as, or very close to, an NVIDIA development kit. It reuses the module, carrier, storage, flashing, and package assumptions already provided by
meta-tegra. - Include a module-family file. This is useful when the product uses a supported Jetson module on a custom carrier board. The custom machine must then provide the carrier-specific differences.
For this guide, we will use the first approach and inherit:
jetson-agx-orin-devkit.conf
This machine describes the standard AGX Orin development kit, including its P3701 module and P3737 carrier-board configuration. Using it as our base gives us a known hardware target for validating the custom machine before introducing product-specific changes.
3. Create the machine file
Create the machine directory in the custom layer:
mkdir -p "$YOCTO_WORKSPACE/meta-myproduct/conf/machine"
Create the following file:
$YOCTO_WORKSPACE/meta-myproduct/conf/machine/myproduct-agx-orin.conf
Add this content:
#@TYPE: Machine #@NAME: MyProduct AGX Orin #@DESCRIPTION: MyProduct machine based on the NVIDIA AGX Orin devkit require conf/machine/jetson-agx-orin-devkit.conf
The require statement imports the complete development-kit machine. This means our first custom machine uses the same module, carrier, storage, and flashing defaults.
This is the only machine implementation used in this guide. It gives us a known baseline that we can validate on an AGX Orin development kit before adding product-specific hardware changes.
4. Select the custom machine
Edit the generated build/conf/local.conf and replace the previous MACHINE value with:
MACHINE = "myproduct-agx-orin"
The value is the machine file name without the .conf extension.
5. Where hardware customizations belong
As the product moves away from the development-kit hardware, the custom machine file is the correct place to select the product's hardware configuration. Common examples include:
KERNEL_DEVICETREE TEGRA_FLASHVAR_PINMUX_CONFIG TEGRA_FLASHVAR_PMC_CONFIG TEGRA_FLASHVAR_PMIC_CONFIG TEGRA_FLASHVAR_MB2BCT_CFG TEGRA_FLASHVAR_BPFDTB_FILE EMC_BCT PARTITION_LAYOUT_TEMPLATE_DEFAULT PARTITION_LAYOUT_EXTERNAL_DEFAULT
For example, a future custom machine might select a product-specific device tree and pinmux with assignments like:
KERNEL_DEVICETREE = "tegra234-myproduct.dtb" TEGRA_FLASHVAR_PINMUX_CONFIG = "tegra234-myproduct-pinmux.dtsi" TEGRA_FLASHVAR_PMC_CONFIG = "tegra234-myproduct-padvoltage.dtsi"
Place these assignments after the require statement. Use = to replace inherited values; ?= only assigns a value when the variable has not already been set.
TEGRA_FLASHVARS is the list of flash-variable keys recognized by meta-tegra. Individual values use the TEGRA_FLASHVAR_<KEY> naming pattern. These settings select the NVIDIA files used for flashing and boot firmware.
This guide does not attempt to explain every device-tree, pinmux, BCT, or flash variable, or how to generate the corresponding NVIDIA files. The important point is that the custom machine is where the product selects those files and overrides inherited hardware defaults. The files themselves must be provided by recipes or .bbappend files in the product layer.
For our basic example, we do not add any of these assignments. We keep all values inherited from jetson-agx-orin-devkit.
6. Verify the custom machine
Before running these commands, load the BitBake environment as described in Create a Custom Layer — Initialize the build setup.
Confirm that both layers are active
bitbake-layers show-layers
The output must include the tegra and myproduct collections.
Parse the metadata
bitbake --parse-only
This detects missing includes, invalid syntax, incompatible layers, and other metadata errors before starting a full build.
Inspect the effective configuration
bitbake-getvar MACHINE bitbake-getvar KERNEL_DEVICETREE bitbake-getvar TNSPEC_BOOTDEV bitbake-getvar PARTITION_LAYOUT_TEMPLATE_DEFAULT
For this example, verify that:
MACHINEismyproduct-agx-orin;KERNEL_DEVICETREEresolves totegra234-p3737-0000+p3701-0000-nv.dtb;TNSPEC_BOOTDEVresolves tommcblk0p1;- the partition layout resolves to
flash_t234_qspi_sdmmc.xml.
These values confirm that the custom machine inherited the intended AGX Orin development-kit configuration.
Build the image
If myproduct-image was created in the previous guide, build it with:
bitbake myproduct-image
Otherwise, use a minimal OpenEmbedded Core image:
bitbake core-image-minimal
The expected output directory is:
$YOCTO_WORKSPACE/bitbake-builds/meta-tegra-wrynose/build/tmp/deploy/images/myproduct-agx-orin/
The flashing package should have a name similar to:
myproduct-image-myproduct-agx-orin.rootfs.tegraflash-tar.zst
A successful build confirms that BitBake recognizes the custom machine and can produce an image with the inherited development-kit configuration. The final validation is to flash it by following Flashing the Board and boot it on the matching AGX Orin development kit.