]> rtime.felk.cvut.cz Git - edu/osp-wiki.git/blob - cviceni/2-en.mdwn
Results from theoretical part of the test.
[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**. 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.
170
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.
174
175 6.  Booting kernel with the prepared filesystem (in emulator)
176
177     The next command is used on 32-bit system to start emulator:
178
179         qemu -kernel /boot/vmlinuz-2.6.26-2-686 -initrd ramdisk
180
181     The 64-bit enabled variant of QEMU has to be used on 64-bit Debian
182     system to emulate 64-bit target system:
183
184         qemu-system-x86_64 -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
185
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:
189
190         kvm -kernel /boot/vmlinuz-2.6.32-5-amd64 -initrd ramdisk
191
192 [kvm]:http://www.linux-kvm.org/ 
193
194 7. If all goes well, next message is displayed
195
196         Please press Enter to activate this console.
197
198    When you press Enter then a shell is started and you can test work
199    inside a system which you have just created.
200
201 Possible Enhancements
202 =====================
203
204 Additionally, you can work out minor improvements to the system that
205 can simplify your further work within a booted system.
206
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.
210
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.
214
215         mount -t proc none /proc
216
217 2. The commands intended to be executed during each system start
218    should be writtent into newly created file `/etc/init.d/rcS`.
219
220         mkdir -p _install/etc/init.d
221         cat <<EOF > _install/etc/init.d/rcS
222         #!/bin/sh
223         mount -t proc none /proc
224         echo Nazdar!!!!
225         EOF
226         chmod +x _install/etc/init.d/rcS    # nastavení spustitelnosti
227
228    The RAM-disk has to be build again and the system should be booted
229    again to test added functionality.
230
231 Kernel Loadable Modules
232 =======================
233
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
240 (např. libata).
241
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).
249
250 The example of source code of a simple kernel module follows: 
251
252     #include <linux/init.h>
253     #include <linux/module.h>
254     MODULE_LICENSE("Dual BSD/GPL");
255     
256     static int hello_init(void)
257     {
258         printk(KERN_ALERT "Hello, world\n");
259         return 0;
260     }
261     
262     static void hello_exit(void)
263     {
264         printk(KERN_ALERT "Goodbye, cruel world\n");
265     }
266     
267     module_init(hello_init);
268     module_exit(hello_exit);
269 *Example taken from [LDD3][LDD3].*
270
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**):
274
275     obj-m = khello.o
276
277 Now a `make` program has to be invoked with right parameters:
278
279     make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
280
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.
289
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
292
293     insmod khello.ko
294
295
296 Assignment
297 ==========
298
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.
304
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).
309
310 Tips and Tricks
311 ===============
312
313 * The shell history search by Ctrl-`R` followed by search text
314   can be used to repeat a command already issued. For example:
315
316         <Ctrl-R>cpio<Enter>
317
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.
323
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.
331
332 References
333 ===========
334
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)
343   
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