> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs-staging.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Build the kernel without Yocto

The standalone workflow lets you compile, test, and deploy kernel changes without
building the full Yocto image. All required cross-compilation and image-packaging
tools are bundled in the `kmake-image` Docker container.

## Limitations and caveats

<Warning>
  The standalone workflow builds and packages the kernel and modules only. It does
  not produce a root file system. To build or modify out-of-tree kernel modules that
  depend on the full Yocto BSP, use the Yocto-based workflow instead.
</Warning>

* **Toolchain**: the `kmake-image` Docker image provides an `aarch64` cross-toolchain,
  `systemd ukify`, and image-packaging scripts. No host toolchain installation is needed.
* **DTB packaging**: when building standalone, you must package the DTB manually
  using a static ITS configuration from the
  [qcom-dtb-metadata](https://github.com/qualcomm-linux/qcom-dtb-metadata) repository.
  The Yocto build handles this automatically via `meta-qcom`.

## Access kernel sources

Clone the kernel repository directly:

```bash theme={null}
git clone --branch qcom-6.18.y \
    https://github.com/qualcomm-linux/kernel.git kernel
```

**Table: Kernel branches**

| Branch | Use case |
| - | - |
| `qcom-6.18.y` | LTS production builds; recommended for SoC bring-up and integration |
| `qcom-next` | Upstream contribution and validation against the latest kernel |

### Check out the exact kernel source revision

A branch checkout follows the latest commit on that branch. For reproducible
standalone validation, check out the required branch and use the kernel `SRCREV`
from the `meta-qcom` release tag that built the target image to ensure
reproducible standalone validation.

Clone `meta-qcom` at that release tag and inspect the LTS kernel recipe:

```bash theme={null}
git clone --branch <release-tag> --depth 1 \
    https://github.com/qualcomm-linux/meta-qcom.git meta-qcom

grep -E '^(SRCREV|SRCBRANCH)' \
    meta-qcom/recipes-kernel/linux/linux-qcom_6.18.bb
```

Release tags follow the `qli-<version>` convention. Use the tag specified in
the release notes for the image under test and obtain the `SRCREV` from that tag.
Do not use the `master` branch because it may reference a newer kernel revision.

Copy the complete 40-character `SRCREV` value from the recipe, and then check out
the corresponding commit in the kernel clone:

```bash theme={null}
SRCREV="<40-character-SRCREV-from-recipe>"
git -C kernel checkout --detach "${SRCREV}"
git -C kernel rev-parse HEAD
```

Confirm that the value printed by `git rev-parse HEAD` exactly matches
`SRCREV` before building. For a `qcom-next` build, use
`meta-qcom/recipes-kernel/linux/linux-qcom-next_git.bb` and clone the
`qcom-next` kernel branch instead.

## Set up the Docker toolchain

### Option 1: Pull the pre-built image (recommended)

The primary approach is to pull the pre-built `kmake-image` from the registry:

```bash theme={null}
docker pull artifacts.codelinaro.org/clo-420-qli-registry/kmake-image:ver.1.0
docker tag artifacts.codelinaro.org/clo-420-qli-registry/kmake-image:ver.1.0 kmake-image
```

<Note>
  Pull the hosted image unless you plan to contribute to the kmake-image Docker image.
  This approach avoids Docker build failures caused by network connectivity or container
  registry access issues.
</Note>

### Option 2: Build the image locally

Clone and build the kmake-image container locally only if you need to develop or customize it:

```bash theme={null}
git clone https://github.com/qualcomm-linux/kmake-image.git
cd kmake-image
docker build --build-arg USER_ID=$(id -u) \
             --build-arg GROUP_ID=$(id -g) \
             --build-arg USER_NAME=$(whoami) \
             -t kmake-image .
cd ..
```

<Warning>
  If you encounter a "failed to resolve source metadata" error during the Docker build,
  see [Troubleshooting Docker build failures](#troubleshooting-docker-build-failures).
</Warning>

### Set up shell aliases

Set up shell aliases for convenience. Add these to your shell profile to persist
across sessions:

```bash theme={null}
alias kmake-image-run='docker run -it --rm \
  --user $(id -u):$(id -g) \
  --workdir="$PWD" \
  -v "$(dirname $PWD)":"$(dirname $PWD)" \
  kmake-image'
alias kmake='kmake-image-run make'
```

## Gather build artifacts

Create an `artifacts/` directory to hold the ramdisk, boot binaries, and DTB
metadata required to assemble the final images:

```bash theme={null}
mkdir artifacts
```

**Get the initramfs ramdisk**

```bash theme={null}
wget -O artifacts/ramdisk.gz \
    http://storage.kernelci.org/images/rootfs/buildroot/buildroot-baseline/20230703.0/arm64/rootfs.cpio.gz
```

**Get systemd-boot binaries**

```bash theme={null}
wget -O artifacts/systemd-boot-efi.deb \
    http://ports.ubuntu.com/pool/universe/s/systemd/systemd-boot-efi_255.4-1ubuntu8_arm64.deb
dpkg-deb -xv artifacts/systemd-boot-efi.deb artifacts/systemd
```

**Get DTB metadata**

When building standalone, DTBs must be packaged manually using a static ITS
configuration. Clone the `qcom-dtb-metadata` repository to get the required
`qcom-metadata.dts` and `qcom-next-fitimage.its` files:

```bash theme={null}
git clone https://github.com/qualcomm-linux/qcom-dtb-metadata.git \
    artifacts/qcom-dtb-metadata
```

## Build the kernel and modules

Configure and build the kernel using the standard Qualcomm<sup>®</sup> configuration
fragments, then install modules into a staging directory:

```bash theme={null}
cd kernel
mkdir -p ../kobj

env -u KCONFIG_CONFIG ./scripts/kconfig/merge_config.sh -m -O ../kobj \
    arch/arm64/configs/defconfig \
    arch/arm64/configs/prune.config \
    arch/arm64/configs/qcom.config

kmake O=../kobj olddefconfig
kmake O=../kobj -j$(nproc)
kmake O=../kobj -j$(nproc) dir-pkg INSTALL_MOD_STRIP=1
```

Package the built kernel modules (DLKMs) into the ramdisk:

```bash theme={null}
(cd ../kobj/tar-install ; \
 find lib/modules | cpio -o -H newc -R +0:+0 | gzip -9 >> ../../artifacts/ramdisk.gz)
```

## Package the boot images

**Generate `efi.bin` (ESP partition)**

The `efi.bin` image contains systemd-boot, the kernel (packaged as a UKI
type-2 image), and the initramfs:

```bash theme={null}
cd ..
# Default command line matches the Yocto UKI_CMDLINE from esp-qcom-image.bb.
# Override CMDLINE if your rootfs partition label or console differs.
CMDLINE="root=PARTLABEL=rootfs rw rootwait console=ttyMSM0,115200"
kmake-image-run generate_boot_bins.sh efi \
    --ramdisk artifacts/ramdisk.gz \
    --systemd-boot artifacts/systemd/usr/lib/systemd/boot/efi/systemd-bootaa64.efi \
    --stub artifacts/systemd/usr/lib/systemd/boot/efi/linuxaa64.efi.stub \
    --linux kobj/arch/arm64/boot/Image \
    --cmdline "${CMDLINE}" \
    --output images
```

**Generate `dtb.bin` (DTB partition)**

Build a FIT-based `dtb.bin` for all targets that support device tree:

```bash theme={null}
kmake-image-run make_fitimage.sh \
    --metadata artifacts/qcom-dtb-metadata/qcom-metadata.dts \
    --its artifacts/qcom-dtb-metadata/qcom-next-fitimage.its \
    --kobj kobj \
    --output images
```

Both `efi.bin` and `dtb.bin` are placed in the `images/` directory and are
ready to flash.

## Kernel Image Build Script

The Docker image includes a `build.sh` script that wraps the preceding build and
packaging steps and generates `efi.bin`, `dtb.bin`, and `boot.img`.

Set `--dtb` to the DTB for the validation target. For IQ-9075 EVK, run:

```bash theme={null}
kmake-image-run build.sh --dtb lemans-evk.dtb \
        --out kobj \
        --systemd artifacts/systemd/usr/lib/systemd/boot/efi \
        --ramdisk artifacts/ramdisk.gz \
        --images images \
        --cmdline "${CMDLINE}"
```

<Note>
  * The `--dtb` argument specifies the device tree blob to package in the
    target-specific images. Select the DTB that matches the target device.
  * Initialize `CMDLINE` to set your kernel command-line parameters; otherwise,
    a default generic command line is used.
</Note>

## Troubleshooting Docker build failures

If the Docker build fails with "failed to resolve source metadata" errors:

1. **Use the pre-built image (recommended)**

   See [Option 1: Pull the pre-built image](#option-1-pull-the-pre-built-image-recommended)
   for instructions.

2. **Check firewall and network access**

   Verify that your network allows access to the Docker registries:

   ```bash theme={null}
   # Test connectivity to Docker Hub
   curl -I https://registry-1.docker.io

   # Test connectivity to Codelinaro registry
   curl -I https://artifacts.codelinaro.org
   ```

   If these fail, contact your network administrator to allow outbound HTTPS
   connections to Docker registries.

3. **Pass proxy settings to the build**

   ```bash theme={null}
   docker build --build-arg HTTP_PROXY=$http_proxy \
                --build-arg HTTPS_PROXY=$https_proxy \
                --build-arg USER_ID=$(id -u) \
                --build-arg GROUP_ID=$(id -g) \
                --build-arg USER_NAME=$(whoami) \
                -t kmake-image .
   ```

## Flash and boot

Put the device into fastboot mode, then flash both images:

```bash theme={null}
fastboot flash efi images/efi.bin
fastboot flash dtb_a images/dtb.bin
fastboot reboot
```

After the device reboots, verify the running kernel version as described in
[Install & boot the kernel](./install-and-boot-the-kernel#verify-the-running-kernel).
