Skip to main content
Image generation is the final stage of the OpenWrt build: it takes the compiled kernel and rootfs and packages them into firmware image files suitable for flashing onto target devices.

Image Types

OpenWrt produces two primary image types for most embedded targets:
TypePurpose
factoryFor first-time installation from the vendor’s stock firmware. Often includes a vendor-specific header.
sysupgradeFor upgrading an existing OpenWrt installation via sysupgrade or LuCI.
Additional image types exist for specific targets:
TypeDescription
initramfsRAM-based root filesystem loaded by the bootloader, used for recovery and testing
combinedSingle image containing kernel + rootfs on the same block device (used for x86/EFI)
kernelStandalone kernel image only

Filesystem Formats

The rootfs inside firmware images can use different formats depending on the target’s FEATURES:
FormatDescription
squashfsCompressed read-only filesystem. Most common for flash-based targets. Paired with OverlayFS for writes.
ext4Read-write filesystem. Used for x86 targets with larger storage.
jffs2Journaling flash filesystem. Used for older NOR-flash targets.
ubifsNAND-optimized flash filesystem. Used for NAND targets.
erofsEnhanced read-only filesystem (newer, replaces SquashFS in some cases).

Key image.mk Variables

These variables are defined in include/image.mk and available in target image Makefiles:
VariableDescription
KDIRKernel build directory ($(BUILD_DIR)/linux-$(BOARD)_$(SUBTARGET))
KDIR_TMPTemporary directory inside KDIR for intermediate files
DTS_DIRLocation of compiled Device Tree blobs (.dtb files)
IMG_PREFIXBase image filename prefix: openwrt-<version>-<board>-<subtarget>
IMG_PREFIX_EXTRAAdditional suffix from CONFIG_EXTRA_IMAGE_NAME
IMG_ROOTFSRootfs image name: $(IMG_PREFIX)-rootfs
IMG_COMBINEDCombined image name: $(IMG_PREFIX)-combined
TARGET_DIRDirectory containing the staged rootfs for image assembly

Utility Macros

MacroDescription
exp_units(size)Convert size with unit suffix (k, m, g) to a byte expression. E.g., exp_units(4m)4 * 1024k
param_get(key, list)Extract value from a key=value entry in a list
param_get_default(key, list, default)Like param_get but returns default if not found

Image Build Commands

Common build commands used in IMAGE/ rules:
CommandDescription
append-kernelAppend the compiled kernel binary
append-rootfsAppend the compiled rootfs image
pad-to <size>Pad the image to a specific size
pad-rootfsPad the rootfs to fill the partition
check-sizeVerify the image fits within the device’s flash size
append-dtbAppend Device Tree Blob to the kernel
kernel-binPrepare the kernel binary in the target format

Defining Device Images

Each device profile in image/Makefile uses the Device/ template:
define Device/tplink-archer-c7-v2
  DEVICE_VENDOR := TP-Link
  DEVICE_MODEL := Archer C7
  DEVICE_VARIANT := v2
  DEVICE_DTS := ath79/qca9558_tplink_archer-c7-v2
  IMAGE_SIZE := 16128k
  TPLINK_HWID := 0xc7000002
  IMAGES := factory.bin sysupgrade.bin
  IMAGE/factory.bin := append-kernel | pad-to 64k | \
      append-rootfs | pad-rootfs | tplink-v1-image
  IMAGE/sysupgrade.bin := append-kernel | pad-to 64k | \
      append-rootfs | pad-rootfs | check-size
endef
TARGET_DEVICES += tplink-archer-c7-v2

Building Images

# Build all images for the selected target
make target/install

# Build images for a specific profile
make target/install PROFILE=tplink-archer-c7-v2

# Rebuild only the image stage (skip package compilation)
make target/linux/compile V=s

Output Location

All generated firmware images are placed in:
bin/targets/<target>/<subtarget>/
For example:
bin/targets/ath79/generic/
  openwrt-ath79-generic-tplink-archer-c7-v2-squashfs-factory.bin
  openwrt-ath79-generic-tplink-archer-c7-v2-squashfs-sysupgrade.bin
  profiles.json
  sha256sums

profiles.json

The build system generates a profiles.json file alongside the images. It provides a machine-readable summary of all built device profiles:
{
  "target": "ath79",
  "subtarget": "generic",
  "profiles": {
    "tplink-archer-c7-v2": {
      "id": "tplink-archer-c7-v2",
      "target": "ath79/generic",
      "name": "TP-Link Archer C7 v2",
      "images": [
        { "name": "openwrt-ath79-generic-tplink_archer-c7-v2-squashfs-factory.bin",
          "type": "factory" },
        { "name": "openwrt-ath79-generic-tplink_archer-c7-v2-squashfs-sysupgrade.bin",
          "type": "sysupgrade" }
      ]
    }
  }
}
This file is consumed by the OpenWrt Firmware Selector and Image Builder tools.
The script scripts/json_overview_image_info.py and scripts/json_add_image_info.py are responsible for generating and populating profiles.json.

Build docs developers (and LLMs) love