> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.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`.
* **Source revision**: to match the exact source used in a release build, check the
  `SRCREV` field in `meta-qcom/recipes-kernel/linux/linux-qcom_6.18.bb`.

## 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      |

## Set up the Docker toolchain

Clone and build the `kmake-image` container:

```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 ..
```

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

Above build and package steps are wrapped under a `build.sh` script which is
part of docker, to automate building and packaging a bootable kernel image into
efi.bin, dtb.bin, and boot.img.

To use this alternative `build.sh` script run following:

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

<Note>
  * The --dtb argument is mandatory. It specifies the Device Tree Blob to be
    packed into the kernel image. Above command shows using `qcs6490-rb3gen2.dtb`
    as an example.
  * Initialize CMDLINE to set your kernel cmdline parameter else a default
    generic is used.
</Note>

## 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).
