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**. Příprava jádra je téměř stejná jako u BusyBoxu:
165 stáhneme zdrojový kód, nakonfigurujeme a přeložíme. Vzhledem k
166 rozsáhlosti jádra (zkompilované zabere na disku cca 1 GB a překlad
167 trvá cca 20 minut) tyto kroky přeskočíme a použijeme již připravené
170 Preparation of the core is quite similar as steps used for BusyBox:
171 the kernel source code is downloaded, configured (i.e. make menuconfig)
172 and compiled (make). Given the size of the kernel and required time
173 (the build tree takes about 1 GB of disk space and compilation
174 takes about 20 minutes), we skip these steps and use the already kernel
175 already installed from a distribution.
177 If you choose to use self build kernel then the path to that
178 kernel image would be specified in after *-kernel* option
179 in next step QEMU command.
181 6. Booting kernel with the prepared filesystem (in emulator)
183 The next command is used on 32-bit system to start emulator:
185 qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
187 The 64-bit enabled variant of QEMU has to be used on 64-bit Debian
188 system to emulate 64-bit target system:
190 qemu-system-x86_64 -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
192 If the host system CPU provides hardware virtualization support
193 then it is advantageous to use [KVM][kvm] enhanced emulator which is
194 significantly faster. Next command can be used in such case:
196 kvm -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
198 [kvm]:http://www.linux-kvm.org/
200 7. If all goes well, next message is displayed
202 Please press Enter to activate this console.
204 When you press Enter then a shell is started and you can test work
205 inside a system which you have just created.
207 Possible Enhancements
208 =====================
210 Additionally, you can work out minor improvements to the system that
211 can simplify your further work within a booted system.
213 1. Můžete připojit souborový systém `/proc`, aby fungovaly příkazy
214 jako např. `ps` (výpis běžících procesů). Příkaz spusťte v
215 emulátoru, ne na vaší pracovní stanici.
217 You can mount a `/proc` virtual filesystem to allow commands such as `ps`
218 (listing running processes) to function correctly. Use next command in
219 the emulator, not on your workstation.
221 mount -t proc none /proc
223 2. The commands intended to be executed during each system start
224 should be writtent into newly created file `/etc/init.d/rcS`.
226 mkdir -p _install/etc/init.d
227 cat <<EOF > _install/etc/init.d/rcS
229 mount -t proc none /proc
232 chmod +x _install/etc/init.d/rcS # nastavení spustitelnosti
234 The RAM-disk has to be build again and the system should be booted
235 again to test added functionality.
237 Kernel Loadable Modules
238 =======================
240 Jaderné moduly jsou přeložené kusy kódu, které lze za běhu nahrávat do
241 Linuxového jádra. Pokud bychom chtěli nalézt analogickou věc v
242 uživatelském prostředí, pak by to byly *sdílené knihovny*. Jaderný
243 modul může obsahovat kód ovladače zařízení, podporu určitého
244 souborového systému, může přidávat do jádra nové funkce (např.
245 firewall) či sloužit jako knihovna pomocných funkcí pro jiné moduly
248 Kernel modules are separate compiled pieces of code that can be loaded
249 into running Linux kernel. If we wanted to find an analogy in the user
250 environment, then it would be shared *shared/dynamically linked library*
251 or program *plugins*. Kernel module can provide device driver functionality,
252 can add support for a file system, can add new features to the core
253 (i.e., firewalls), or serve as a library of utility functions for other
254 modules (i.e., libata).
256 The example of source code of a simple kernel module follows:
258 #include <linux/init.h>
259 #include <linux/module.h>
260 MODULE_LICENSE("Dual BSD/GPL");
262 static int hello_init(void)
264 printk(KERN_ALERT "Hello, world\n");
268 static void hello_exit(void)
270 printk(KERN_ALERT "Goodbye, cruel world\n");
273 module_init(hello_init);
274 module_exit(hello_exit);
275 *Example taken from [LDD3][LDD3].*
277 The compilation can be controlled by a simple Makefile,
278 which will contain a single line (here we assume that the
279 above file is named **khello.c**):
283 Now a `make` program has to be invoked with right parameters:
285 make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
287 The parameter `-C` direct a `make` build control tool
288 to read kernel installation provided `Makefile` from actual
289 running kernel sources/build directory directory (where
290 are actual directory located can be check by link examination
291 `readlink -f /lib/modules/$(uname -r)/build`). The parameter
292 `M` specifies that your module is located in the current
293 directory and kernel make-system should build only in that directory.
294 The word `modules` on the end means that you want to compiled modules only.
296 If everything goes well, the file `khello.ko` is created as a result
297 of compilation, which is module which can be load into kernel by command
305 Create a simple kernel module, which after logs your name after insertion
306 into the kernel. The kernel log can be examined by `dmesg` command.
307 No other functionality is required from the module.
308 Demonstrate functionality of result of your work in a emulator
309 environment with root filesystem created according above described steps.
311 Who will get bored, may try to extend the module such way that his/her
312 name appeared in the file `/proc/myname` or a simple driver
313 can be created which would return your name when read from `/dev/myname`
314 is issued. Instructions can be found in [this article][henson_drivers] (page 2 and 3).
319 * The shell history search by Ctrl-`R` followed by search text
320 can be used to repeat a command already issued. For example:
324 * To quickly copy text between programs (i.e., commands from the shell of this page)
325 use a middle mouse button. It works so that the text is selected by mouse
326 left button (the Ctrl-C is not pressed/used) and then position mouse
327 to desired target terminal/window/location and press the middle mouse button.
328 It is not necessary to touch keyboard at all and you get forward faster.
330 * If the QEMU is executed over a remote connection (i.e. on server postel)
331 then tunneling of X protocol (`ssh -X`) is required to allow
332 QEMU emulated screen of target system to be launched. Or the QEMU
333 and target system can be run with text mode console (`qemu -curses`).
334 Yet another option is to run QEMU without console and graphic card
335 emulation at all (`qemu -nographic`) and setup emulated system system
336 console to be redirected to serial port.
341 * [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)
342 * [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)
343 * [Inside the Linux boot process](http://www.ibm.com/developerworks/linux/library/l-linuxboot/)
344 * [The Linux Bootdisk HOWTO](http://www.tldp.org/HOWTO/Bootdisk-HOWTO/)
345 * [Linux Loadable Kernel Module HOWTO](http://tldp.org/HOWTO/Module-HOWTO/)
346 * [Linux Device Drivers, Third Edition][LDD3]
347 * [Kbuild & modules](http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/kbuild/modules.txt;hb=HEAD)
348 * [/dev/hello_world: A Simple Introduction to Device Drivers under Linux](henson_drivers)
350 [LDD3]:http://lwn.net/Kernel/LDD3/
351 [henson_drivers]:http://linuxdevcenter.com/pub/a/linux/2007/07/05/devhelloworld-a-simple-introduction-to-device-drivers-under-linux.html