@@ -87,8 +87,9 @@ Busybox Userspace
87
87
All these tools you know and love like `` ls `` , `` echo `` , `` cat `` `` mv `` , and
88
88
`` rm `` and so on are commonly referred to as the 'coreutils'. Busybox has that
89
89
and alot more, like utilities from `` util-linux `` so we can do stuff like
90
- `` mount `` and even a complete init system. Basicly most tools to expect to be
91
- present on a Linux system only are these somewhat simplified.
90
+ `` mount `` and even a complete init system. Basically, it contains most tools
91
+ you expect to be present on a Linux system, except they are a slightly
92
+ simplified version of the regular ones.
92
93
93
94
You can get the source from [ busybox.net] ( https://busybox.net/ ) . They also
94
95
provide prebuilt binaries which will do just fine for most use-cases. But just
@@ -110,7 +111,7 @@ The C standard library is more important to the operating system than you might
110
111
think. It provides some useful functions and an interface to the kernel. But it
111
112
also handles DNS requests and provides a dynamic linker. We don't really have to
112
113
pay attention to any of this, we can just statically link the one we are using
113
- right know which is probably 'glibc'. This means the following part is optional.
114
+ right now which is probably 'glibc'. This means the following part is optional.
114
115
But I thought this would make it more interesting and it also makes us able to
115
116
build smaller binaries.
116
117
@@ -120,33 +121,33 @@ on Ubuntu or simply ``musl`` on Arch Linux. Now we can link binaries to musl
120
121
instead of glibc by using `` musl-gcc `` instead of `` gcc `` .
121
122
122
123
Before we can build busybox with musl, we need sanitized kernel headers for use
123
- with musl. You get get that from [ this github
124
+ with musl. You get that from [ this github
124
125
repo] ( https://github.com/sabotage-linux/kernel-headers ) . And set
125
126
`` CONFIG_EXTRA_CFLAGS `` in your busybox config to
126
127
`` CONFIG_EXTRA_CFLAGS="-I/path/to/kernel-headers/x86_64/include" `` to use them.
127
128
Obviously change `` /path/to `` to the location where you put the headers repo,
128
- can be relative from within the busybox source directory.
129
+ which can be relative from within the busybox source directory.
129
130
130
131
If you run `` make CC=musl-gcc `` now, the busybox executable will be
131
132
significantly smaller because we are statically linking a much smaller libc.
132
133
133
134
Be aware that even though there is a libc standard, musl is not always a
134
- drop-in replacement from glibc if the application you're compiling uses glibc
135
+ drop-in replacement for glibc if the application you're compiling uses glibc
135
136
specific things.
136
137
137
138
Building the Disk Image
138
139
-----------------------
139
140
140
- Installing a OS on a file instead of a real disk complicates things but this
141
+ Installing an OS on a file instead of a real disk complicates things but this
141
142
makes development and testing easier.
142
143
143
144
So let's start by allocating a new file of size 100M by doing ``fallocate -l100M
144
145
image`` (some distro's don't have `` fallocate`` so you can do `` dd if=/dev/zero
145
146
of=image bs=1M count=100`` instead). And then we format it like we would format
146
- a disk with `` fdisk image `` . It automatically creates a MBR partition table for
147
+ a disk with `` fdisk image `` . It automatically creates an MBR partition table for
147
148
us and we'll create just one partition filling the whole image by pressing 'n' and
148
149
afterwards just use the default options for everything and keep spamming 'enter'
149
- untill you're done. Finally press 'w' exit and to write the changes to the
150
+ until you're done. Finally press 'w' exit and to write the changes to the
150
151
image.
151
152
``` bash
152
153
$ fdisk image
@@ -191,8 +192,8 @@ my case. Let's make a filesystem on it.
191
192
` ` ` bash
192
193
$ mkfs.ext4 /dev/loop0p1
193
194
` ` `
194
- If you want to use something else than ext4, be sure to enable it when
195
- configuring your kernel. Now that we have done that, we can mount it start
195
+ If you want to use something other than ext4, be sure to enable it when
196
+ configuring your kernel. Now that we have done that, we can mount it and start
196
197
putting everything in place.
197
198
` ` ` bash
198
199
$ mkdir image_root
@@ -217,7 +218,7 @@ We'll copy our binaries over.
217
218
$ cp /path/to/busybox usr/bin/busybox
218
219
$ cp /path/to/bzImage boot/bzImage
219
220
```
220
- You can call every busybox utility by supplying the utility as argument, like
221
+ You can call every busybox utility by supplying the utility as an argument, like
221
222
so: ``busybox ls --help``. But busybox also detects by what name it is called
222
223
and then executes that utility. So you can put symlinks for each utility and
223
224
busybox can figure out which utility you want by the symlink' s name.
@@ -231,7 +232,7 @@ These symlinks might be incorrect from outside the system because of the
231
232
absolute path, but they work just fine from within the booted system.
232
233
233
234
Lastly, we' ll copy some files from ``../filesystem`` to the image that will be
234
- some use to us later.
235
+ of some use to us later.
235
236
```bash
236
237
$ cp ../filesystem/{passwd,shadow,group,issue,profile,locale.sh,hosts,fstab} etc
237
238
$ install -Dm755 ../filesystem/simple.script usr/share/udhcpc/default.script
@@ -245,7 +246,7 @@ a binary keymap file I use for belgian azerty.
245
246
The Boot Loader
246
247
---------------
247
248
248
- The next step is to install the bootloader, the program that loads our kernel in
B41A
249
+ The next step is to install the bootloader - the program that loads our kernel in
249
250
memory and starts it. For this we use GRUB, one of the most widely used
250
251
bootloaders. It has a ton of features but we are going to keep it very simple.
251
252
Installing it is very simple, we just do this:
@@ -256,7 +257,7 @@ grub-install --modules=part_msdos \
256
257
/dev/loop0
257
258
` ` `
258
259
The ` ` --target=i386-pc` ` tells grub to use the simple msdos MBR bootloader. This
259
- is often the default but this can vary from machine to machine so you better
260
+ is often the default, but this can vary from machine to machine so you better
260
261
specify it here. The ` ` --boot-directory` ` options tells grub to install the grub
261
262
files in /boot inside the image instead of the /boot of your current system.
262
263
` ` --modules=part_msdos` ` is a workaround for a bug in Ubuntu' s grub. When you
@@ -265,7 +266,7 @@ think it needs to support msdos partition tables and won't be able to find the
265
266
root partition.
266
267
267
268
Now we just have to configure grub and then our system should be able to boot.
268
- This basicly means telling grub how to load the kernel. This config is located
269
+ This basically means telling grub how to load the kernel. This config is located
269
270
at ` ` boot/grub/grub.cfg` ` (some distro' s use ``/boot/grub2``). This file needs
270
271
to be created first, but before we do that, we need to figure something out
271
272
first. If you look at ``/proc/cmdline`` on your own machine you might see
@@ -277,14 +278,14 @@ BOOT_IMAGE=/boot/vmlinuz-4.4.0-71-generic root=UUID=83066fa6-cf94-4de3-9803-ace8
277
278
These are the arguments passed to your kernel when it' s booted. The ' root'
278
279
option tells our kernel which device holds the root filesystem that needs to be
279
280
mounted at ' /' . The kernel needs to know this or it won' t be able to boot. There
280
- are different ways of identifying your the root filesystem. Using a UUID is a
281
+ are different ways of identifying your root filesystem. Using a UUID is a
281
282
good way because it is a unique identifier for the filesystem generated when you
282
283
do ``mkfs``. The issue with using this is that the kernel doesn' t really
283
284
support it because it depends on the implementation of the filesystem. This
284
- works on your system because it uses an initramfs. But we can' t use it now. We
285
+ works on your system because it uses an initramfs, but we can' t use it now. We
285
286
could do ``root=/dev/sda1``, this will probably work but it has some other problems.
286
- The ' a' in ' sda' is can depend on the order the bios will load the disk and this
287
- can change when you add a new disk or sometimes the order can change randomly .
287
+ The ' a' in ' sda' depends on the order the bios will load the disk and this
288
+ can change when you add a new disk, or for a variety of other reasons .
288
289
Or when you use a different type of interface/disk it can be something entirely
289
290
different. So we need something more robust. I suggest we use the PARTUUID. It' s
290
291
a unique id for the partition (and not the filesystem like UUID) and this is a
@@ -294,9 +295,9 @@ a GPT thing). We'll find the id like this:
294
295
$ fdisk -l ../image | grep " Disk identifier"
295
296
Disk identifier: 0x4f4abda5
296
297
` ` `
297
- Then we drop the 0x and append the partition number as two digit hexidecimal. A
298
+ Then we drop the 0x and append the partition number as two digit hexidecimal. An
298
299
MBR only has 4 partitions max so that it' s hexidecimal or decimal doesn' t really
299
- matter but that' s what the standard says. So the grub.cfg should look like this:
300
+ matter, but that' s what the standard says. So the grub.cfg should look like this:
300
301
```
301
302
linux /boot/bzImage quiet init=/bin/sh root=PARTUUID=4f4abda5-01
302
303
boot
@@ -352,14 +353,14 @@ everything down because it's the first and last process to live.
352
353
353
354
This also makes this ` ` init` ` process very suitable to start and manage services
354
355
as is the case with the very common ` ` sysvinit` ` and the more modern
355
- ` ` systemd` ` . But this isn' t strictly necessary and some other process can cary
356
+ ` ` systemd` ` . But this isn' t strictly necessary and some other process can carry
356
357
the burden of service supervision, which is the case with the
357
358
[runit](http://smarden.org/runit/)-like ``init`` that is included with
358
359
``busybox``.
359
360
360
361
Unless you passed the ``rw`` kernel parameter the root filesystem is mounted as
361
362
read-only. So before we can make changes to our running system we have to
362
- remount it as read-write first. And before we can do any mounting at all we have
363
+ remount it as read-write first. Before we can do any mounting at all we have
363
364
to mount the ``proc`` pseudo filesystem that serves as an interface to kernel.
364
365
```bash
365
366
$ mount -t proc proc /proc
@@ -370,14 +371,14 @@ $ mount / -o remount,rw
370
371
are not confortable using either of those you could always shutdown the VM,
371
372
mount the image again, and use your favorite text editor on your host machine.
372
373
373
- If you don' t use an qwerty keyboard you might have noticed that the VM uses a
374
- qwerty layout which is the default, you might want to change it to azerty with
374
+ If you don' t use a qwerty keyboard, you might have noticed that the VM uses a
375
+ qwerty layout as this is the default. You might want to change it to azerty with
375
376
` ` loadkmap < /usr/share/keymaps/be-latin1.bmap` ` . You can dump the layout you
376
377
are using on your host machine with ` ` busybox dumpkmap > keymap.bmap` ` in a
377
378
virtual console (not in X) and put this on your image instead.
378
379
379
380
First, we' ll create a script that handles the initialisation of the system
380
- itself like mounting filesystems and configuring devices, etc. You could call it
381
+ itself ( like mounting filesystems and configuring devices, etc) . You could call it
381
382
``startup`` and put it in the ``/etc/init.d`` directory (create this first).
382
383
Don' t forget to ` ` chmod +x` ` this file when you' re done.
383
384
```bash
@@ -457,17 +458,17 @@ after ``sysinit`` and will be restarted when they exit. We'll put some
457
458
it' s correct. If you don' t care for user login and passwords, you could instead
458
459
of the ``getty``' s do ` ` ::askfirst:-/bin/sh` ` . ` ` askfirst` ` does the same as
459
460
` ` respawn` ` but asks you to press enter first. If no tty is specified it will
460
- figure out what the console is. And the ` ` -` ` infront of ` ` -/bin/sh` ` means that
461
+ figure out what the console is. The ` ` -` ` infront of ` ` -/bin/sh` ` means that
461
462
the shell is started as a login shell. ` ` /bin/login` ` usually does this for us
462
463
but we have to specify it here. Starting the shell as a login shell means that
463
464
it configures certain things it otherwise assumes already to be configured. E.g.
464
465
it sources ` ` /etc/profile` ` .
465
466
466
467
We can now start our system with ` ` init` ` . You can remove the ` ` init=/bin/sh` `
467
- entry in ` ` /boot/grub/grub.cfg` ` because it defaults to ` ` /sbin/init` ` . And if
468
+ entry in ` ` /boot/grub/grub.cfg` ` because it defaults to ` ` /sbin/init` ` . If
468
469
you reboot the system you should see a login screen. But if you run ` ` reboot` ` ,
469
470
you' ll notice it won' t do anything. This happens because normally ` ` reboot` `
470
- tells the running ` ` init` ` to reboot. You know, the ` ` init` ` that isn' t running
471
+ tells the running ` ` init` ` to reboot. You know - the ` ` init` ` that isn' t running
471
472
right now. So we have two options, we could run ``reboot -f`` which skips the
472
473
``init``, or we could do this:
473
474
```bash
@@ -489,10 +490,10 @@ from how the more common ``sysvinit`` does things but it'll give you a
489
490
feel for which problems it' s supposed to solve and how.
490
491
491
492
A basic service consists of a directory containing a ` ` run` ` executable, usually
492
- a script. This ` ` run` ` script usually starts the daemon and doesn' t exit untill
493
- the daemon does. If ``run`` exits ``runit`` will thinks the service itself has
493
+ a script. This ` ` run` ` script usually starts the daemon and doesn' t exit until
494
+ the daemon does. If ``run`` exits ``runit`` will think the service itself has
494
495
stopped and if it wasn' t supposed to stop, ` ` runit` ` will try to restart it. So
495
- be careful with forking daemons. Startin the service is done with ` ` runsv` ` .
496
+ be careful with forking daemons. Starting the service is done with ` ` runsv` ` .
496
497
This is the process that actually monitors the service and restarts it if
497
498
necessary. Usually you won' t run it manually but doing so is useful for testing
498
499
services.
@@ -580,7 +581,7 @@ exec udhcpc -f -S
580
581
$ chmod +x /etc/init.d/udhcpc/run
581
582
$ ln -s /etc/init.d/udhcpc /etc/rc.d
582
583
```
583
- And we' re done. Yes it' s that simple. Note that udhcpc just asks for a lease
584
+ Now we' re done. Yes - it' s that simple. Note that udhcpc just asks for a lease
584
585
from the DHCP server and that' s it. When it has a lease it executes
585
586
` ` /usr/share/udhcpc/default.script` ` to configure the system. We already copied
586
587
this script to this location. This script is included with the busybox source.
@@ -592,4 +593,4 @@ Epilogue
592
593
--------
593
594
594
595
That' s it! We' re done for now. Thanks for reading. I hope you learned something
595
- useful, I certainly did while making this.
596
+ useful. I certainly did while making this.
0 commit comments