]> rtime.felk.cvut.cz Git - edu/osp-wiki.git/blob - cviceni/2-en.mdwn
9da0f73cf98de33317c7663722948987aec1dc10
[edu/osp-wiki.git] / cviceni / 2-en.mdwn
1 [[!meta title="Embedded Linux"]]
2
3 [[!toc]]
4
5 Aim of the Exercises
6 ====================
7
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.
15
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).
21
22
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].
29
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.
34
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
39
40 The Steps
41 =========
42
43 1. Download/clone [source code][bbgit] of [BusyBox][bb] project:
44
45         git clone git://busybox.net/busybox.git --reference /usr/src/busybox.git
46         cd busybox
47
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
52
53         qgit
54
55     and we can choose an older/stable version which is not affected by such problems.
56     For example
57
58         git checkout -f 1_18_3
59
60 [bbgit]:http://git.busybox.net/busybox/
61
62 2. Next step is to configure BusyBox such way as intended.
63
64         make menuconfig
65
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.
69
70 3. Project is compiled by standard command
71
72         make
73
74 4. Command
75
76         make install
77
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.
81
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).
86
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.
89
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:
93
94         # chroot _install /bin/sh
95
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.
99
100 [chroot]:http://en.wikipedia.org/wiki/Chroot
101
102 6. Next command can be used to determine missing libraries and their paths
103
104         ldd _install/bin/busybox
105
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:
108
109         mkdir _install/lib
110         cp /lib/i686/cmov/libm.so.6 /lib/i686/cmov/libc.so.6 /lib/ld-linux.so.2 _install/lib
111
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`
115
116         ( cd _install && ln -s lib lib64 )
117
118    The BusyBox can be executed in chroot environment after libraries setup.
119
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.
123
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.
128
129    1. If the root access is available, then the device nodes can be
130       prepared and RAM-disk archive prepared by next commands:
131
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
136
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.
141
142             (
143             cat <<EOF
144             dir /dev 755 0 0
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
151             dir /proc 755 0 0
152             dir /sys 755 0 0
153             EOF
154             
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"
158             ) > filelist
159             
160             gen_init_cpio filelist | gzip > ramdisk
161
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      
163
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é
168    jádro z distribuce.
169
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.
176
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.
180
181 6.  Booting kernel with the prepared filesystem (in emulator)
182
183     The next command is used on 32-bit system to start emulator:
184
185         qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
186
187     The 64-bit enabled variant of QEMU has to be used on 64-bit Debian
188     system to emulate 64-bit target system:
189
190         qemu-system-x86_64 -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
191
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:
195
196         kvm -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
197
198 [kvm]:http://www.linux-kvm.org/ 
199
200 7. If all goes well, next message is displayed
201
202         Please press Enter to activate this console.
203
204    When you press Enter then a shell is started and you can test work
205    inside a system which you have just created.
206
207 Possible Enhancements
208 =====================
209
210 Additionally, you can work out minor improvements to the system that
211 can simplify your further work within a booted system.
212
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.
216
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.
220
221         mount -t proc none /proc
222
223 2. The commands intended to be executed during each system start
224    should be writtent into newly created file `/etc/init.d/rcS`.
225
226         mkdir -p _install/etc/init.d
227         cat <<EOF > _install/etc/init.d/rcS
228         #!/bin/sh
229         mount -t proc none /proc
230         echo Nazdar!!!!
231         EOF
232         chmod +x _install/etc/init.d/rcS    # nastavení spustitelnosti
233
234    The RAM-disk has to be build again and the system should be booted
235    again to test added functionality.
236
237 Kernel Loadable Modules
238 =======================
239
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
246 (např. libata).
247
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).
255
256 The example of source code of a simple kernel module follows: 
257
258     #include <linux/init.h>
259     #include <linux/module.h>
260     MODULE_LICENSE("Dual BSD/GPL");
261     
262     static int hello_init(void)
263     {
264         printk(KERN_ALERT "Hello, world\n");
265         return 0;
266     }
267     
268     static void hello_exit(void)
269     {
270         printk(KERN_ALERT "Goodbye, cruel world\n");
271     }
272     
273     module_init(hello_init);
274     module_exit(hello_exit);
275 *Example taken from [LDD3][LDD3].*
276
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**):
280
281     obj-m = khello.o
282
283 Now a `make` program has to be invoked with right parameters:
284
285     make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
286
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.
295
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
298
299     insmod khello.ko
300
301
302 Assignment
303 ==========
304
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.
310
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).
315
316 Tips and Tricks
317 ===============
318
319 * The shell history search by Ctrl-`R` followed by search text
320   can be used to repeat a command already issued. For example:
321
322         <Ctrl-R>cpio<Enter>
323
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.
329
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.
337
338 References
339 ===========
340
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)
349   
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