Dev/Embedded/Rootfs/BusyBox/Example1: Difference between revisions
No edit summary |
|||
(6 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{DISPLAYTITLE:BusyBox Example 1 : Simple system}} | |||
Most of the time when you start with BusyBox as the heart of your system you do not plan for a multi-user desktop box, but rather aim for a small, single purpose embedded system, so you won't need too many stuff to get it running. | Most of the time when you start with BusyBox as the heart of your system you do not plan for a multi-user desktop box, but rather aim for a small, single purpose embedded system, so you won't need too many stuff to get it running. | ||
Line 35: | Line 37: | ||
As this is a very simple system the set of libraries should be very limited. You may need additional ones for your application binaries so I cannot give you a full list, but if you chose to have dynamically linked binaries (which is usually a good idea if your system has more than one or two binaries) you will always need these two : | As this is a very simple system the set of libraries should be very limited. You may need additional ones for your application binaries so I cannot give you a full list, but if you chose to have dynamically linked binaries (which is usually a good idea if your system has more than one or two binaries) you will always need these two : | ||
* The dynamic linker/loader (name depending on the target architecture/triplet) : ld-linux-*.so.* | * The dynamic linker/loader (name depending on the target architecture/triplet) : ld-linux-*.so.* | ||
* the libc | * the libc : libc.so.6 | ||
In order to check for additional library requirements, have a look at this part in the second example | In order to check for additional library requirements, have a look at this part in the second example. | ||
Once you know which libraries you need, you'll need to figure which files to put in which directory for each library. | Once you know which libraries you need, you'll need to figure which files to put in which directory for each library. | ||
Unless you specified an absolute or relative pathname during the linking stage of the compilation of your binaries, there is no "fixed" location for each library file, save maybe the dynamic linker/loader (ld-linux-*.so.*), which usually goes under "/lib", and the dynamic linker will end up looking for libraries in some "default" path which usually includes "/lib". | Unless you specified an absolute or relative pathname during the linking stage of the compilation of your binaries, there is no "fixed" location for each library file, save maybe the dynamic linker/loader (ld-linux-*.so.*), which usually goes under "/lib", and the dynamic linker will end up looking for libraries in some "default" path which usually includes "/lib".<br /> | ||
So the easy way is to create a single "/lib" directory (remember that we chose to desactivate the use of "/usr" in BusyBox configuration). | |||
As for the files, for the dynamic linker/loader and the libc, the files should be shipped with your cross-compilation toolchain. If you're using the toolchain packaged by Debian, then you will find them under "/usr/${triplet}/lib/" if you installed "libc6-*-cross" package, or under "/usr/lib/${triplet}/" if you installed "libc6:*" package (* is for the Debian architecture name, while you should [[Dev/Embedded/Rootfs/BusyBox/Example2#First,_the_answer_about_the_"triplet"|read the bits I collected about the ${triplet} in the second BusyBox example page]]). | |||
== Bootup script(s) == | == Bootup script(s) == | ||
Line 55: | Line 58: | ||
* Other service or configuration script(s) | * Other service or configuration script(s) | ||
What you put in each file depends on your application and your needs. | What you put in each file depends on your application and your needs, even if some parts are hard to avoid and thus common to every system, like the initial mounts of /dev and /proc at least. | ||
In SysVinit the rcS script (called by init according to inittab content) calls "/etc/init.d/rc" for the runlevel S, which will start all scripts from "/etc/rcS.d", and after this, init will change to the default runlevel configured in inittab, which will call "/etc/init.d/rc" for the default runlevel (usually 2) which in turn will start all scripts from the corresponding "/etc/rcN.d" directory. | In SysVinit the rcS script (called by init according to inittab content) calls "/etc/init.d/rc" for the runlevel S, which will start all scripts from "/etc/rcS.d", and after this, init will change to the default runlevel configured in inittab, which will call "/etc/init.d/rc" for the default runlevel (usually 2) which in turn will start all scripts from the corresponding "/etc/rcN.d" directory. | ||
Line 70: | Line 73: | ||
== Configuration files == | == Configuration files == | ||
' | The list of configuration files depend on what you have selected in you BusyBox configuration and on what you write in your scripts.<br /> | ||
And their content depends on your needs, of course.<br /> | |||
In order to know which ones you'll need, there is no easy way (as far as I know).<br /> | |||
* Some of them are listed within BusyBox configuration menu and help for each entry, so you can start there, reading the help for each entry you have activated (save thoses you think would not need a configuration file, like archiving related utilities). | |||
* You can also look at the content of "/etc" on your development host | |||
* Another solution is to try running the system, try to start the services you want, and check the messages on the console. | |||
Here is a short list of those I have listed/created for this simple example : | |||
* /etc/nologin | * /etc/nologin | ||
* /etc/securetty | * /etc/securetty | ||
* /etc/shells | * /etc/shells | ||
* /etc/{passwd,shadow,groups} | * /etc/{passwd,shadow,groups} | ||
* ''' TO BE COMPLETED ''' | |||
== Application binaries and related files == | |||
This part is really only up to you and your application. | |||
As this simple BusyBox example does not include any kind of "application packaging" support there's not need (save for your mental health) to stick to any particular organisation for your files. | |||
Remember that if your binaries rely on some more libs than those you already put under "/lib" (or any other place you chose for them), then you'll need to add them to your base file system too. | |||
Latest revision as of 19:48, 3 February 2025
Most of the time when you start with BusyBox as the heart of your system you do not plan for a multi-user desktop box, but rather aim for a small, single purpose embedded system, so you won't need too many stuff to get it running.
This example explains how to create a minimal Linux based base system using BusyBox as a base for the userland part of the system.
Minimal configuration
You can start with this example minimal config.
Some information about my choices :
- This configuration is based upon the "defaultconfig", but with many modifications (not all listed here)
- No "/usr" support (all binaries under /bin and /sbin)
- Archival utilities limited to tar with "xz" and "bz2" support
- Removed console utilities
- Removed most users handling utilities : users should be known when building the system (or added by direct editting of the files)
- Removed disk partitionning and formatting utilities save for UBIFS
- Removed runit support
- Removed all commands I never used on a full blown system
Compile using uClibc
The options selected for a minimal configuration should not impact the compilation process, unless you want a really small system, which is common when using BusyBox due to storage size constraints.
In this case using uClibc instead of the GNU libc is a good idea.
Most information about using uClibc in a cross-compilation toolchain can be found on uClibc website.
You will then need to use the cross-compilation prefix of your toolchain to build BusyBox.
With a stripped down BusyBox, you may well end up with :
Final link with: <none>
But note that in this case you'll still need the selected libc (uClibc) !
Directories and links
Here is a very simple set of directories for a configuration without "/usr", according to the minimal configuration given above :
mkdir -p dev etc lib/{modules,firmware} proc root run sys var/{log,spool/cron}
Then add some links :
ln -s run/tmp tmp ln -s ../run/tmp var/tmp
Libraries
As this is a very simple system the set of libraries should be very limited. You may need additional ones for your application binaries so I cannot give you a full list, but if you chose to have dynamically linked binaries (which is usually a good idea if your system has more than one or two binaries) you will always need these two :
- The dynamic linker/loader (name depending on the target architecture/triplet) : ld-linux-*.so.*
- the libc : libc.so.6
In order to check for additional library requirements, have a look at this part in the second example.
Once you know which libraries you need, you'll need to figure which files to put in which directory for each library.
Unless you specified an absolute or relative pathname during the linking stage of the compilation of your binaries, there is no "fixed" location for each library file, save maybe the dynamic linker/loader (ld-linux-*.so.*), which usually goes under "/lib", and the dynamic linker will end up looking for libraries in some "default" path which usually includes "/lib".
So the easy way is to create a single "/lib" directory (remember that we chose to desactivate the use of "/usr" in BusyBox configuration).
As for the files, for the dynamic linker/loader and the libc, the files should be shipped with your cross-compilation toolchain. If you're using the toolchain packaged by Debian, then you will find them under "/usr/${triplet}/lib/" if you installed "libc6-*-cross" package, or under "/usr/lib/${triplet}/" if you installed "libc6:*" package (* is for the Debian architecture name, while you should read the bits I collected about the ${triplet} in the second BusyBox example page).
Bootup script(s)
Now Busybox seems to support two init systems : the historic one sharing similarities to SysVinit (without the runlevels) and one similar to runnit.
I choose to disable runnit support in this minimal configuration, so the "init" applet will look for the "/etc/inittab" configuration file.
There is an example one under "examples/" in BusyBox source tree.
Anyway, even without this file the applet will look for a script called "/etc/init.d/rcS" and, even if it found none, start an "askfirst" shell (display the message "Please press Enter to activate this console." which would then give you a prompt). All the details are explained in the example inittab file in BusyBox sources.
So here is a short list of files for the init part of the base system :
- /etc/inittab
- /etc/init.d/rcS
- Other service or configuration script(s)
What you put in each file depends on your application and your needs, even if some parts are hard to avoid and thus common to every system, like the initial mounts of /dev and /proc at least.
In SysVinit the rcS script (called by init according to inittab content) calls "/etc/init.d/rc" for the runlevel S, which will start all scripts from "/etc/rcS.d", and after this, init will change to the default runlevel configured in inittab, which will call "/etc/init.d/rc" for the default runlevel (usually 2) which in turn will start all scripts from the corresponding "/etc/rcN.d" directory.
In busybox there are no runlevels, and usually much less configuration to perform, with this configuration being more "static".
As such, I usually create a single "startup" script (the "/etc/init.d/rcS" one) which does all the usual system configuration and setup (hostname, mounts, hwclock, modules, sysctl, random init, ...) then the network configuration (static IP or DHCP, firewall, ...)
Having everything started sequentially by a single script which does not try to read a hundred configuration files is not that much slower than using a heavy, complicated system which tries to run everything in parallel but needs to be heavily configured to avoid race conditions and handle dependencies.
In order to start the services (sshd, inetd, ...) and the main application(s) you have some options :
- add them at the end of the rcS script (using start-stop-daemon if need be for respawn)
- create a separate script for them (or one for each) and call them at the end of the rcS one (still using start-stop-daemon if need be)
- use the "wait", "once" or "respawn" actions in inittab
I usually use the inittab solution, sometimes with a wrapper script.
Configuration files
The list of configuration files depend on what you have selected in you BusyBox configuration and on what you write in your scripts.
And their content depends on your needs, of course.
In order to know which ones you'll need, there is no easy way (as far as I know).
- Some of them are listed within BusyBox configuration menu and help for each entry, so you can start there, reading the help for each entry you have activated (save thoses you think would not need a configuration file, like archiving related utilities).
- You can also look at the content of "/etc" on your development host
- Another solution is to try running the system, try to start the services you want, and check the messages on the console.
Here is a short list of those I have listed/created for this simple example :
- /etc/nologin
- /etc/securetty
- /etc/shells
- /etc/{passwd,shadow,groups}
- TO BE COMPLETED
This part is really only up to you and your application.
As this simple BusyBox example does not include any kind of "application packaging" support there's not need (save for your mental health) to stick to any particular organisation for your files.
Remember that if your binaries rely on some more libs than those you already put under "/lib" (or any other place you chose for them), then you'll need to add them to your base file system too.