1 [[!meta title="Embedded Linux"]]
8 The aim of this exercise is to practice building of the base
9 system from open-source components presented during 2-nd lecture
10 and motivate and practically introduce students for topics presented
11 during 4-th lecture “*Linux kernel - beginning, development, components
12 and device drivers; GNU libc and user space*”. If there are some
13 steps or relations clear to you, we recommend you try Google to find
14 information first and prepare to ask questions at the 4-th lecture.
16 Open Source Software (OSS) projects are often not used alone but
17 in combination with other OSS projects, resulting in the so-called OSS stacks
18 or even distributions. Perhaps the best known is the LAMP stack - Linux,
19 Apache, MySQL, PHP. In today's exercise you will learn and experiment
20 with another, very often used, a stack of [Linux][kenrel] + [BusyBox][bb] (+[Dropbear][dropbear] SSH server).
23 [BusyBox][bb] is a set of basic/standard UNIX utilities (shell, editor
24 and such utilities as ls, mkdir, …) compiled into one binary.
25 In combination with the Linux kernel it forms a complete minimal
26 operating system with a relatively small footprint. Thanks to this
27 combination is often used in embedded applications such
28 as [WiFi routers and ADSL modems][owrt].
30 We try to create a complete open source operating system from the
31 Linux kernel and user space environment consisting of just busybox
32 during this exercise. Next, you try to program and load a simple
33 module into the kernel.
35 [kenrel]: http://kernel.org/
36 [bb]:http://busybox.net/
37 [owrt]:http://www.openwrt.org/
38 [dropbear]:http://matt.ucc.asn.au/dropbear/dropbear.html
43 1. Download/clone [source code][bbgit] of [BusyBox][bb] project:
45 git clone git://busybox.net/busybox.git --reference /usr/src/busybox.git
48 Because expanded source tree is a current development snapshot, it is
49 quite possible that some problem is encountered during compilation, installing
50 or use of the project. Our significant advantage is that cloned project
51 repository contains whole project development history
55 and we can choose an older/stable version which is not affected by such problems.
58 git checkout -f 1_18_3
60 [bbgit]:http://git.busybox.net/busybox/
62 2. Next step is to configure BusyBox such way as intended.
66 There is possibility to control build of many components but default
67 configuration is suitable for our task. Selection of `Exit` and confirm
68 by `Yes` to save configuration is enough for our case then.
70 3. Project is compiled by standard command
78 installs busybox into local directory `./_install`. Notice, please,
79 that there is only single binary executable file `bin/busybox` and all
80 other directory contents are symbolic links to that binary file.
82 Because we have not used *cross compilation*, which is quite often in case
83 of build for embedded devices, it is possible to test functionality of
84 our result of *native build* directly on build machine. The shell
85 `./_install/bin/sh` can be run for example (it can be terminated by `exit` command).
87 In the case of a real embedded system would have to go on and test the BusyBox
88 after booting on the target hardware.
90 5. If you can use supervisor (root) rights on build system, then it is possible
91 to test BusyBox in [chroot environment][chroot], i.e. with actual running kernel
92 instance, but with minimal filesystem populated during BusyBox install:
94 # chroot _install /bin/sh
96 But you find that the attempt to execute BusyBox would fail, because there are
97 necessary system libraries for default/non-static build of BusyBox and these
98 libraries are not available in `_install` substree after chroot.
100 [chroot]:http://en.wikipedia.org/wiki/Chroot
102 6. Next command can be used to determine missing libraries and their paths
104 ldd _install/bin/busybox
106 These libraries must be copied to the directory `_install`. The command
107 to copy libraries can look like line below on 32-bit system:
110 cp /lib/i686/cmov/libm.so.6 /lib/i686/cmov/libc.so.6 /lib/ld-linux.so.2 _install/lib
112 The ELF file "interpreter" (`/lib64/ld-linux-x86-64.so.2`) is searched
113 in directory `/lib64` on 64-bit system by kernel.
114 The `/lib64` can be substituted by symbolic link to directory `/lib`
116 ( cd _install && ln -s lib lib64 )
118 The BusyBox can be executed in chroot environment after libraries setup.
120 5. The easiest way how to boot into the user environment you just created
121 is to store pack directory tree in the Linux kernel initial RAM-disk
122 format and boot Linux with this RAM-disk.
124 For everything worked as planned, there are some minimal set of named
125 entries required in `/dev` directory of `_install` tree in addition
126 to already setup binary and libraries. The device nodes in the `/dev`
127 directory are required for correct access virtual terminals foe example.
129 1. If the root access is available, then the device nodes can be
130 prepared and RAM-disk archive prepared by next commands:
132 mkdir _install/{dev,etc,proc,sys}
133 sudo cp -a /dev/tty? _install/dev
134 ln -s bin/busybox _install/init
135 (cd _install; find . | cpio -o -H newc | gzip) > ramdisk
137 2. If the root access is not available on system used for RAM-disk
138 preparation then the [gen_init_cpio][gic] from kernel build
139 can be used for preparation of RAM-disk archive with set
140 of special files and directories injected.
145 nod /dev/tty0 644 0 0 c 4 0
146 nod /dev/tty1 644 0 0 c 4 1
147 nod /dev/tty2 644 0 0 c 4 2
148 nod /dev/tty3 644 0 0 c 4 3
149 nod /dev/tty4 644 0 0 c 4 4
150 slink /init bin/busybox 700 0 0
155 find _install -mindepth 1 -type d -printf "dir /%P %m 0 0\n"
156 find _install -type f -printf "file /%P %p %m 0 0\n"
157 find _install -type l -printf "slink /%P %l %m 0 0\n"
160 gen_init_cpio filelist | gzip > ramdisk
162 [gic]:http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=usr/gen_init_cpio.c;hb=HEAD
164 5. **The Linux Kernel**. Preparation of the kernel is quite similar as steps used for BusyBox:
165 the kernel source code is downloaded, configured (i.e. make menuconfig)
166 and compiled (make). Given the size of the kernel and required time
167 (the build tree takes about 1 GB of disk space and compilation
168 takes about 20 minutes), we skip these steps and use the already kernel
169 already installed from a distribution.
171 If you choose to use self build kernel then the path to that
172 kernel image would be specified in after *-kernel* option
173 in next step QEMU command.
175 6. Booting kernel with the prepared filesystem (in emulator)
177 The next command is used on 32-bit system to start emulator:
179 qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
181 The 64-bit enabled variant of QEMU has to be used on 64-bit Debian
182 system to emulate 64-bit target system:
184 qemu-system-x86_64 -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
186 If the host system CPU provides hardware virtualization support
187 then it is advantageous to use [KVM][kvm] enhanced emulator which is
188 significantly faster. Next command can be used in such case:
190 kvm -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
192 [kvm]:http://www.linux-kvm.org/
194 7. If all goes well, next message is displayed
196 Please press Enter to activate this console.
198 When you press Enter then a shell is started and you can test work
199 inside a system which you have just created.
201 Possible Enhancements
202 =====================
204 Additionally, you can work out minor improvements to the system that
205 can simplify your further work within a booted system.
207 1. Můžete připojit souborový systém `/proc`, aby fungovaly příkazy
208 jako např. `ps` (výpis běžících procesů). Příkaz spusťte v
209 emulátoru, ne na vaší pracovní stanici.
211 You can mount a `/proc` virtual filesystem to allow commands such as `ps`
212 (listing running processes) to function correctly. Use next command in
213 the emulator, not on your workstation.
215 mount -t proc none /proc
217 2. The commands intended to be executed during each system start
218 should be writtent into newly created file `/etc/init.d/rcS`.
220 mkdir -p _install/etc/init.d
221 cat <<EOF > _install/etc/init.d/rcS
223 mount -t proc none /proc
226 chmod +x _install/etc/init.d/rcS # nastavení spustitelnosti
228 The RAM-disk has to be build again and the system should be booted
229 again to test added functionality.
231 Kernel Loadable Modules
232 =======================
234 Jaderné moduly jsou přeložené kusy kódu, které lze za běhu nahrávat do
235 Linuxového jádra. Pokud bychom chtěli nalézt analogickou věc v
236 uživatelském prostředí, pak by to byly *sdílené knihovny*. Jaderný
237 modul může obsahovat kód ovladače zařízení, podporu určitého
238 souborového systému, může přidávat do jádra nové funkce (např.
239 firewall) či sloužit jako knihovna pomocných funkcí pro jiné moduly
242 Kernel modules are separate compiled pieces of code that can be loaded
243 into running Linux kernel. If we wanted to find an analogy in the user
244 environment, then it would be shared *shared/dynamically linked library*
245 or program *plugins*. Kernel module can provide device driver functionality,
246 can add support for a file system, can add new features to the core
247 (i.e., firewalls), or serve as a library of utility functions for other
248 modules (i.e., libata).
250 The example of source code of a simple kernel module follows:
252 #include <linux/init.h>
253 #include <linux/module.h>
254 MODULE_LICENSE("Dual BSD/GPL");
256 static int hello_init(void)
258 printk(KERN_ALERT "Hello, world\n");
262 static void hello_exit(void)
264 printk(KERN_ALERT "Goodbye, cruel world\n");
267 module_init(hello_init);
268 module_exit(hello_exit);
269 *Example taken from [LDD3][LDD3].*
271 The compilation can be controlled by a simple Makefile,
272 which will contain a single line (here we assume that the
273 above file is named **khello.c**):
277 Now a `make` program has to be invoked with right parameters:
279 make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
281 The parameter `-C` direct a `make` build control tool
282 to read kernel installation provided `Makefile` from actual
283 running kernel sources/build directory directory (where
284 are actual directory located can be check by link examination
285 `readlink -f /lib/modules/$(uname -r)/build`). The parameter
286 `M` specifies that your module is located in the current
287 directory and kernel make-system should build only in that directory.
288 The word `modules` on the end means that you want to compiled modules only.
290 If everything goes well, the file `khello.ko` is created as a result
291 of compilation, which is module which can be load into kernel by command
299 Create a simple kernel module, which after logs your name after insertion
300 into the kernel. The kernel log can be examined by `dmesg` command.
301 No other functionality is required from the module.
302 Demonstrate functionality of result of your work in a emulator
303 environment with root filesystem created according above described steps.
305 Who will get bored, may try to extend the module such way that his/her
306 name appeared in the file `/proc/myname` or a simple driver
307 can be created which would return your name when read from `/dev/myname`
308 is issued. Instructions can be found in [this article][henson_drivers] (page 2 and 3).
313 * The shell history search by Ctrl-`R` followed by search text
314 can be used to repeat a command already issued. For example:
318 * To quickly copy text between programs (i.e., commands from the shell of this page)
319 use a middle mouse button. It works so that the text is selected by mouse
320 left button (the Ctrl-C is not pressed/used) and then position mouse
321 to desired target terminal/window/location and press the middle mouse button.
322 It is not necessary to touch keyboard at all and you get forward faster.
324 * If the QEMU is executed over a remote connection (i.e. on server postel)
325 then tunneling of X protocol (`ssh -X`) is required to allow
326 QEMU emulated screen of target system to be launched. Or the QEMU
327 and target system can be run with text mode console (`qemu -curses`).
328 Yet another option is to run QEMU without console and graphic card
329 emulation at all (`qemu -nographic`) and setup emulated system system
330 console to be redirected to serial port.
335 * [ramfs, rootfs and initramfs](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/filesystems/ramfs-rootfs-initramfs.txt;hb=HEAD)
336 * [Early userspace support](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/early-userspace/README;hb=HEAD)
337 * [Inside the Linux boot process](http://www.ibm.com/developerworks/linux/library/l-linuxboot/)
338 * [The Linux Bootdisk HOWTO](http://www.tldp.org/HOWTO/Bootdisk-HOWTO/)
339 * [Linux Loadable Kernel Module HOWTO](http://tldp.org/HOWTO/Module-HOWTO/)
340 * [Linux Device Drivers, Third Edition][LDD3]
341 * [Kbuild & modules](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/kbuild/modules.txt;hb=HEAD)
342 * [/dev/hello_world: A Simple Introduction to Device Drivers under Linux](henson_drivers)
344 [LDD3]:http://lwn.net/Kernel/LDD3/
345 [henson_drivers]:http://linuxdevcenter.com/pub/a/linux/2007/07/05/devhelloworld-a-simple-introduction-to-device-drivers-under-linux.html