How to mount /lib/firmware RW

My apologies if this is an ignorant question, I have googled and searched this forum but have been unable to find the answer. I wanted to try to add wireless support to an unsupported board (everything works except wireless) during the build process. However, in order to do this I need to mount /lib/firmware RW.

I appreciate the assistance.

Hi Rob!

/lib/firmware is part of the host OS filesystem, and changing it would either block Resin OS updates, or overwrite them on every update ā€“ As this could leave devices in a non functioning state, Resin OS doesnā€™t allow modifications to it by default.

That said, it is certainly possible to load custom kernel modules and/or firmware from a container. If you put the firmware in the containers /lib/firmware (instead of mounting the host OSā€™s), and load the required kernel module from there, that generally works well.

Alternatively, there might be a way to specify an alternative location for the firmware in the drivers?

I found this thread when searching for ā€œbalena mount /lib/fimware rwā€ which is pretty close to the threadā€™s titleā€¦ yet the thread didnā€™t quite answer the question. As Iā€™ve found a bit more about the answer, I thought I would add it here. (Chances are Iā€™ll need to search again in a few monthsā€™ time, so really I am helping myself.) :slight_smile:

Regarding the /lib/firmware folder, it is possible to ā€œbind mountā€ it on an app container by setting the io.balena.features.firmware label in the docker-compose.yml file (or by using a single-container app with a single Dockerfile):

With that in place, firmware files can be added through an app container. The /lib/firmware folder will be initially mounted ā€œread onlyā€ on the app container, but it can remounted ā€œread writeā€ before copying the file(s) with the command:

# on the app container
mount -o remount,rw /lib/firmware

It works similarly for the /lib/modules folder.

Specifically regarding network interfaces that are required to allow the device to connect to the internet, note that balena does not advise loading kernel modules or firmware files via app containers because of the risk that a routing application update could fail (e.g. a typo in the Dockerfile entry point script) and thus render the device unreachable. It would also make host OS upgrades riskier, in case the firmware file is incompatible (thought host OS upgrades should be first tested in a lab anywayā€¦).

1 Like

I know Iā€™m bumping an old topic; apologies. Your instructions are exactly what Iā€™m looking for, but when I attempt to bind-mount the /lib/firmware directory:

services:
    app:
      ...
      labels:
        io.balena.features.firmware: '1'
      ...

ā€¦and then attempt to re-mount the directory in the container, I get this error:

bash-5.0# mount -o remount,rw /lib/firmware
mount: can't find /lib/firmware in /proc/mounts

Any ideas?

EDIT: I was able to get it working by making two small changes.

First, I had to run my app container with privileged: true:

services:
    app:
      ...
      labels:
        io.balena.features.firmware: '1'
      privileged: true
      ...

Second, I had to have a space between remount and rw (I got the idea from https://askubuntu.com/a/744648):

bash-5.0# mount -o remount, rw /lib/firmware
1 Like

Glad you got it working and thanks for posting your solution!

Hi,
I am trying to copy my new Wifi dongle driver in to the /lib/firmware.
followed you way but doesnā€™t work for me. When I want to build the image and upload in the fleet, I have error which is :
"
[app] Step 80/83 : RUN mount -o remount, rw /lib/firmware
[app] ā€”> Running in 629a1642eb30
[app] mount: /lib/firmware: mount point does not exist.
"

my docker-compose.yml is :
"
version: ā€˜2.1ā€™
volumes:
settings-data:
log-data:
persistent-files:
services:
app:
build: ./app
privileged: true
network_mode: host
volumes:
- ā€˜settings-data:/usr/src/app/settingsā€™
- ā€˜log-data:/usr/src/app/logsā€™
- ā€˜persistent-files:/usr/src/app/persistentā€™
labels:
io.balena.features.kernel-modules: ā€˜1ā€™
io.balena.features.firmware: ā€˜1ā€™
io.balena.features.dbus: ā€˜1ā€™
io.balena.features.supervisor-api: ā€˜1ā€™
io.balena.features.balena-api: ā€˜1ā€™
io.balena.features.sysfs: ā€˜1ā€™
ulimits:
core:
hard: 0
soft: 0
"

and added this bit in my Dockerfile:
"
RUN mount -o remount, rw /lib/firmware

COPY WIFI_RAM_CODE_MT7961_1.bin /lib/firmware/mediatek/WIFI_RAM_CODE_MT7961_1.bin

COPY WIFI_MT7961_patch_mcu_1_2_hdr.bin /lib/firmware/mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin
"

Appreciate the help :slight_smile:

Hi, the /lib/firmware directory is only available at runtime, not at build time.

You will need to do it from your running container as explained above.

1 Like