OpenWrt
As stated at the OpenWrt home site:
OpenWrt is described as a Linux distribution for embedded devices.
Based on the Linux kernel, this distribution is primarily used on devices to route network traffic due to the fact that it is born because the Linksys released the source code of the firmware for their WRT54G series of wireless routers under the GNU/GPL license (that's why, the WRT into the name). Then, other chipsets, manufacturers, and device types have been included in turning the initial project into a valid and rock-solid software product.
OpenWrt's main components are the Linux kernel, the uClibc (or musl) C library, and BusyBox. All components have been optimized for size in order to fit into very small memory devices (bare but functional OpenWrt footprint is around 4 MB!). This distribution is known as the best distribution for embedded networking devices.
The distribution has its building system based on a (modified) Buildroot system that automates the building process, thanks to a set of makefiles and patches. The main tool used to manage the distribution is make
.
Note
More information on the OpenWrt distribution can be retrieved from the project's home page at: https://openwrt.org .
In the upcoming sections, we will build a minimal image from scratch, and then, we'll show you how you can add some included packages and how to add a new (and simple) package in order to expand the distribution.
Using the default configuration
To install the base system for our SAMA5D3 Xplained board, we can use the OpenWrt default configuration we will show here. However, as the first step, we need to download the sources. This can be done with the git
command as follows:
$ git clone git://git.openwrt.org/15.05/openwrt.git
Then move into the just created openwrt
directory and execute the configuration menu as below:
$ cd openwrt $ make menuconfig
It may happen that the command ends with an error:
Build dependency: Please install zlib. (Missing libz.so or zlib.h) Build dependency: Please install the openssl library (with development headers) Build dependency: Please install GNU 'awk' Build dependency: Please install the Subversion client /home/giometti/A5D3/openwrt/include/prereq.mk:12: recipe for target 'p rereq' failed Prerequisite check failed. Use FORCE=1 to override. /home/giometti/A5D3/openwrt/include/toplevel.mk:140: recipe for target 'staging_dir/host/.prereq-build' failed make: *** [staging_dir/host/.prereq-build] Error 1
In this case, we have to manually add all missing dependencies to be able to compile our new OpenWrt distribution, so in the preceding error, our host PC tells us that several packages are missing. Then, we have to install them using the following command:
$ sudo aptitude install libz-dev libssl-dev gawk subversion
Tip
How we can deduce the missing packages' names from the output of the preceding configuration command is not a an act of magic, but we used the package management tools of the Ubuntu/Debian OS described at Chapter 2 , Managing the System Console, in Packages management section.
Then, we can relaunch the command and, if all packages are in place, we should get a configuration menu similar to the one we got during the kernel configuration in Chapter 1 , Installing the Developing System, in SAMA5D3 Xplained section. Now, we must select our SAMA5D3 Xplained board by setting Atmel AT91 in the Target System entry, SAMA5D3 (Cortex-A5) for the Subtarget entry, and Atmel AT91SAMA5D3XPLAINED in Target Profile, as shown in the following screenshot:
Before starting the compilation, we need to do a little patch at the OpenWrt sources. In fact, by default, the system will generate a single file for both the SAMA5D3 Xplained's kernel image and the DTB configuration file (the DTB file is actually appended to the kernel image), but since we want two separate files, in order to flash them into their matching MTD partitions, we must apply the following patch:
--- a/target/linux/at91/image/Makefile +++ b/target/linux/at91/image/Makefile @@ -50,7 +50,7 @@ Image/Build/Kernel/AT91SAM9G35EK=$(call MkuImageDtb, 9g35ek,at91sam9g35ek) Image/Build/Kernel/AT91SAM9M10G45EK=$(call MkuImageDtb,9m10g45ek,at91 sam9m10g45ek) Image/Build/Kernel/AT91SAM9X25EK=$(call MkuImageDtb,9x25ek,at91sam9x2 5ek) Image/Build/Kernel/AT91SAM9X35EK=$(call MkuImageDtb,9x35ek,at91sam9x3 5ek) -Image/Build/Kernel/AT91SAMA5D3XPLAINED=$(call MkuImageDtb,sama5,at91- sama5d3_xplained) +Image/Build/Kernel/AT91SAMA5D3XPLAINED=$(call MkOftree,sama5,at91-sam a5d3_xplained) # CalAmp Image/Build/Kernel/LMU5000=$(call MkuImageDtb,lmu5000,lmu5000) # Calao
Now, we are ready, so let's launch the compilation using the following make
command:
$ make make[1] world make[2] toolchain/install make[3] -C toolchain/gdb prepare make[3] -C toolchain/gdb compile make[3] -C toolchain/gdb install ...
Note
The compilation is very time consuming, so you should consider to take your time to have your preferred coffee! If we got some error, we can use the following command line to enable all compilation messages and force just one task to see what caused the error:
$ make -j1 V=s
In any case, we can use only the V=s
settings to normally compile the system, but enabling all messages in order to see what's happening.
When the compilation has finished, we should get the following messages:
... make[2] package/install make[3] package/preconfig make[2] target/install make[3] -C target/linux install make[2] package/index $
Now, we can see the compilation results under the bin/at91/
directory as shown here:
$ cd bin/at91/ $ ls md5sums openwrt-at91-sama5d3-AT91SAMA5D3XPLAINED-rootfs.tar.gz openwrt-at91-sama5d3-root.ext4 openwrt-at91-sama5d3-root.jffs2-128k openwrt-at91-sama5d3-root.jffs2-64k openwrt-at91-sama5d3-root.ubi openwrt-at91-sama5d3-root.ubifs openwrt-at91-sama5d3-sama5-oftree.dtb openwrt-at91-sama5d3-sama5-uImage openwrt-at91-sama5d3-uImage openwrt-at91-sama5d3-zImage packages sha256sums
The files we have to move to the SAMA5D3 Xplained are:
- file
openwrt-at91-sama5d3-zImage
- the kernel, - file
openwrt-at91-sama5d3-sama5-oftree.dtb
- the DTB and - file
openwrt-at91-sama5d3-root.ubi
- the rootfs.
The following command will copy all these files into a dedicated directory of our embedded board:
$ scp openwrt-at91-sama5d3-zImage openwrt-at91-sama5d3-sama5-oftree.dtb openwrt-at91-sama5d3-root.ubi root@192.168.8.2:nand/
Tip
Note that the nand
directory must be already present into the SAMA5D3 Xplained root user's home directory.
Now, we have to compile the bootloader. The OpenWrt has the possibility to do it for us, but this option seems disabled for our board! Then, keep calm and remember that we already compiled the SAMA5D3 Xplained's bootloader into Chapter 1 , Installing the Developing System, in SAMA5D3 Xplained section. We can now redo the same steps, but this time, with two major differences:
- We have to use the
sama5d3_xplained_nandflash_defconfig
target in order to compile our U-Boot image for the NAND flash. - We have to write the result image into the flash itself.
Let's see one step at time. First of all, we have to go into the directory we used to download the U-Boot's source code and reconfigure it for the NAND flash:
$ cd A5D3/u-boot $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- sama5d3_xplained_nandflash_defconfig # # configuration written to .config #
Then, we have to re-compile it with the usual command:
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
Again, the two bootloaders image files boot.bin
and u-boot.img
(the board has two bootloaders remember? See Chapter 1 , Installing the Developing System, in SAMA5D3 Xplained section) are created, but this time, they are suitable to be used on the NAND instead of on the microSD. So, let's place them on the SAMA5D3 Xplained into the dedicated directory as we did earlier:
$ scp boot.bin u-boot.img root@192.168.8.2:nand/
Now, under the /root/nand
directory on the SAMA5D3 Xplained, we should have all the needed files, and then, we have only to write them into the NAND flash to have a running OpenWrt system. However, before continuing, you should notice that we used the kernel and the rootfs from OpenWrt while the bootloaders have been generated outside OpenWrt! This fact can lead to some misconfigurations that can produce an unbootable system. The problem is about the flash partitioning. In fact, we must be sure that we write all data into the correct place. Let's see how.
Since we will use our Debian OS to set up the OpenWrt image files, we must check the current partitioning. This can be done with the following command:
root@a5d3:~# cat /proc/mtd dev: size erasesize name mtd0: 00040000 00020000 "at91bootstrap" mtd1: 00080000 00020000 "bootloader" mtd2: 000c0000 00020000 "bootloader env" mtd3: 00080000 00020000 "device tree" mtd4: 00600000 00020000 "kernel" mtd5: 0f800000 00020000 "rootfs"
The preceding output states a NAND partitioning as reported into the following table:
In this scenario, we must be sure that:
- U-Boot will load the kernel and the DTB file at the right positions.
- the kernel has a compatible setting, that is, the rootfs must be placed into a partition from offset
0x00800000
and 248 MB length at maximum.
These settings must be done into the U-Boot, so we have to stop it the first time we try to execute our OpenWrt to check the current U-Boot's configuration. On the other hand, we are quite sure that boot.bin
will safely load u-boot.img
due to the fact that they derive from the same compilation and that the former has the correct settings to do it.
Tip
You can verify it by looking at the CONFIG_SYS_NAND_U_BOOT_OFFS
value in the include/configs/sama5d3_xplained.h
file in the U-Boot's repository.
OK, let's start by flashing the bootloaders, erasing the mtd2
partition, just to be sure to work with a void-saved environment:
root@a5d3:~# flash_erase -q /dev/mtd0 0 0 root@a5d3:~# flash_erase -q /dev/mtd1 0 0 root@a5d3:~# flash_erase -q /dev/mtd2 0 0 root@a5d3:~# nandwrite -q -m -p /dev/mtd0 nand/boot.bin root@a5d3:~# nandwrite -q -m -p /dev/mtd1 nand/u-boot.img
Then, we can flash the DTB and the kernel images:
root@a5d3:~/nand# flash_erase -q /dev/mtd3 0 0 root@a5d3:~/nand# flash_erase -q /dev/mtd4 0 0 root@a5d3:~# nandwrite -q -m -p /dev/mtd3 nand/openwrt-at91-sama5d3-sa ma5-oftree.dtb root@a5d3:~# nandwrite -q -m -p /dev/mtd4 nand/openwrt-at91-sama5d3-zI mage
And the last step is the rootfs image. However, this time, we cannot use the nandwrite
utility due to the fact that it doesn't properly format the flash partition for UBIFS. To do this, we have to use the ubiformat
as reported here:
root@a5d3:~# flash_erase -q /dev/mtd5 0 0 root@a5d3:~# ubiformat /dev/mtd5 -s 2048 -O 2048 -f nand/openwrt-at91-sama5d3-root.ubi
Now, we have to stop the system with the halt
command, and then, we must remove the microSD and press the reset button (see Chapter 1 , Installing the Developing System, in SAMA5D3 Xplained section). If everything works well, we should see the following messages on the serial console:
RomBOOT U-Boot SPL 2016.03-dirty (Jun 15 2016 - 16:19:44) Trying to boot from NAND U-Boot 2016.03-dirty (Jun 15 2016 - 16:19:44 +0200) CPU: SAMA5D36 Crystal frequency: 12 MHz CPU clock : 528 MHz Master clock : 132 MHz DRAM: 256 MiB NAND: 256 MiB MMC: mci: 0 *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial Net: gmac0 Error: gmac0 address not set. , macb0 Error: macb0 address not set. Hit any key to stop autoboot: 1
We have to be quick and stop the autoboot by pressing a key, and then, we can show the U-Boot environment:
=> print arch=arm baudrate=115200 board=sama5d3_xplained board_name=sama5d3_xplained bootargs=console=ttyS0,115200 earlyprintk mtdparts=atmel_nand:256k(boo tstrap)ro,512k(uboot)ro,256K(env),256k(env_redundent),256k(spare),512k (dtb),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=7 root=ubi0:root fs bootcmd=nand read 0x21000000 0x180000 0x80000;nand read 0x22000000 0x2 00000 0x600000;bootz 0x22000000 - 0x21000000 bootdelay=1 cpu=armv7 ethact=gmac0 soc=at91 vendor=atmel Environment size: 484/131067 bytes
The relevant settings here are in the bootcmd
and bootargs
variables. The first variable defines the commands to load the kernel and the DTB file, and they are correct, while bootargs
defines a slightly different settings regarding the UBIFS settings (ubi.mtd
) and the flash partitioning for the kernel (mtdparts
), so they must be fixed up. Recalling the preceding table, the correct values per the mtdparts
and ubi.mtd
settings are shown here:
mtdparts=atmel_nand:256k(at91bootstrap)ro,512k(bootloader)ro,768K(boot loader env),512k(device tree),6M(kernel)ro,-(rootfs) ubi.mtd=5
So, we can use the setenv
command to do the job:
=> setenv bootargs 'console=ttyS0,115200 earlyprintk mtdparts=atmel_na nd:256k(at91bootstrap)ro,512k(bootloader)ro,768K(bootloader env),512k( device tree),6M(kernel)ro,-(rootfs) rootfstype=ubifs ubi.mtd=5 root=ub i0:rootfs rw'
Note
The usage of the '
character to delimit the variable content!
Then, we can save the new environment with the saveenv
command:
=> saveenv Saving Environment to NAND... Erasing redundant NAND... Erasing at 0x100000 -- 100% complete. Writing to redundant NAND... OK
Now, everything is in place, and we can safely reset the system:
=> reset resetting ... RomBOOT
U-Boot SPL 2016.03-dirty (Jun 15 2016 - 16:19:44) Trying to boot from NAND
U-Boot 2016.03-dirty (Jun 15 2016 - 16:19:44 +0200)
CPU: SAMA5D36 Crystal frequency: 12 MHz CPU clock : 528 MHz Master clock : 132 MHz DRAM: 256 MiB NAND: 256 MiB MMC: mci: 0 In: serial Out: serial Err: serial Net: gmac0 Error: gmac0 address not set. , macb0 Error: macb0 address not set.
Hit any key to stop autoboot: 0
NAND read: device 0 offset 0x180000, size 0x80000 524288 bytes read: OK NAND read: device 0 offset 0x200000, size 0x600000 6291456 bytes read: OK Kernel image @ 0x22000000 [ 0x000000 - 0x155680 ] ## Flattened Device Tree blob at 21000000 Booting using the fdt blob at 0x21000000 Loading Device Tree to 2fadc000, end 2fae6abc ... OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel. [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Linux version 3.18.29 (giometti@ubuntu1510) (gcc versio n 4.8.3 (OpenWrt/Linaro GCC 4.8-2014.04 r49378) ) #2 Wed Jun 15 16:07: 48 CEST 2016 [ 0.000000] CPU: ARMv7 Processor [410fc051] revision 1 (ARMv7), cr= 10c53c7d [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache [ 0.000000] Machine model: SAMA5D3 Xplained [ 0.000000] Memory policy: Data cache writeback [ 0.000000] AT91: Detected soc type: sama5d3 [ 0.000000] AT91: Detected soc subtype: sama5d36 ...
Great! The kernel has been correctly loaded, and now, we should wait until the rootfs is mounted:
... [ 1.850000] UBIFS: mounted UBI device 0, volume 0, name "rootfs", R /O mode [ 1.850000] UBIFS: LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes [ 1.860000] UBIFS: FS size: 244936704 bytes (233 MiB, 1929 LEBs), j ournal size 9023488 bytes (8 MiB, 72 LEBs) [ 1.870000] UBIFS: reserved for root: 0 bytes (0 KiB) [ 1.880000] UBIFS: media format: w4/r0 (latest is w4/r0), UUID E598 066D-054B-44EB-BD77-EF8321F5F8A7, small LPT model [ 1.920000] VFS: Mounted root (ubifs filesystem) readonly on device 0:10. [ 1.920000] Freeing unused kernel memory: 136K (c0396000 - c03b8000 ) [ 2.230000] init: Console is alive ...
OK! The rootfs has been correctly mounted, so it's time to wait for the console login message:
... [ 3.250000] init: - preinit - /etc/preinit: .: line 1: can't open '/lib/at91.sh' [ 3.400000] procd: - early - [ 4.070000] procd: - ubus - [ 5.100000] procd: - init - Please press Enter to activate this console.
We got it! Now, if we strike the Enter key, we get the following message:
BusyBox v1.23.2 (2016-06-15 13:48:20 CEST) built-in shell (ash) _______ ________ __ | |.-----.-----.-----.| | | |.----.| |_ | - || _ | -__| || | | || _|| _| |_______|| __|_____|__|__||________||__| |____| |__| W I R E L E S S F R E E D O M ----------------------------------------------------- CHAOS CALMER (Chaos Calmer, r49378) ----------------------------------------------------- * 1 1/2 oz Gin Shake with a glassful * 1/4 oz Triple Sec of broken ice and pour * 3/4 oz Lime Juice unstrained into a goblet. * 1 1/2 oz Orange Juice * 1 tsp. Grenadine Syrup ----------------------------------------------------- root@OpenWrt:/#
Before ending the paragraph, let me show you the actual flash memory occupation:
root@OpenWrt:/# df -h Filesystem Size Used Available Use% Mounted on rootfs 215.4M 2.1M 213.3M 1% / ubi0:rootfs 215.4M 2.1M 213.3M 1% / tmpfs 124.9M 56.0K 124.8M 0% /tmp tmpfs 512.0K 0 512.0K 0% /dev
Around 2MB, so cute!
Adding a (quasi) LAMP system
As you can easily verify using the just created OpenWrt distribution, its base system is very small and it's also quite useless. That's why we will show you how you can add a (quasi) LAMP system. In fact, we will install a lighttpd web server (that's why, the quasi word) with PHP support and a MySQL server.
To do our job, we should consider that the OpenWrt supports the feeds. They are external repositories based on git repositories useful to add additional packages without touching the main distribution. The feeds are managed by the feeds
command placed in the scripts
directory. So, first of all, we have to update all feeds' repositories with this command:
$ ./scripts/feeds update -a
Then, we can use the next command to search for the package holding the lighttpd web server:
$ ./scripts/feeds search lighttpd Search results in feed 'packages': lighttpd A flexible and lightweight web server ... lighttpd-mod-cgi CGI module lighttpd-mod-cml Cache Meta Language module lighttpd-mod-compress Compress output module lighttpd-mod-evasive Evasive module lighttpd-mod-evhost Exnhanced Virtual-Hosting module lighttpd-mod-expire Expire module lighttpd-mod-extforward Extract client module lighttpd-mod-fastcgi FastCGI module ...
Then, to install it (belong other useful modules, we can use the following command:
$ ./scripts/feeds install lighttpd lighttpd-mod-cgi lighttpd-mod-fastcgi
For the PHP language, we can do the same:
$ ./scripts/feeds search php5 Search results in feed 'packages': php5 PHP5 Hypertext preprocessor php5-cgi PHP5 Hypertext preprocessor (CGI & FastCGI) php5-cli PHP5 Hypertext preprocessor (CLI) php5-fastcgi FastCGI startup script ... php5-mod-mysql MySQL shared module php5-mod-mysqli MySQL Improved Extension shared module php5-mod-opcache OPcache shared module php5-mod-openssl OpenSSL shared module php5-mod-pcntl PCNTL shared module php5-mod-pdo PHP Data Objects shared module php5-mod-pdo-mysql PDO driver for MySQL shared module php5-mod-pdo-pgsql PDO driver for PostgreSQL shared module php5-mod-pdo-sqlite PDO driver for SQLite 3.x shared module ...
Then, the installation command can be as follows:
$ ./scripts/feeds install php5 php5-cgi php5-cli php5-fastcgi php5-mod-mysql php5-mod-mysqli php5-mod-pdo-mysql
Now, we know the trick, so for MySQL, the commands are as follows:
$ ./scripts/feeds search mysql Search results in feed 'packages': freeradius2-mod-sql-mysql MySQL module libdbd-mysql MySQL database server driver for libdbi libmysqlclient MySQL client library libmysqlclient-r MySQL client library threadsafe libzdb A thread-safe multi database connection poo l library lighttpd-mod-mysql_vhost Mysql virtual hosting module luasql-mysql Lua SQL binding for MySQL mysql-server MySQL Server php5-mod-mysql MySQL shared module php5-mod-mysqli MySQL Improved Extension shared module php5-mod-pdo-mysql PDO driver for MySQL shared module ... $ ./scripts/feeds install libmysqlclient libmysqlclient-r mysql-server
Now, we have to enable the compilation of these new packages, and in order to do it, we have to re-execute the make menuconfig
command. Then, when the configuration menu appears, we have to choose the entry Network and then Web Servers/Proxies and then enable the lighttpd entry. Hit the Enter key on that entry to enter into the lighttpd menu where we have to select lighttpd-mod-cgi and lighttpd-mod-fastcgi as shown in the following screenshot:
Tip
Note that instead of the Linux configuration menu you saw into Chapter 1 , Installing the Developing System, Linux kernel for SAMA5D3 Xplained, this menu has a slightly different meaning for packages selection (even if they look like the same). In the Linux menu, a kernel component is selected as built-in with an *
character, while we select it as module with an M
. In this menu, using an M
character, we select the program for compilation and packaging only. In other words, we get the program's package in the bin/at91/packages
directory only, while using *
, we select the program to be placed in the final rootfs image too.
Then, to enable the PHP support, we must go back to the main menu, then select the Languages entry, and then enter into the PHP entry. Then, we have to enable the PHP language support as built-in, and we must enable the PHP plugins for CGI and MySQL, as shown in the following screenshot:
The last settings are for MySQL, so let's go back to the main menu and select the Utilities entry, then database, and just enable the mysql-server entry as built-in.
That's all! Now, we have to re-execute the make
command and wait for the end of the compilation. When finished, we'll get a new kernel and a new image to be flashed as shown earlier. So, we have to restart our Debian on the SAMA5D3 Xplained, and then erase and flash the kernel and rootfs filesystem's partitions using the following commands:
root@a5d3:~# flash_erase -q /dev/mtd3 0 0 root@a5d3:~# flash_erase -q /dev/mtd4 0 0 root@a5d3:~# flash_erase -q /dev/mtd5 0 0 root@a5d3:~# nandwrite -q -m -p /dev/mtd3 nand/openwrt-at91-sa ma5d3-sama5-oftree.dtb root@a5d3:~# nandwrite -q -m -p /dev/mtd4 nand/openwrt-at91-sa ma5d3-zImage root@a5d3:~# nandwrite -q -m -p /dev/mtd5 nand/openwrt-at91-sa ma5d3-root.ubi
Now, just restart the system, and the new OpenWrt image should start as before, This time, we can see that it's slightly bigger (even if is still really small, less than 9MB):
root@OpenWrt:/# df -h Filesystem Size Used Available Use% Mounted on rootfs 215.4M 8.7M 206.7M 4% / ubi0:rootfs 215.4M 8.7M 206.7M 4% / tmpfs 124.9M 64.0K 124.8M 0% /tmp tmpfs 512.0K 0 512.0K 0% /dev
To get access to the internal web server, we have to set up the networking settings. The default configuration can be retrieved by looking at the /etc/config/network
file:
root@OpenWrt:/# cat /etc/config/network config interface loopback option ifname lo option proto static option ipaddr 127.0.0.1 option netmask 255.0.0.0 config interface lan option ifname eth0 option type none option proto static option ipaddr 192.168.1.1 option netmask 255.255.255.0 config interface debug option ifname usb0 option type none option proto static option ipaddr 172.18.0.18 option netmask 255.255.255.0
We see that only one Ethernet device is configured and also the usb0
device is present, but with a different configuration than our Debian. We can choose several solutions. However we decided to set up the eth0
network device with DHCP, so the relative new settings are shown here:
config interface lan option ifname eth0 option type none option proto dhcp
When all our networking settings are in place, we have to restart the networking systems using the following command:
root@OpenWrt:/# /etc/init.d/network restart [ 1225.880000] macb f0028000.ethernet eth0: link down [ 1227.490000] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready [ 1227.880000] macb f0028000.ethernet eth0: link up (100/Full) [ 1227.880000] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
Great, now, we can see our new IP address with the usual ifconfig
command:
root@OpenWrt:/# ifconfig eth0 eth0 Link encap:Ethernet HWaddr C6:4C:E4:F8:C4:11 inet addr:192.168.32.51 Bcast:192.168.32.255 Mask:255.255.2 55.0 inet6 addr: fe80::c44c:e4ff:fef8:c411/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:4212 errors:0 dropped:0 overruns:0 frame:0 TX packets:4137 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:376053 (367.2 KiB) TX bytes:424302 (414.3 KiB) Interrupt:49 Base address:0x8000
OK, now, let's check the lighttpd default configuration in the /etc/lighttpd/lighttpd.conf
file as shown here:
root@OpenWrt:/# cat /etc/lighttpd/lighttpd.conf server.modules = ( ) server.document-root = "/www" server.upload-dirs = ( "/tmp" ) server.errorlog = "/var/log/lighttpd/error.log" server.pid-file = "/var/run/lighttpd.pid" server.username = "http" server.groupname = "www-data" index-file.names = ( "index.php", "index.html", "index.htm", "default.htm", "index.lighttpd.html" ) static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" ) ...
Our web server seems OK. However, you should notice that the default root directory is /www
rather than /var/www
as for Debian. Then, we have to verify the CGI support configuration, which is placed in the /etc/lighttpd/conf.d/30-cgi.conf
file:
root@OpenWrt:/# cat /etc/lighttpd/conf.d/30-cgi.conf ####################################################################### ## ## CGI modules ## --------------- ## ## http://www.lighttpd.net/documentation/cgi.html ## server.modules += ( "mod_cgi" ) ## ## Plain old CGI handling ## ## For PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini. ## cgi.assign = ( ".pl" => "/usr/bin/perl", ".cgi" => "/usr/bin/perl", ".rb" => "/usr/bin/ruby", ".erb" => "/usr/bin/eruby", ".py" => "/usr/bin/python" ) ...
Nope, this time, we need to apply the following patch since the .php
extension is missing in the cgi.assign
array:
--- /etc/lighttpd/conf.d/30-cgi.conf.orig 2016-06-19 11:16:12.930534015 +0200 +++ /etc/lighttpd/conf.d/30-cgi.conf 2016-06-19 11:15:18.686718936 +0200 @@ -16,6 +16,7 @@ ".cgi" => "/usr/bin/perl", ".rb" => "/usr/bin/ruby", ".erb" => "/usr/bin/eruby", + ".php" => "/usr/bin/php-cgi", ".py" => "/usr/bin/python" ) ##
After the modifications are in place, let's restart the server:
root@OpenWrt:/# /etc/init.d/lighttpd restart
Then, we have to point our web browser at the IP address of our SAMA5D3 Xplained board, and we should see something similar to the following screenshot:
Now, it's time to verify the MySQL, and we can try the usual command line to log in as MySQL's root user:
root@OpenWrt:/# mysql -u root ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld.sock' (2)
Tip
The preceding command and the following ones are typical commands used to manage the MySQL from the command line. You can refer to Chapter 4, Quick Programming with Scripts and System Daemons, MySQL or to the online documentation of The MySQL Command-Line Tool at: http://dev.mysql.com/doc/refman/5.7/en/mysql.html to get more information on these commands.
The database is not running, so let's try to restart the daemon to see what's wrong:
root@OpenWrt:/# /etc/init.d/mysqld start /etc/init.d/mysqld: Error: datadir '/mnt/data/mysql/' in /etc/my.cnf doesn't exist
This is a typical error due the fact that, by default, MySQL takes as datadir
the /mnt/data/mysql/
directory, which is usually mounted on a separate filesystem (usually, a microSD storage). No problem. We can change the configuration in the /etc/my.cnf
file, so we can take a look at that file where we notice the following warnings:
[client] port = 3306 socket = /var/run/mysqld.sock [mysqld] user = root socket = /var/run/mysqld.sock port = 3306 basedir = /usr ############ Don't put this on the NAND ############# # Figure out where I are going to put the databases # And run mysql_install_db --force datadir = /mnt/data/mysql/ ######### This should also not go on the NAND ####### tmpdir = /mnt/data/tmp/ ...
This is because the system heavily uses these directories for disk I/O activity, but since our system has nothing other than NAND, we have no choices (usually, these directories are pointing at an external filesystem on microSD or USB key. However, don't forget that also those devices are based on NAND flashes!). So, a reasonable solution for these directories' settings can be as follows:
datadir = /var/data/mysql/ tmpdir = /tmp/
Then, as suggested earlier, we have to execute mysql_install_db
as shown here:
root@OpenWrt:/# mysql_install_db --force Installing MySQL system tables... OK Filling help tables... OK To start mysqld at boot time you have to copy support-files/mysql.server to the right place for your system PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER ! To do so, start the server, then issue the following commands: /usr/bin/mysqladmin -u root password 'new-password' /usr/bin/mysqladmin -u root -h OpenWrt password 'new-password' Alternatively you can run: /usr/bin/mysql_secure_installation which will also give you the option of removing the test databases and anonymous user created by default. This is strongly recommended for production servers. See the manual for more instructions. You can start the MySQL daemon with: cd /usr ; /usr/bin/mysqld_safe & You can test the MySQL daemon with mysql-test-run.pl cd /usr/mysql-test ; perl mysql-test-run.pl Please report any problems with the /usr/scripts/mysqlbug script!
Now, the starting command that failed before should now work without any errors:
root@OpenWrt:/# /etc/init.d/mysqld start
Then, we can retry the root login as we did earlier:
root@OpenWrt:/# mysql -u root Welcome to the MySQL monitor. Commands end with ; or g. Your MySQL connection id is 1 Server version: 5.1.73 Source distribution Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or 'h' for help. Type 'c' to clear the current input statement. mysql>
OK, everything is working, so let's try a little demo with our new (quasi) LAMP system. However, before starting, it is better to add a password for MySQL's root user. So, use the quit
command to exit from the previous tools and execute the following command:
root@OpenWrt:/# mysqladmin -u root password 'myroot'
Note
In the preceding command, we used the myroot
password, but of course, you can choose whatever you want in order to fit your needs.
Since now, to log in to MySQL from the command line, we must use the following command and then insert the new password when asked for:
root@OpenWrt:/# mysql -u root -p
Now, we have to copy the chapter_05/phpdemo/demo_init.sh
and chapter_05/phpdemo/demo_set.sh
files from the book's example code repository to the /root
directory on our SAMA5D3 Xplained:
$ scp demo_init.sh demo_set.sh root@192.168.32.51:/root/
Then, still from the same repository, the chapter_05/phpdemo/demo_dump.php
file in the /www
directory:
$ scp demo_dump.php root@192.168.32.51:/www/
Tip
It may happen that the scp
command will not accept any root password and then refuse to copy the files. In this case, we have to reset the root's password using the passwd
command:
root@OpenWrt:/# passwd Changing password for root Enter the new password (minimum of 5, maximum of 8 characters) Please use a combination of upper and lower case le tters and numbers. New password: Re-enter new password: passwd: password changed.
Then, redo the command.
Then, we can set up the demo
database using the demo_init.sh
command:
root@OpenWrt:~# ./demo_init.sh Warning, all data will be dropped!!! [CTRL-C to stop or ENTER to continue] Enter password:
Of course we have to enter here the MySQL root's password we set up before. Once the database has been set up we have only to add data to it and the command to do it is shown below:
root@OpenWrt:~# ./demo_set.sh temp 21.5
Tip
These commands are quite similar to the ones used in Chapter 4 , Quick Programming with Scripts and System Daemons, in MySQL in Bash section, so you can refer to those pages to know how the commands are functioning.
Now, to display the data, we have only to point our web browser to the demo_dump.php
file at SAMA5D3 Xplained's IP address, and the result is reported in the next screenshot:
Of course, if we add new data and then reload the page, we'll get different results:
root@OpenWrt:~# ./demo_set.sh lamp on
Tip
You should take a look at the demo_dump.php
file since it's quite similar to the my_dump.php
file presented in Chapter 4 , Quick Programming with Scripts and System Daemons, in MySQL in PHP section, where we used the standard PHP's mysql API. However, in demo_dump.php
, we used the newest mysqli API, which is going to supersede the old one in few releases.
Adding a custom package
As the last example on OpenWrt, let's see how we can add a new package to our new system. We'll use the famous Hello World example, and we'll see how we can add it into our current distribution and how we can install it on our running system.
The trick is to create a new feed named applications
where we can put all our new programs. So, let's create a new directory named helloworld
within applications
as shown here:
$ cd A5D3/ $ mkdir -p applications/helloworld $ cd applications/helloworld/
Then, we have to create Makefile
where we will define our new applications to be added to OpenWrt:
include $(TOPDIR)/rules.mk # Define package's name, version, release and the default package's # build directory. PKG_NAME:=helloworld PKG_VERSION:=1.0.0 PKG_RELEASE:=1 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) include $(INCLUDE_DIR)/package.mk # Define package's section and category inside the OpenWRT system. # These information are used to manage the package and to display # it inside the comfiguration menu define Package/$(PKG_NAME) SECTION:=apps CATEGORY:=Applications TITLE:=The Hello World program MAINTAINER:=Rodolfo Giometti <giometti@hce-engineering.com> endef # Define package's description (long version) define Package/$(PKG_NAME)/description This package holds a program that display the "hello world" message endef # Set up the build directory in order to be use by the compilation # stage. # Our data are not downloaded from a remote site by we have them # already into the "src" directory, so let's copy them accordingly define Build/Prepare mkdir -p $(PKG_BUILD_DIR) $(CP) ./src/* $(PKG_BUILD_DIR)/ endef # Define the package's installation steps after the compilation # stage has done define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/usr/bin $(CP) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/bin endef # The OpenWRT's main entry $(eval $(call BuildPackage,$(PKG_NAME)))
Note
The preceding code can be found in the chapter_05/openwrt-helloworld/Makefile
file in the book's example code repository.
The content of the file is quite self-explicative. However, the reader should notice that everything is defined using several make
macros. The OpenWrt system already has some default macros for the main building steps: downloading, compilation, installation, and so on. Our job is to integrate these default macros with our own ones in order to do the correct steps to build the new package inside the distribution.
Tip
For further information on these topics, you can take a look at: https://wiki.openwrt.org/doc/devel/packages?s[]=define&s[]=package .
Then, we have to create a src
directory where we can put our code:
$ mkdir src/ $ cd src/ $ ls helloworld.c Makefile
The two files Makefile
and helloworld.c
are obviously the makefile useful to compile the usual helloworld.c
C program.
Note
The preceding files can be found in the chapter_05/openwrt-helloworld/src/
directory in the book's example code repository.
When finished, the tree layout of our new feed looks like this:
$ tree applications applications \-- helloworld +-- Makefile \-- src +-- helloworld.c \-- Makefile 2 directories, 3 files
OK, now, we can come back to the OpenWrt root directory and then modify the feeds.conf
file as shown here:
--- a/feeds.conf.default +++ b/feeds.conf.default @@ -12,4 +12,4 @@ src-git management https://github.com/ openwrt-management/packages.git;for-15.05 #src-svn desktop svn://svn.openwrt.org/openwrt/feeds/desktop #src-svn xfce svn://svn.openwrt.org/openwrt/feeds/xfce #src-svn lxde svn://svn.openwrt.org/openwrt/feeds/lxde -#src-link custom /usr/src/openwrt/custom-feed +src-link applications /home/giometti/A5D3/applications
Tip
Note that /home/giometti/A5D3/applications
is relative to my configuration, but you have to fix it up to suit your needs.
Now, we have to update our new repository by adding the new feed:
$ ./scripts/feeds update applications Updating feed 'applications' from '/home/giometti/Projects/A5D3/openwrt/applications' ... Create index file './feeds/applications.index' Collecting package info: done Collecting target info: done
Then, we can verify that the new package is now available under the new feed:
$ ./scripts/feeds search hello Search results in feed 'applications': helloworld The Hello World program
Then, to install the new helloworld
package, we can use the following command:
$ ./scripts/feeds install -f helloworld Overriding package 'helloworld'
Tip
Note that the -f
option argument can be necessary if a package with the same name is already present.
Now, if we execute the make menuconfig
command again, a new entry labeled Applications should be present in the configuration menu. Just select it and then enable our new helloworld
program as shown in the following screenshot:
Great! Now, we can use the make
command again to compile our new package or, just to avoid a long wait, we can use these commands to compile the program and then install it respectively:
$ make package/helloworld/compile make[1] package/helloworld/compile make[2] -C package/libs/toolchain compile make[2] -C /home/giometti/A5D3/applications/helloworld compile $ make package/helloworld/install make[1] package/helloworld/install make[2] -C /home/giometti/A5D3/applications/helloworld install
We can now reflash the system, but we can just install the new package into our running system! In fact, we should find a new package file relative to our Hello World program in the bin/at91/packages
directory as follows:
$ tree bin/at91/packages/applications bin/at91/packages/applications \-- helloworld_1.0.0-1_at91.ipk 0 directories, 1 file
So, let's move it into our SAMA5D3 Xplained with the usual scp
:
$ scp bin/at91/packages/applications/helloworld_1.0.0-1_at91.ipk root@192.168.32.51:/root/
Then, we can install it with the opkg
command (the OpenWrt equivalent packages management command of Debian ones):
root@OpenWrt:~# opkg install helloworld_1.0.0-1_at91.ipk Installing helloworld (1.0.0-1) to root... Configuring helloworld. root@OpenWrt:~# helloworld Hello World