Yocto blueprint

Just some helpers/notes to start a new project with some passionate opinions.
Here's the complete setup process:
Step 1: Initial Repository Setup
mkdir meta-forte && cd meta-forte && git init -b main
Step 2: Create Directory Structure
mkdir -p layers/meta-forte/conf/{machine,distro} && mkdir -p layers/meta-forte/recipes-{kernel/linux,security/optee,core/images,apps/hello-trustzone} && mkdir -p kas docs scripts
You can check using tree command:
π¦[aviler@yocto-box meta-forte]$ tree
.
βββ docs
βββ kas
βββ layers
β βββ meta-forte
β βββ conf
β β βββ distro
β β βββ machine
β βββ recipes-apps
β β βββ hello-trustzone
β βββ recipes-core
β β βββ images
β βββ recipes-kernel
β β βββ linux
β βββ recipes-security
β βββ optee
βββ scripts
16 directories, 0 files
Step 3: Create .gitignore
cat > .gitignore << 'EOF'
# Kas artifacts
sources/
# Build outputs
build/
downloads/
sstate-cache/
tmp/
# Editor files
*.swp
*~
.vscode/
.idea/
# Python
__pycache__/
*.pyc
EOF
Step 4: Create Main kas.yml
cat > kas.yml << 'EOF'
header:
version: 14
machine: beagley-ai
distro: forte-distro
repos:
poky:
url: https://git.yoctoproject.org/git/poky
branch: scarthgap
layers:
meta:
meta-poky:
meta-openembedded:
url: git@github.com:openembedded/meta-openembedded.git
branch: scarthgap
layers:
meta-oe:
meta-python:
meta-networking:
meta-arm:
url: https://git.yoctoproject.org/git/meta-arm
branch: scarthgap
layers:
meta-arm:
meta-arm-toolchain:
meta-ti:
url: git@github.com:TexasInstruments/meta-ti.git
branch: scarthgap
layers:
meta-ti-bsp:
meta-ti-extras:
meta-forte:
path: layers/meta-forte
bblayers_conf_header:
forte: |
# Forte BeagleY-AI TrustZone Build Configuration
BBMASK += ""
local_conf_header:
forte: |
# Build optimizations
BB_NUMBER_THREADS = "8"
PARALLEL_MAKE = "-j 8"
# Package management
PACKAGE_CLASSES = "package_ipk"
# Base features
EXTRA_IMAGE_FEATURES += "ssh-server-openssh tools-debug"
# TrustZone/OP-TEE support (CORREΓΓO: hardware-specific)
MACHINE_FEATURES += "optee"
PREFERRED_PROVIDER_virtual/crypt = "optee-os"
ARM_TF_FLAGS += "TRUSTED_BOARD_BOOT=1"
# TI AM62x specific
MACHINE_ESSENTIAL_EXTRA_RDEPENDS += "ti-sci-fw"
target:
- forte-image
EOF
Updates on the kas.yml
refspec was deprecated so replaced with branch to avoid warning messages. Removed deprecated meta-beagle layer. Update github URLS to fix authenticate issues with HTTPS.Step 5: Create Kas Variants
cat > kas/dev.yml << 'EOF'
header:
version: 14
includes:
- ../kas.yml
local_conf_header:
dev: |
# Development build settings
EXTRA_IMAGE_FEATURES += "debug-tweaks tools-sdk tools-debug"
# Enable core dumps and debug symbols
IMAGE_FEATURES += "dbg-pkgs dev-pkgs"
# Keep debug info
INHIBIT_PACKAGE_STRIP = "1"
# Serial console access
SERIAL_CONSOLES = "115200;ttyS0"
EOF
cat > kas/prod.yml << 'EOF'
header:
version: 14
includes:
- ../kas.yml
local_conf_header:
prod: |
# Production build settings
EXTRA_IMAGE_FEATURES:remove = "debug-tweaks"
# Size optimization
IMAGE_FEATURES += "read-only-rootfs"
# Strip debug symbols
INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
# Security hardening
EXTRA_IMAGE_FEATURES += "secure-core-image"
EOF
cat > kas/sdk.yml << 'EOF'
header:
version: 14
includes:
- ../kas.yml
target:
- forte-image
- meta-toolchain
EOF
Step 6: Create Layer Configuration
cat > layers/meta-forte/conf/layer.conf << 'EOF'
# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "meta-forte"
BBFILE_PATTERN_meta-forte = "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-forte = "10"
# CORREΓΓO ESSENCIAL: dependΓͺncias explΓcitas
LAYERDEPENDS_meta-forte = "poky meta-arm meta-ti meta-beagle meta-openembedded"
LAYERSERIES_COMPAT_meta-forte = "scarthgap"
EOF
Step 7: Create Distro Configuration
cat > layers/meta-forte/conf/distro/forte-distro.conf << 'EOF'
require conf/distro/poky.conf
DISTRO = "forte-distro"
DISTRO_NAME = "Forte Linux (Yocto Project based Distro)"
DISTRO_VERSION = "1.0"
DISTRO_CODENAME = "scarthgap"
MAINTAINER = "Oliver M. Batista <code.monitor759@aleeas.com>"
# TrustZone/OP-TEE support
DISTRO_FEATURES:append = " optee"
# TI-specific optimizations
DISTRO_FEATURES:append = " sgx" # GPU acceleration
DISTRO_FEATURES:append = " virtualization" # KVM support
# TI SDK compatibility
PREFERRED_PROVIDER_virtual/mesa = "mesa-pvr"
PREFERRED_PROVIDER_virtual/libgles1 = "ti-sgx-ddk-um"
PREFERRED_PROVIDER_virtual/libgles2 = "ti-sgx-ddk-um"
PREFERRED_PROVIDER_virtual/egl = "ti-sgx-ddk-um"
# Systemd preferred
VIRTUAL-RUNTIME_init_manager = "systemd"
EOF
Step 7.5: Create machine configuration
cat > layers/meta-forte/conf/machine/beagley-ai.conf << 'EOF'
# @NAME: BeagleY-AI Machine Configuration
include conf/machine/include/ti-am62x.inc
MACHINE = "beagley-ai"
MACHINE_FEATURES += "screen gpu wifi bluetooth cryptoprocessor"
# Firmware requirements
MACHINE_ESSENTIAL_EXTRA_RDEPENDS += " \
trustzone-standalonefw \
optee-os-ti \
"
# Device tree and kernel config
KERNEL_DEVICETREE = "ti/k3-am625-beagley-a1.dtb"
UBOOT_MACHINE = "am62x_evm_a53_defconfig"
# TrustZone specific
OPTEE_PLATFORM = "k3-am62x"
OPTEE_EXTRA_BUILDARGS = "PLATFORM=ti-k3"
EOF
Step 8: Create Minimal Image Recipe
cat > layers/meta-forte/recipes-core/images/forte-image.bb << 'EOF'
SUMMARY = "Forte minimal image with TrustZone support"
LICENSE = "MIT"
inherit core-image
# Base image features
IMAGE_INSTALL:append = " \
kernel-modules \
openssh \
optee-os-ti \ # TI-specific
optee-client \
optee-test \
ti-sgx-ddk-um \ # GPU drivers
trustzone-standalonefw \ # TrustZone
ti-sci-fw \ # Firmware management
"
# Security packages
IMAGE_INSTALL:append = " \
packagegroup-security-optee \
tpm2-tools \
swtpm \
"
# Root filesystem extra space (MB)
IMAGE_ROOTFS_EXTRA_SPACE = "500"
# Image types (WB: Beagle-specific)
IMAGE_FSTYPES = "wic wic.bmap tar.xz"
WKS_FILE = "beaglebone-yocto.wks"
EOF
Step 9: Create Layer README
cat > layers/meta-forte/README.md << 'EOF'
# meta-forte Layer
Custom Yocto layer for BeagleY-AI with TrustZone/OP-TEE support.
## Layer Dependencies
- meta (poky)
- meta-arm
- meta-ti
- meta-beagle
- meta-oe (meta-openembedded)
## Recipes
- **recipes-core/images**: Custom image definitions
- **recipes-kernel/linux**: Kernel patches and configurations
- **recipes-security/optee**: OP-TEE trusted applications
- **recipes-apps**: Example applications
## Distro
- **forte-distro**: Custom distribution with TrustZone support
## Machine
- **beagley-ai**: BeagleY-AI board configuration (uses meta-beagle defaults)
## Verification Commands
```bash
bitbake-layers show-layers | grep "meta-forte"
bitbake-layers show-recipes "optee-*"
```
## Secure Boot Flow (need to verify)
- ARM TF-A (BL1/BL2) in secure world
- OP-TEE OS initializes secure partitions
- U-Boot (BL33 in non-secure world)
- Linux kernel with OP-TEE drivers
EOF
Step 10: Create Main README
cat > README.md << 'EOF'
# BeagleY-AI TrustZone Yocto Study Project
Study project demonstrating a custom Yocto build for BeagleY-AI with
TrustZone/OP-TEE integration using modern, scalable practices.
## π― Objectives
- Learn Yocto with professional approach
- Custom build for BeagleY-AI (TI AM62x)
- TrustZone/OP-TEE security integration
- Kas integration for reproducibility
- Document complete process
## π Quick Start
### Prerequisites
```bash
# Install Kas
pip3 install kas
# Install dependencies (Ubuntu/Debian)
sudo apt-get install gawk wget git diffstat unzip texinfo \
gcc build-essential chrpath socat cpio python3 python3-pip \
python3-pexpect xz-utils debianutils iputils-ping python3-git \
python3-jinja2 libegl1-mesa libsdl1.2-dev pylint xterm \
python3-subunit mesa-common-dev zstd liblz4-tool
```
### Build Commands
```bash
# Clone repository
git clone https://github.com/aviler/meta-forte.git
cd meta-forte
# Development build
kas build kas.yml:kas/dev.yml
# Production build
kas build kas.yml:kas/prod.yml
# Generate SDK
kas build kas.yml:kas/sdk.yml
```
### Flash to SD Card
```bash
# Find your SD card device (e.g., /dev/sdX)
lsblk
# Flash image (replace sdX with your device)
sudo dd if=build/tmp/deploy/images/beagley-ai/forte-image-beagley-ai.wic \
of=/dev/sdX bs=4M status=progress && sync
```
## ποΈ Architecture
### Layer Stack
```
meta-forte (custom)
β
meta-beagle (BeagleBoard configs)
β
meta-ti (TI AM62x BSP)
β
meta-arm (ARM architecture + TrustZone)
β
meta-openembedded (additional recipes)
β
poky (base Yocto)
```
### Key Technologies
- **Yocto Project**: Embedded Linux build system
- **Kas**: Declarative build configuration
- **OP-TEE**: Trusted Execution Environment
- **TI AM62x**: ARM Cortex-A53 + Cortex-M4F processor
- **BeagleY-AI**: Development board
## π Documentation
- [Setup Guide](docs/01-setup.md) - Initial environment setup
- [Build Process](docs/02-build-process.md) - Understanding the build
- [TrustZone Integration](docs/03-trustzone-integration.md) - OP-TEE setup
## π Key Learnings
- Modern Kas approach vs traditional git submodules
- Custom layer structuring and dependencies
- BSP integration for TI AM62x platform
- TrustZone/OP-TEE security architecture
- Build variant management (dev/prod/sdk)
- Reproducible build environments
## π€ Author
Oliver M. Batista - [Blog](https://olivermbatista.com) - [LinkedIn](https://www.linkedin.com/in/oliver-batista/)
EOF
Step 12: Create Helper Scripts
cat > scripts/setup.sh << 'EOF'
#!/bin/bash
# Quick setup script
echo "Installing Kas..."
pip3 install --user kas
echo "Checking dependencies..."
kas --version
echo "Setup complete! Run 'kas build kas.yml:kas/dev.yml' to build"
EOF
chmod +x scripts/setup.sh
cat > scripts/flash-image.sh << 'EOF'
#!/bin/bash
# Flash image to SD card
if [ -z "$1" ]; then
echo "Usage: $0 /dev/sdX"
echo "Available devices:"
lsblk -d -o NAME,SIZE,TYPE | grep disk
exit 1
fi
IMAGE="build/tmp/deploy/images/beagley-ai/forte-image-beagley-ai.wic"
if [ ! -f "$IMAGE" ]; then
echo "Error: Image not found at $IMAGE"
echo "Run a build first: kas build kas.yml:kas/dev.yml"
exit 1
fi
echo "Flashing $IMAGE to $1..."
sudo dd if=$IMAGE of=$1 bs=4M status=progress && sync
echo "Done!"
EOF
chmod +x scripts/flash-image.sh
Step 13: Initial Git Commit
git add . && git commit -m "Initial project structure with Kas configuration"
Had to branch out another article because I tried the command above on a super fresh new machine missing some git configuration, check it here Git inside Distrobox.
Step 14: Verify Structure
tree -L 3 -a
Step 15: Install and check Kas Configuration
Oh snap, forgot to install kas:
pip3 install kas
Update
kas.yml file I already update file contents above. Iβll leave a image here that show the issue. Added meta-beagle layer to meta-ti.kas dump kas.yml
We should see that everything went good and in the end of the log kas just rewrites the kas.yml file.
What Kas Will Populate
When you run kas build kas.yml, Kas will automatically:
Clone all repositories into
sources/:poky
meta-arm
meta-ti
meta-openembedded
Create build directory with:
build/conf/local.conf(from your kas.yml config)build/conf/bblayers.conf(from layer definitions)build/tmp/(build artifacts)
Download sources into
downloads/Create sstate cache in
sstate-cache/
Final Structure After First Build
meta-forte/
βββ layers/meta-forte/ (you created)
βββ kas.yml (you created)
βββ kas/ (you created)
βββ docs/ (you created)
βββ scripts/ (you created)
βββ sources/ (Kas clones this)
βββ build/ (Kas creates this)
βββ downloads/ (Kas creates this)
βββ sstate-cache/ (Kas creates this)
Summary of Manual vs Automated
You create manually (Steps 1-13):
Directory structure
Configuration files (kas.yml, layer.conf, etc.)
Your custom recipes
Documentation
Helper scripts
Kas creates automatically (when you run kas build):
sources/- All dependency layersbuild/- Build configuration and outputsdownloads/- Source tarballssstate-cache/- Shared state cache
This gives you a production-ready project structure that's fully reproducible! π
Follow up from steps above
Just created all the files required and run it kas dump kas.yml with success. I mean with still some small issues that I recorded above. Letβs try to build now.
The building attempts have resulted in the errors below
This is a summary of the recent BitBake errors encountered and the corresponding fixes:
| Error # | Description | Root Cause | Resolution |
| 1 (ParseError) | BitBake failed to parse forte-distro.conf. | An inline comment (# GPU acceleration) was placed on the same line as a variable assignment (DISTRO_FEATURES:append = ...). BitBake requires comments to be on separate lines. | The comment was moved or removed from the assignment line. |
| 2 (Host Tool Missing) | BitBake failed to start due to missing system tools. | The essential host utility file (specified by HOSTTOOLS) was not found in the host system's $PATH. | The file utility package was installed on the host operating system. |
| 3 (Layer Dependency) | meta-forte reported dependency errors (e.g., "depends on layer 'poky', but this layer is not enabled"). | The layers were enabled in bblayers.conf, but the local layer (meta-forte/conf/layer.conf) used the wrong dependency names (full repository names like poky or meta-ti). | The dependency definition (LAYERDEPENDS_meta-forte) was corrected to use the required short collection names (e.g., core, meta-oe, ti-bsp) found in each sublayer's conf/layer.conf. |
Letβs try again

Ok, oh by the way, today we are searching with Deepseek R1T2 Chimera. The errors were about dependencies declared in meta-forte/conf/layer.conf but missing from the kas config.
Ok had a new error because I was adding yocto to the key/value below from meta-forte/conf/layer.conf
LAYERDEPENDS_meta-forte = "yocto core meta-ti-extras meta-ti-bsp meta-beagle meta-python openembedded-layer networking-layer arm-toolchain meta-arm"
Thing is that we are creating a custom meta-layer and in this sense yocto in LAYERDEPENDS_ is wrong. The meta-poky is a reference/example layer, it canβt be used as dependency for other custom layers like how we are creating meta-forte to be. We donβt need meta-poky as dependency for meta-forte layer but we still need to declare it in the kas.yml file so we use some base configurations in our distro. We define a distro ourselves atmeta-forte/layers/meta-forte/conf/distro/forte-distro.conf.
Well the error message changed:

After researching I have a guess that this might be related with my attempt to create a custom machine to wrapper the official one. Made some mistakes in the file meta-forte/conf/machine/beagley-ai.conf and will try to make the changes below and try again.
require conf/machine/beagley-ai.conf
# @NAME: BeagleY-AI Machine Configuration
# No need to define we get it from the requite in the top of this file
#MACHINE = "beagley-ai"
MACHINE_FEATURES += "screen gpu wifi bluetooth cryptoprocessor"
# Rest of the file remains how it was
New error during build
And also some weird behaviour from this blog editor from hashnode.com π I guess I need to go back to old habits like typing CTRL+S every 3-5 words. So I am facing this bundle of warnings ending in as error and itβs all related.

Is a Python RecursionError generated by this endless loop of self include in the layers/meta-forte/conf/machine/beagley-ai.conf we let it happen. The file requires a beagly-ai.conf. Then bitbake go search this file. It finds the same but includes anyways, repeting until it reaches its limit. So I removed the βselfβ inclusion, added two new require entries and did some cleaning compared to the original.
# layers/meta-forte/conf/machine/beagley-ai.conf
# Get the base for BeagleY-AI (SoC J722S)
require conf/machine/include/j722s.inc
require conf/machine/include/beagle-bsp.inc
# Add desired features
MACHINE_FEATURES += "screen gpu wifi bluetooth cryptoprocessor"
# Add firmware dependency for TrustZone/OP-TEE
MACHINE_ESSENTIAL_EXTRA_RDEPENDS += " \
trustzone-standalonefw \
optee-os-ti \
"
# TrustZone specific
# Still need to check if these values are correct
OPTEE_PLATFORM = "k3-am62x"
OPTEE_EXTRA_BUILDARGS = "PLATFORM=ti-k3"
And it worked because at least the layer resolution got solved by bitbake and now I see some sort of parsing issue.
ERROR: /var/home/aviler/Code/meta-forte/build/../poky/meta/recipes-core/packagegroups/packagegroup-rust-cross-canadian.bb: Please ensure that your setting of VIRTUAL-RUNTIME_init_manager (systemd) matches the entries enabled in DISTRO_FEATURES
ERROR: /var/home/aviler/Code/meta-forte/build/../poky/meta/recipes-core/packagegroups/packagegroup-core-ssh-dropbear.bb: Please ensure that your setting of VIRTUAL-RUNTIME_init_manager (systemd) matches the entries enabled in DISTRO_FEATURES
Summary: There were 58 ERROR messages, returning a non-zero exit code.
2025-11-09 21:58:34 - ERROR - Command "/var/home/aviler/Code/meta-forte/poky/bitbake/bin/bitbake -c build forte-image" failed with error 1
π¦[aviler@yocto-box meta-forte]$
The amazing thing about Yocto is that you not only need many files but you also need to be consistent in between configuration files. So, I wanted to have systemd so I added the key VIRTUAL-RUNTIME_init_manager = "systemd", but for this to work, I also need to explicitly ask for the feature with DISTRO_FEATURES:append = " systemd". And, that solves. Ok! Next error π
And I fall again for the misplaced # comment in files:
ERROR: ParseError at .../forte-image.bb:10: unparsed line: 'IMAGE_INSTALL:append = " ... optee-os-ti \ # TI-specific'
Just went to forte-image.bb file and removed the comments written in the end of the line. I can say it worked because my laptop fans are going crazy parsing the recipes here. All recipes parsed but still other errors, letβs fix it!
And we are back at it

The above error list is about a missing UBOOT_MACHINE declaration. I thought the previously added dependencies would define it, but I was wrong.

Still donβt get why we canβt just βincludeβ this file and accept whatever it says and on our custom layer we just declare things that we would like to override. So, I added the UBOOT_MACHINE config and that fix it.

The optee things are not on the meta-ti layer but in the meta-arm one. Will update package name from optee-os-ti to optee-os at the files forte-image.bb and in our custom machine definition beagley-ai.conf.
Ok, so my first draft for this project was based on beaglebone-black examples which of course would not work with beagley-ai. I am removing references of ti-sgx-ddk-um and other graphics related. Hopefully, a correct configuration will be finded by bitbake if not is ok since I donβt need any graphics related stuff for now.

Another wrong package name, replacing trustzone-standalonefw with arm-trusted-firmware. It didnβt work, same error but now about arm-trusted-firmware.
Removed more clutter like below. Beagley-ai has no TPM components so I got a bulding error about the tpm2-tools package/feature so I just removed the whole section below:
# Security packages
IMAGE_INSTALL:append = " \
tpm2-tools \
swtpm \
"
After some more tries
I had to solve more issues with outdated package names, removing features completely because my board canβt support TPM π , and other details. The building process seems to be happening.

So yeah, this is the real deal. And it is even slowing me down while typing this paragraph. The laptop fans are singing the song of their people.
When you see BitBake starting to execute tasks like this, it means:
All configurations are valid.
All layers are correctly loaded.
All dependencies have been successfully resolved.
BitBake now has a complete, valid plan to build your entire Linux distribution from source.
What's Happening Now?
You are now in the actual build phase. BitBake is executing tasks in order for hundreds of packages. You'll see it go through stages for each package:
do_fetch (downloading source code)
do_unpack
do_patch
do_configure
do_compile (This is the long part)
do_install
do_package
A Word of Warning: The very first build from scratch is a marathon. Depending on your machine's CPU, RAM, and internet speed, this will take a long timeβanywhere from an hour to several hours.
Conclusion?
This article started as just notes to draft a blueprint for a YOCTO project. It started with too big goals, maybe, but here we are. Great learning challenge so far. But now it is making me suffer by making it impossible to use this laptop. I need to buy βserverββ¦ yeah this distrobox should be a VPS on someone else's computer. It would be a good topic for a follow-up article.


