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:
| Type | Purpose |
|---|
| factory | For first-time installation from the vendor’s stock firmware. Often includes a vendor-specific header. |
| sysupgrade | For upgrading an existing OpenWrt installation via sysupgrade or LuCI. |
Additional image types exist for specific targets:
| Type | Description |
|---|
initramfs | RAM-based root filesystem loaded by the bootloader, used for recovery and testing |
combined | Single image containing kernel + rootfs on the same block device (used for x86/EFI) |
kernel | Standalone kernel image only |
The rootfs inside firmware images can use different formats depending on the target’s FEATURES:
| Format | Description |
|---|
squashfs | Compressed read-only filesystem. Most common for flash-based targets. Paired with OverlayFS for writes. |
ext4 | Read-write filesystem. Used for x86 targets with larger storage. |
jffs2 | Journaling flash filesystem. Used for older NOR-flash targets. |
ubifs | NAND-optimized flash filesystem. Used for NAND targets. |
erofs | Enhanced 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:
| Variable | Description |
|---|
KDIR | Kernel build directory ($(BUILD_DIR)/linux-$(BOARD)_$(SUBTARGET)) |
KDIR_TMP | Temporary directory inside KDIR for intermediate files |
DTS_DIR | Location of compiled Device Tree blobs (.dtb files) |
IMG_PREFIX | Base image filename prefix: openwrt-<version>-<board>-<subtarget> |
IMG_PREFIX_EXTRA | Additional suffix from CONFIG_EXTRA_IMAGE_NAME |
IMG_ROOTFS | Rootfs image name: $(IMG_PREFIX)-rootfs |
IMG_COMBINED | Combined image name: $(IMG_PREFIX)-combined |
TARGET_DIR | Directory containing the staged rootfs for image assembly |
Utility Macros
| Macro | Description |
|---|
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:
| Command | Description |
|---|
append-kernel | Append the compiled kernel binary |
append-rootfs | Append the compiled rootfs image |
pad-to <size> | Pad the image to a specific size |
pad-rootfs | Pad the rootfs to fill the partition |
check-size | Verify the image fits within the device’s flash size |
append-dtb | Append Device Tree Blob to the kernel |
kernel-bin | Prepare 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.