Prepare, build and flash any openWRT device to run Heads Artefacts
What is OpenWrt?
OpenWrt is described as a Linux distribution for embedded devices. Instead of trying to create a single, static firmware, OpenWrt provides a fully writable filesystem with package management. This frees you from the application selection and configuration provided by the vendor and allows you to customize the device through the use of packages to suit any application. For developer, OpenWrt is the framework to build an application without having to build a complete firmware around it; for users this means the ability for full customization, to use the device in ways never envisioned.
We use in particular the lede project.
The LEDE project is a Linux-based, embedded meta-distribution based on OpenWrt, targeting a wide range of wireless SOHO routers and non-network devices. LEDE is an acronym for “Linux Embedded Development Environment”.
LEDE spun away from the mother project in May 2016, with goals of continuing to develop superior software in an open governance model and encouraging new developers to contribute to the development effort.
In this section, we will describe the different step to build a compatible firmware for the WG3526 router that has been chosen in one of the case study. The same kind of methodology can be followed for another device.
Preparing the docker environment to cross compile your firmware
First you need a docker image for crosscompiling lede firmware.
You can build it. The docker file is the following:
FROM ubuntu:16.04
RUN apt-get update -y && apt-get upgrade -y
RUN apt-get install git git-core build-essential libssl-dev libncurses5-dev unzip gawk file wget python svn
RUN git clone https://github.com/lede-project/source
RUN mv /opt/source /opt/lede
RUN cd /opt/lede
RUN ./scripts/feeds update -a
RUN ./scripts/feeds install -a
WORKDIR /opt/lede
CMD /bin/bash
You can build this image in creating a text file nammed Dockerfile. Put the following context and call the command
docker docker build -t barais/lede .
Next run the following command
docker run -ti barais/lede /bin/bash
#if you build your image
cd /opt/lede
Creating a new firmware
cd /opt/lede
make menuconfig
#select the correct devices.
#Select the package you need. You need at least nodejs and blockmount.
In particular, you need to remove support for /etc/fstab in
base system -> busybox -> custom busy box options -> Linux System Utilities -> Mount -> Support fstab and -a
You need also to include mount-utils
> Utilities -> mount-utils................................... related (u)mount utilities
and
> Utilities -> Disc blkid........................... locate and print block device attribute
Next configure the kernel
FORCE_UNSAFE_CONFIGURE=1 make kernel_menuconfig -j1 V=s
Select at least the option in the kernel
kernel FPU emulation.
Kernel Type --->
MIPS FPU EMULATOR Y
Do not forget to enable USBStorage NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'" "may also be needed; see USB_STORAGE Help for more information" Do not forget to enable ext4 and vfat in FS.
Device Drivers --->
SCSI device support --->
## (Although SCSI will be enabled automatically when selecting USB Mass Storage,
we need to enable disk support.)
--- SCSI support type (disk, tape, CD-ROM)
<*> SCSI disk support
## (Then move back a level and go into USB support)
USB support --->
## (This is the root hub and is required for USB support.
If you'd like to compile this as a module, it will be called usbcore.)
<*> Support for Host-side USB
## (Select at least one of the HCDs. If you are unsure, picking all is fine.)
--- USB Host Controller Drivers
<*> xHCI HCD (USB 3.0) support
<*> EHCI HCD (USB 2.0) support
< > OHCI HCD support
<*> UHCI HCD (most Intel and VIA) support
## (Moving a little further down, we come to CDC and mass storage.)
< > USB Modem (CDC ACM) support
<*> USB Printer support
<*> USB Mass Storage support
## (If you have a USB Network Card like the RTL8150, you'll need this)
USB Network Adapters --->
<*> USB RTL8150 based ethernet device support (EXPERIMENTAL)
## (If you have a serial to USB converter like the Prolific 2303, you'll need this)
USB Serial Converter support --->
<*> USB Serial Converter support
<*> USB Prolific 2303 Single Port Serial Driver (NEW)
## In most cases enabling RFCOMM, HIDP, HCI USB and/or HCI UART should be sufficient.
## It is also a good idea to enable the UHID (Userspace Human Interface Device) driver for Bluetooth input devices such as keyboards and mice.
## Tallying up the options: CONFIG_BT, BT_BREDR, CONFIG_BT_RFCOMM, CONFIG_BT_HIDP, BT_LE, CONFIG_BT_HCIBTUSB, CONFIG_BT_HCIUART, CONFIG_RFKILL, CONFIG_UHID
KERNEL Enable bluetooth support
[*] Networking support --->
<*> Bluetooth subsystem support --->
[*] Bluetooth Classic (BR/EDR) features
<*> RFCOMM protocol support
[ ] RFCOMM TTY support
< > BNEP protocol support
[ ] Multicast filter support
[ ] Protocol filter support
<*> HIDP protocol support
[*] Bluetooth High Speed (HS) features
[*] Bluetooth Low Energy (LE) features
Bluetooth device drivers --->
<*> HCI USB driver
<*> HCI UART driver
<*> RF switch subsystem support --->
Device Drivers --->
HID support --->
<*> User-space I/O driver support for HID subsystem
Do no forget to check in the config file that is unselected. For this specific device, there is a bug with sdcard reader; See https://dev.openwrt.org/changeset/49131
You have also to include the following packages: bluez-libs bluez-utils usbutils.
When you are happy with your current configuration, you can build the firmware.
make -j1 V=s
If there is some questions, please answer the missing configuration part. Next, take a big big coffee. When it finishes.
Copy the bin/targets/ramips/mt7621/*.bin into your host.
scp bin/targets/ramips/mt7621/*.bin user@172.17.0.1:~
Flash the router
Next connect the router to your laptop using an ethernet cable. For the WG3526, the easiest way to update the router locally is to use a pen or something to keep the reset button pressed when starting the router. Then, when your machine gets an IP (192.168.1.X), enter 192.168.1.1, click on the big button with chinese text and choose the firmware available in your home folder. It takes a couple of minutes to flash the router, but once it is done, the router will reboot and you should get a new IP adress 192.168.1.X and everything should be fine again.
You can login to the router through ssh.
ssh root@192.168.1.1
You can connect to the luci interface here login, admin no passwword.
Extend the filesystem on a USB key.
First thing you have to do is to extend the File system. Plug a USB key.
You can follow this tutorial
If you put blockmount in the default package and usb in the kernel, you don-t have to install them, else install them using.
opkg update ; opkg install block-mount
mount /dev/sda1 /mnt ; tar -C /overlay -cvf - . | tar -C /mnt -xf - ; umount /mnt
block detect > /etc/config/fstab; \
sed -i s/option$'\t'enabled$'\t'\'0\'/option$'\t'enabled$'\t'\'1\'/ /etc/config/fstab; \
sed -i s#/mnt/sda1#/overlay# /etc/config/fstab; \
cat /etc/config/fstab;
You'll end up with an fstab looking something like this:
config 'global'
option anon_swap '0'
option anon_mount '0'
option auto_swap '1'
option auto_mount '1'
option delay_root '5'
option check_fs '0'
config 'mount'
option target '/overlay'
option uuid 'c91232a0-c50a-4eae-adb9-14b4d3ce3de1'
option fstype 'ext4'
option enabled '1'
config 'swap'
option uuid '08b4f0a3-f7ab-4ee1-bde9-55fc2481f355'
option enabled '1'
config 'mount'
option target '/data'
option uuid 'c1068d91-863b-42e2-bcb2-b35a241b0fe2'
option enabled '1'
Check if it is mountable to overlay:
root@lede:~# mount /dev/sda1 /overlay
root@lede:~# df
Filesystem 1K-blocks Used Available Use% Mounted on
rootfs 896 244 652 27% /
/dev/root 2048 2048 0 100% /rom
tmpfs 14708 64 14644 0% /tmp
/dev/mtdblock6 7759872 477328 7221104 6% /overlay
overlayfs:/overlay 896 244 652 27% /
tmpfs 512 0 512 0% /dev
/dev/sda1 7759872 477328 7221104 6% /overlay
root@OpenWrt:~#
Note that only /overlay has grown but not the /
Reboot the router
Verify that the partitions were mounted properly: Next you can configure your router to be sure it is connected to internet.
Adding new packages
Just edit the file /etc/opkg/customfeeds.conf
vi /etc/opkg/customfeeds.conf
add the following line
src/gz newpackage http://downloads.lede-project.org/snapshots/packages/mipsel_24kc/packages/
next
opkg update
#to install node
opkg install wget
opkg install git
#Download the following file https://github.com/barais/WG3526Notes/blob/master/node_v4.4.5-1_mipsel_24kc.ipk?raw=true
# copy it on the router and next
opkg install --force-checksum node_v4.4.5-1_mipsel_24kc.ipk
#to install nano
opkg install nano
#to install mosquitto
opkg install mosquitto
Install KevoreeJS
Next you can do an update and install npm
npm update -g npm.
npm i -g grunt-cli
npm i -g bower
npm i -g generator-kevoree
npm i -g kevoree-cli
Install Kevoree NodeJS Runtime
Prefer a global install for this module as it is intended to be used that way:
npm i -g kevoree-cli
This will allow you to start a new Kevoree JavaScript runtime from the command-line by using:
$ kevoree
Usage
Usage documentation is available by using the -h flag:
$ kevoreejs -h
NB You can override the Kevoree registry your runtime uses by specifying two ENV VAR:
KEVOREE_REGISTRY_HOST=localhost KEVOREE_REGISTRY_PORT=9000 kevoreejs
Enjoy
Cross compiling node modules
Follow the tutorial to crosscompule some npm modules.
Openzwave
in your cross-compile docker container.
go to /opt/source
cd /opt/source
cd packages/libs
git clone https://github.com/cabal/openwrt
cd openwrt
mv openzwave ..
cd ..
rm -rf openwrt
cd ../..
make package/libs/openzwave/compile V=s
cd dl
wget http://old.openzwave.com/downloads/openzwave-1.2.919.tar.gz
cd ..
make menuconfig
#in libraries select now openzwave as module to get an ipkg
make -j1 V=s
in /opt/source/bin/targets/ramips/mt7621/packages you will get a file named openzwave_1.2.919-1_mipsel_24kc.ipk
just copy it and copy the libudev* on the router and install it.
opk install libudev_3.2-1_mipsel_24kc.ipk --force-checksum
opkg install openzwave_1.2.919-1_mipsel_24kc.ipk --force-checksum --force-depends
next you have to cross-compile openzwave-shared
It is not so easy to compile it.
You have to clone the openzwave-shared in your container.
Next you can patch the binding.gyp
The linux part should be something like that.
["OS=='linux'", {
"variables": {
"OZW_LIB_PATH" : "/opt/source/build_dir/target-mipsel_24kc_musl-1.1.15/openzwave-1.2.919/",
"OZW_INC" : "/opt/source/dl/openzwave-1.2.919/cpp/src/",
},
"defines": [
"OPENZWAVE_ETC=/usr/local/etc/openzwave",
"OPENZWAVE_DOC=/usr/local/share/doc/openzwave",
"OPENZWAVE_SECURITY=0"
],
"link_settings": {
"libraries": ["-lopenzwave"]
},
"include_dirs": [
"<!(node -p -e \"require('path').dirname(require.resolve('nan'))\")",
"<(OZW_INC)",
"<(OZW_INC)/value_classes"
],
"cflags": [ "-Wno-ignored-qualifiers -Wno-write-strings -Wno-unknown-pragmas" ],
}],
Next set the following envs variable
export CC=/opt/source/staging_dir/toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.15/bin/mipsel-openwrt-linux-gcc
export CXX=/opt/source/staging_dir/toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.15/bin/mipsel-openwrt-linux-g++
export STAGING_DIR=/opt/source/staging_dir
export PKG_CONFIG_PATH=/opt/source/build_dir/target-mipsel_24kc_musl-1.1.15/openzwave-1.2.919
export npm_config_arch=mips
# path to the node source that was used to create the cross-compiled version
export npm_config_nodedir=/opt/source/build_dir/target-mipsel_24kc_musl-1.1.15/node-v4.4.5/
Please install nodejs in version 4.4.5 in your docker container. You can do it using nvm.
next install the module
npm i -g node-gyp
in the folder where you clone node-openzwave-shared
npm install --unsafe-perm
next put the resulting folder in a node_modules and copy it to your global npm folder on the router.
Great, we can do a kevoree component that use this library.
node-usb, noble, bleno
I just prepare the pre-compiled libraries for noble and bleno.
You have to install the libusb ipk which is in this github repository. Copy it on the router, copy also the node-noble.tgz on the router.
Install the libusb-1.0_1.0.20-1_mipsel_24kc.ipk file.
opkg install --force-checksum libusb-1.0_1.0.20-1_mipsel_24kc.ipk
next uncompress the node-noble.tgz in /root and copy all the content of the node_module foler in /usr/lib/node_modules
cd ~
rm -rf node_modules
tar -czf node-noble.tgz
mv node_modules/* /usr/lib/node_modules
Just for information, to create this node_modules, I had to cross-compile the node-usb.
git clone --recursive https://github.com/nonolith/node-usb.git
cd node-usb
npm i
next edit the binding.gyp file.
-- 'use_system_libusb%': 'false',
++ 'use_system_libusb%': 'true',
-- ['use_system_libusb=="true"', {
-- 'include_dirs+': [
-- '<!@(pkg-config libusb-1.0 --cflags-only-I | sed s/-I//g)'
-- ],
-- 'libraries': [
-- '<!@(pkg-config libusb-1.0 --libs)'
-- ],
-- }],
++['use_system_libusb=="true"', {
++ 'include_dirs+': [
++ '/opt/source/build_dir/target-mipsel_24kc_musl-1.1.15/libusb-1.0.20/libusb/','/opt/source/staging_dir/target-mipsel_24kc_musl-1.1.15/usr/include/'
++ ],
++ 'libraries': [
++ '-lusb-1.0'
++ ],
++ }],
#link the libusb library
ln -s /opt/source/build_dir/target-mipsel_24kc_musl-1.1.15/libusb-1.0.20/ipkg-install/usr/lib/libusb-1.0.so /opt/source/staging_dir/toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.15/mipsel-openwrt-linux-musl/bin/../../../toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.15/lib/
#chck if ld can find it
/opt/source/staging_dir/toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.15/lib/gcc/mipsel-openwrt-linux-musl/5.4.0/../../../../mipsel-openwrt-linux-musl/bin/ld -lusb-1.0 --verbose
#Compile node-usb
export CC=/opt/source/staging_dir/toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.15/bin/mipsel-openwrt-linux-gcc
export CXX=/opt/source/staging_dir/toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.15/bin/mipsel-openwrt-linux-g++
export STAGING_DIR=/opt/source/staging_dir
export PKG_CONFIG_PATH=/opt/source/build_dir/target-mipsel_24kc_musl-1.1.15/openzwave-1.2.919
export npm_config_arch=mips
# path to the node source that was used to create the cross-compiled version
export npm_config_nodedir=/opt/source/build_dir/target-mipsel_24kc_musl-1.1.15/node-v4.4.5/
npm install --unsafe-perm
#prepare the package
rm -rf .git
cd ..
mv node-usb usb
mkdir test
cd test
mkdir node_modules
mv ../usb node_modules
mv node_modules/usb/node_modules/* node_modules
npm i bleno
npm i noble
#Great it works you can zip the test folder.