Ubiquiti airCube: Alternative installation method - problems when writing U-Boot environment


I'm searching for a method to install OpenWRT on the Ubiquiti AirCube via the original web interface instead of via a serial console.

Note: They are using a fork of OpenWRT (see [1] below for more details).

I did some analysis and I think I found a way to inject a script via uploading a new config. See my notes on github if you are interested in lot's of details.

What I didn't manage was to convince their version of sysupgrade to accept a OpenWRT image. But I found that the tools for U-Boot environment management are installed (fw_printenv and fw_setenv) and with some effort they can be used too.

Now my problem:

If I call fw_setenv from the injected script I receive the following error:

+ fw_setenv -s /tmp/ubootenv_add
Can't open /dev/mtd1: Operation not permitted
Error: can't write fw_env to flash

If I use the same script (or only fw_setenv after preparation with the script from web-if) from the console, everything works and the environment is modified.

Any idea, why fw_setenv has a different behaviour depending on from where I call it?

Thanks in advance for any hints.

[1] Some background info: Ubiquiti is running an old version of OpenWRT. Some weeks after the airCube support has been added to OpenWRT, they published their sources (the ones where their support told me that they have no ETA when I asked a few months before adding the support). The source archive that can be downloaded from their home page seems to be based on a commit somewhere around 8fe8360981acd7e65 (from Sun Jan 31 00:55:05 2016 - "musl: fix an alignment issue that was breaking ldso on ARMv5"). At least that's the version with the least differences.

From your github

# prepare environment for fw_setenv
mkdir -p /tmp/root
mkdir -p /tmp/overlay
mkdir -p /tmp/overlay_work
mount -t squashfs -oro /dev/mtdblock3 /tmp/root
mount -t overlay -o lowerdir=/tmp/root/etc,upperdir=/tmp/overlay,workdir=/tmp/overlay_work overlay /etc
echo "/dev/mtd1 0x0 0x10000 0x10000" >> /etc/fw_env.config

Where in the above is /dev/mtd1? I think you may have missed something here ( dev )... What bootstage is this running at? Either way ... you can't test very well running blind.... have you tried attaching console / "echo cat /proc/partitions >> /dev/console" etc. etc.

Thanks for having a look at that and sorry that I missed some relevant information in my initial post. It's sometimes a little hard to extract the relevant parts when you have been working on the problem for some time.

I have a console attached and I can log in via serial console. My target is that I'm able to flash OpenWRT on a second airCube without opening it (just out of ambition).

The steps in the script have been found by experimenting on the console. The same is true for the U-Boot environment variables that I want to write. I already tested it and it works if entered manually.

Regarding the partitions:

ubnt@(none):~# cat /proc/partitions 
major minor  #blocks  name

  31        0        256 mtdblock0
  31        1         64 mtdblock1
  31        2       4096 mtdblock2
  31        3      11648 mtdblock3
  31        4        256 mtdblock4
  31        5         64 mtdblock5
ubnt@(none):~# cat /proc/mtd 
dev:    size   erasesize  name
mtd0: 00040000 00010000 "u-boot"
mtd1: 00010000 00010000 "u-boot-env"
mtd2: 00400000 00010000 "kernel"
mtd3: 00b60000 00010000 "rootfs"
mtd4: 00040000 00010000 "cfg"
mtd5: 00010000 00010000 "EEPROM"

The script I wrote works as long as I call it manually from a console. But it doesn't when called via the injected lua-handler from the uhttpd webserver. I was hoping that someone could help me find differences. uhttpd runs with root rights and all the preparation stuff works fine. Only the fw_setenv prints an error when called from uhttpd.

In both cases (console and webserver) the device is fully booted.

1 Like

so you've answered your own question. the proc partitions output you showed was not from your script. the whole point is to probe the environment from within the script. but know you know it's an interpreter / handler issue.... can you think of better ways to troubleshoot that?

Good hint. Although I wouldn't expect the output to be any different from the command line and from a injected script, I'll take a look (maybe extending the lua script to take a command via the parameter - makes analyzing simpler). I somehow didn't realize that it might would be a good idea to analyze that via the injected code.

I'll report back in a few days (I don't think that I find much time during the week).

I have added a "execute any command" to my lua script but I was not able to find the difference between console and injected command. So I tried something quite different: Stop the firewall and start a dropbear via console. I tried to use the fw_setenv in that ssh session. Result: Can't open /dev/mtd1: Operation not permitted.

So I have no idea how it has been done but it seems that fw_setenv can only be run from a directly connected serial shell on that target.

Seems like I'll have to try to find some other way to program the firmware image ...