Which image have I flashed?

I have been building some different images and generally playing around. So I have 2 different images both built from 21.02.2. Is there a straight forward way to determine which image I have actually flashed onto my OpenWrt device? Yes I realise I could just flash it again but I wanted to know if there is a way to interrogate the running image.

Both images have the same "version.buildinfo" reference (r16495-bf0c965af0) but obviously the "config.buildinfo" and the hash for the bin files are different. I tried looking at /proc/version but that just tells me the version buildinfo.


SSH in to the router and run ubus call system board

Thanks but it doesn't help identify exactly which image I flashed just the build details which is the same for both images even though the built with different libraries.

        "kernel": "5.4.179",
        "hostname": "OpenWrt",
        "system": "MediaTek MT7621 ver:1 eco:3",
        "model": "D-Link DIR-2660 A1",
        "board_name": "dlink,dir-2660-a1",
        "release": {
                "distribution": "OpenWrt",
                "version": "21.02.2",
                "revision": "r16495-bf0c965af0",
                "target": "ramips/mt7621",
                "description": "OpenWrt 21.02.2 r16495-bf0c965af0"

Suppose I should have added some descriptive name into the build details during compilation, I guess that would have worked

It may only be a clue, but the file date and time on, e.g., /etc/banner /etc/rom tells you at least when exactly you built the image and may allow you to correlate that with the datetime of one of your images.

# date -r /etc/rom

(Edited, see below.)

The list of installed packages and their dependencies might give you some clues -

SSH in and run the following -

for PKG in $(opkg list-installed | awk -e '{print $1}' | tr '\n' ' ')
	opkg info $PKG | grep -E "Package:|Depends:" 

Good idea.

ls --full-time /rom
will give you image date/time creation

1 Like

That's pretty much exactly what I said two posts earlier. No harm in that, good advice won't get bad if given twice. That being said, ls will not give you the time if the file was created in a different year, replacing the time with the year, so it's better to recommend date -r /rom to get the full timestamp.

Point taken, but the question was which of two 21.02.2 builds was most current. Year wasn’t relevant.

I’ve edited my post to reflect the ls option that provides full timestamp. Got caught out by my shell alias :flushed:

Checking /rom is less ambiguous to the question. It’s static, and the timestamps are created in the build process. I for one rely on touch /etc/banner in a couple of of shell scripts I use, and I know there are a lot of cron reboot runs in use.

Oh, right, I forgot that it's a popular workaround to touch exactly that file. Of all the files I could have chosen I just had to pick that one. :sweat_smile: Good catch, I'll edit my post.

@takimata and @RuralRoots

Thanks both.......these commands both give the same date/time but it's not the date/time that I built the image so I'm a bit confused by that. The image that is flashed onto the device atm was created 12th April 2022 09:47:04 BST but the commands you have suggested both give a date time of 16th Feb 2022 20:29:10


Thanks....I guess I could just look for the libraries I included in the build

Are you using imagebuilder or Buildroot to create your images?

If you are using imagebuilder, check the date/time of your openwrt-imagebuilder-21.02.2-<your target>.Linux-x86_64.tar.xz

Buildroot for image creation. However, I do have the imagebuilder archive in the same packages directory as the bin files I created.....it has the same date as the files on running OpenWrt system (i.e. 16th Feb)?

If your sysupgrade.bin you flashed is dated as above and your /rom is dated Feb. 16, I have to surmise you are using ImageBuilder for your images and not building from source.

I flashed a "factory.bin" image. Here is the guide I was following when I built the image, not specifically a OpenWrt build document but covers downloading source etc etc...


I vaguely remember the build system setting the "creation date" on a squahfs filesystem to the last-commit date, rather than the build time. (This kind of choice is needed for testing that requires repeatable builds.)

See, for example, fgrep -r SOURCE_DATE_EPOCH ./include

1 Like

Thanks @jeff

That would make sense. Posted the output from my build environment, doesn't mean a great deal to me.

fgrep -r SOURCE_DATE_EPOCH ./include
./include/package-ipkg.mk:)$$(call addfield,SourceDateEpoch,$(PKG_SOURCE_DATE_EPOCH)
./include/package-ipkg.mk:    $$(IPKG_$(1)) : export PKG_SOURCE_DATE_EPOCH:=$(PKG_SOURCE_DATE_EPOCH)
./include/package.mk:PKG_SOURCE_DATE_EPOCH:=$(if $(DUMP),,$(shell $(TOPDIR)/scripts/get_source_date_epoch.sh $(CURDIR)))
./include/kernel-defaults.mk:	$(if $(SOURCE_DATE_EPOCH),touch -hcd "@$(SOURCE_DATE_EPOCH)" $(TARGET_DIR)/init)
./include/kernel.mk:ifneq ($(SOURCE_DATE_EPOCH),)
./include/kernel.mk:    KBUILD_BUILD_TIMESTAMP:=$(shell perl -e 'print scalar gmtime($(SOURCE_DATE_EPOCH))')
./include/version.mk:# SOURCE_DATE_EPOCH:=x
./include/kernel-build.mk:		$(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \
./include/toplevel.mk:  SOURCE_DATE_EPOCH:=$(shell $(TOPDIR)/scripts/get_source_date_epoch.sh)
./include/toplevel.mk:export SOURCE_DATE_EPOCH
./include/image.mk:IMG_PART_SIGNATURE:=$(shell echo $(SOURCE_DATE_EPOCH)$(LINUX_VERMAGIC) | mkhash md5 | cut -b1-8)
./include/image.mk:IMG_PART_DISKGUID:=$(shell echo $(SOURCE_DATE_EPOCH)$(LINUX_VERMAGIC) | mkhash md5 | sed -E 's/(.{8})(.{4})(.{4})(.{4})(.{10})../\1-\2-\3-\4-\500/')
./include/image.mk:		$(if $(SOURCE_DATE_EPOCH),-T $(SOURCE_DATE_EPOCH)) \
./include/image.mk:		$(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \
./include/image.mk:	SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) \
./include/image.mk:	SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) \
./include/image-commands.mk:		$(if $(SOURCE_DATE_EPOCH),-fixed-time $(SOURCE_DATE_EPOCH))
./include/image-commands.mk:		$(if $(SOURCE_DATE_EPOCH),--mtime="$(SOURCE_DATE_EPOCH)") \
./include/rootfs.mk:	$(if $(SOURCE_DATE_EPOCH),sed -i "s/Installed-Time: .*/Installed-Time: $(SOURCE_DATE_EPOCH)/" $(1)/usr/lib/opkg/status)
./include/rootfs.mk:	$(if $(SOURCE_DATE_EPOCH),find $(1)/ -mindepth 1 -execdir touch -hcd "@$(SOURCE_DATE_EPOCH)" "{}" +)

And you followed the OpenWrt Build System:

https://openwrt.org/docs/guide-developer/toolchain/use-buildsystem#build_system_usage to build the factory.img you flashed, or did you just download factory.img from https://downloads.openwrt.org/releases/21.02.2 and flash it?

I see nothing there that explains building an OpenWrt firmware.

Not sure I'm following you.

As per the link and instructions....

I downloaded the sources
Selected a specific code revsion
Updated the feeds
Configured the image and kernel
Build the firmware image

Isn't that what building a OpenWrt firmware image involves? What am I missing?

I use this shell script:

$ cat ~/bin/wrt


usage () {
    echo '
usage: wrt prep [{wrt1900acs,wndr3700v2}]
       wrt save [{wrt1900acs,wndr3700v2}]'
    exit 0


case $TARGET in
        echo "unknown target $TARGET"

find_fw_name () {
    local \
        rev="$(git rev-parse --short=10 HEAD)"
    local date=$(date +%Y%m%d)

    local i=1
    while [ -f "$SAVE_DIR/$fw_name.config" ]; do
        i=$(($i + 1))

prep () {
    if [ ! -f .config ] ; then echo '.config does not exist'; exit 1; fi

    if [ -d $ETC_FW_DIR ]; then
        find $ETC_FW_DIR -name '*~' -delete
        mkdir -p $ETC_FW_DIR

    cp -v .config $ETC_FW_DIR/config

    echo "$fw_name" > $ETC_FW_DIR/version

save () {
    if [ ! -f .config ] ; then echo '.config does not exist'; exit 1; fi

    local BIN_DIR
    local FW_BASE
    if [ -d $OPENWRT_BIN_DIR ] ; then
        echo 'BIN_DIR not recognized'
        exit 1
    local fw_factory="$BIN_DIR/$FW_BASE-factory.img"
    local fw_sysupgrade="$BIN_DIR/$FW_BASE-sysupgrade.bin"

    for fw in $fw_factory $fw_sysupgrade; do
        if [ ! -f $fw ] ; then echo "$fw does not exist"; exit 1; fi

    if [ -f $ETC_FW_DIR/version ]; then
        fw_name=$(cat $ETC_FW_DIR/version)

    if [ -f $fw_config ]; then
        echo "$fw_config exists, forgot 'wrt prep' before 'make'?"
        exit 1

    cp -v .config $fw_config

    cp -v $fw_factory $fw_fdst

    cp -v $fw_sysupgrade $fw_sdst

case $1 in
    p|pr|pre|prep)  prep;;

    s|sa|sav|save)  save;;

    *) usage;;

Calling 'wrt prep' from the buildroot before starting the build will create two files in ./files/etc/firmware:
version has one line like 'wrt1900acs-20220506-231206ad23-1', i.e. target, build date, git revision and a number incremented with each 'wrt prep'.
config is a copy of .config created with 'make menuconfig'
After flashing the image and ssh-ing into the router they are available in /etc/firmware/.

Calling wrt save after the build will use the string in ./files/etc/firmware/version as basename for 3 files copied to $buildroot/..:
$version_string.fac.img is the factory image,
$version_string.sys.bin is a sysupdate image and
$version_string.config is again a copy of ./.config.