• We build our own OS based on Linux. How to create your own operating system from scratch

    Ilya Alexandrov

    We create our own OS on Linux based

    There are hundreds of Linux distributions, and no one knows how many more will appear. Dozens of companies and thousands of programmers compete to create the best Linux project, and yet any advanced user can become the author of a system for a home PC that is not inferior to the products of the giants of the IT industry.

    Over the many years of working with Linux, I have used a huge number of different distributions: Mandriva, Fedora, SlackWare, Debian, Ubuntu and many others. I liked some projects more, some less. But in all distributions we inevitably had to deal with serious shortcomings that made work very difficult. One is too demanding on resources, the other does not support everything the necessary equipment, the third lacks various software. That’s when I remembered the famous Eastern wisdom: if you need to do something well, do it yourself.

    Linux from Scratch

    I'm not the only one who decided to build my own version of Linux - an OS in which the basic part of the system and the kernel will be taken as a basis, but where there will not be a single extra kilobyte from the developer, that is, from you. Large quantity Linux distributions not meeting user requirements prompted Gerard Beekmans to create a distribution that would allow everyone to build a system with only the components and functions they need.

    The desire of a talented programmer resulted in the Linux from Scratch project (www.linuxfromscratch.org), abbreviated as LFS. This project allows you to design your own Linux-based operating system from scratch, from source codes. LFS compilation takes place on a computer with a Linux system already installed, however, an “advanced” Live-CD, for example, Knoppix, is also suitable.

    In this case, the Linux system used for assembly can be any - only the presence of a compiler and system libraries. Linux From Scratch can hardly be called a distribution in the usual sense of the word - it is something like auxiliary software that, together with the basic part of the operating system, will allow you to create your own unique version of the OS.

    As you know, Linus Torvalds developed his operating system under the motto “Just for fun!” - that is, just for the sake of pleasure. It must be admitted that LFS is really not often found on servers; this system is used, as a rule, by computer enthusiasts. Installing and working with Linux from Scratch will help you understand the relationship between OS components, which will be useful when developing your own Linux distribution, and not only based on LFS. Therefore, LFS is largely designed for those people for whom the process of assembling their own distribution is exciting and interesting - and, believe me, there are many such people.

    So, if you are ready to spend a whole day (or even more) on designing a system, then I recommend downloading from the site (2) LFS-packages-6.0, LFS-book, and continuing to read this article.

    Partitioning the disk and creating a directory tree

    For a better understanding of the material, we will describe the entire process in general terms (see Fig. 1).

    At the first stage, using an already installed distribution kit or LiveCD, the disk is split. A partition is allocated on the hard disk for new system. After that, on this partition you will need to statically compile all the necessary programs and the system kernel. Next, the root directory is changed to the partition hard drive, allocated for our new OS. You will need to repeat the compilation, but this time the software must be built dynamically (the difference between dynamic and static compilation will be described below). The last stage includes building the all-important glibc library and configuring the installed OS. As you can see, you don’t have to do anything particularly complicated.

    Throughout the entire process, your main assistant is the documentation from the LFS-book package, the Russian translation of which can be found here: http://multilinux.sakh.com/download/lfsbook.tar.bz2. The book describes each step of creating an OS in detail, so be sure to refer to this guide if you have problems (this article is not intended to replace such extensive documentation).

    We create new section– in my case this is /dev/hda5, since the /dev/hda1 partition is already occupied by installed on hard drive Linux Slackware. It is recommended to first make a backup of the system so that it can be restored in case of damage, although the probability of this is close to zero. And here, I think, everything is clear: we allocate the required amount (23 GB is enough) for the root directory, space equal to twice the amount of RAM for the swap partition, if desired, you can create separate partitions for the home directory (/home) and for /boot. However, the partitioning option favored by many - allocating all available space minus swap to the root directory, and then creating the swap itself - is also quite acceptable when building LFS. On the author’s computer, both Linux Slackware, which is the parent OS, and LFS use one hard drive, however, installing LFS on another hard drive is also not difficult.

    Choose the file system at your discretion: with both Ext3 and ReiserFS there were no problems under LFS. But fans of XFS will have to be disappointed - attempts to make Linux From Scratch work with this FS were not successful.

    Now we mount the partition allocated for the new OS:

    $ mount /dev/hda5 /mnt/mylin

    For convenience, let's define the MYLIN variable:

    $ export MYLIN=/mnt/mylin

    Great, for further work it’s better to create individual user mylin, which we will assign as the owner of the mounted partition.

    $ useradd mylin

    $ chown –R mylin $MYLIN

    You need to create a directory tree at the root of the new partition:

    $cd$MYLIN

    $ mkdir –p bin boot dev etc home lib mnt opt ​​root sbin usr/(X11R6,local) var

    In the usr, usr/X11R6, usr/local directories we create the necessary structure: subdirectories bin, etc, include, lib, sbin, share, src.

    Then we will do the same for the /var and /opt directories future system:

    $ mkdir var/(cache,lib,local,lock,log,opt,run,spool)

    $ mkdir opt/(bin,doc,include,info,lib,man)

    Let's not forget that there are deeper hierarchies, for example /usr/share/man/man1. But the scope of the article does not allow us to provide here all the information about the structure of the file tree, so you need to either use the Filesystem Hierarhy Standard document (can be found at: http://linux-ve.net/MyLDP/file-sys/fhs-2.2-rus) , or carefully study the structure of the Linux OS you already have installed. After training hard disk we proceed to static assembly.

    Static build

    Why do we use static assembly? With static compilation, the library source code is attached to the application code, which entails an increase in its size, but at the same time its integrity is preserved. With dynamic compilation, the library is in separate file, which applications access as needed. As a result, all programs work with the same version of the library

    But when we use the chroot command to set the root directory for the newly assembled system, the libraries of the “parent” installed system, located in /lib, /usr/lib, and others, will no longer be available, so dynamically compiled programs will refuse to work, in addition, version compatibility will not be possible not guaranteed.

    To avoid this, everything you need software For our future system, we will first assemble it statically. Let's start, perhaps, with command interpreter bash. (Fans of ZSH or TCSH can install their favorite interpreters after installing the system, but at the build stage their use is not provided by the author of LFS). You should check if you have the file /usr/lib/libcurses.a and if not, install the ncursesdev package. All packages must be built with static build flags: “--enable-static-link”, “--disable-shared” or “--static”. Which one is suitable for each specific case, can be found from the documentation for a specific package or from the output of a configuration script run with the “--help” option.

    $ ./configure --help

    In order not to confuse statically compiled programs with “dynamic” ones later, let’s create a special directory for them:

    $ mkdir $MYLIN/stat

    When building and installing packages, do not forget to add the parameter “--prefix=$MYLIN/stat” to move files to this directory. And finally, install bash:

    $ ./configure –-enable-static-link --prefix=$MYLIN/stat

    $ make

    $ make install

    Using the same scheme, we collect the remaining necessary packages : binutils, bzip2, textutils, texinfo, tar, sh-utils, gcc, grep, gzip, gawk, diffutils, fileutils, make, patch, sed, and, in fact, linux-kernel.

    Yes, when compiling the kernel, do not forget that for older versions of kernels (2.2.x-2.4.x) you need to use gcc 2.95, and for the current version 2.6.x it is recommended to use gcc 3.x to avoid problems.

    Don’t forget to look at the relevant sections of the LFS-book, it talks about this and many other nuances. In general, compiling a kernel in LFS is no different from a similar procedure carried out when using a distribution installed on the HDD. Let's unzip the kernel sources into $MYLIN/usr/src/linux-2.6.xx, and then configure it by running:

    $ make menuconfig

    The process of setting kernel parameters has been described many times on the Internet (6); there is hardly any need to dwell on this in more detail. Next, we give the following commands in the folder with the Linux-kernel sources:

    $ make bzImage

    $ make modules

    That's it, at $MYLIN/usr/src/linux-2.6.xx/arch/i386/boot/bzImage there is a new kernel.

    Next, create the files $MYLIN/etc/passwd and $MYLIN/etc/group. In the first, we register a single user for now - root with any password, and in the second, groups of users (for starters, one root group will also be enough).

    At this point, our preparations for the next step are over, and we are moving on to a more subtle dynamic assembly.

    Dynamic assembly

    Now we need to change the root directory to /mnt/mylin, where we will use only statically assembled utilities - we will no longer be able to resort to the help of tools from the “parent” OS. We issue the command in the console:

    $ chroot $MYLIN/usr/bin/env –i

    >HOME=/root TERM=$TERM PS1=’u:w$’

    >PATH=/bin: /usr/bin: /sbin: /usr/sbin: /stat/sbin

    >/stat/bin/bash --login

    With this command we specified the paths to the executable files, the terminal type, the interpreter and the type of command line prompt.

    To ensure the operation of some programs, you need to install the proc file system on the new system.

    $ mount proc /proc -t proc

    The most crucial moment has arrived. Building the glibc library. He is the most responsible because most people work without her necessary programs it won’t, and there’s no point in using Linux without the main library. Building glibc often causes a lot of problems.

    During the build, we specified the “--prefix=$MYLIN/stat” parameter, so when changing the root, all statically built packages will end up in the /stat directory of the new OS partition.

    So, unpack the glibc-2.x.x.tar.gz archive (for example, into the /usr/src/ directory) and go to the glibclinuxthreads directory. We will have to slightly correct the source code due to the fact that at this stage It is impossible to identify a user by name in the system (precisely due to the lack of glibc and other libraries), and the fact that to install glibc you need a Perl interpreter, which we do not have.

    We replace the root user name in the login/Makefile with its uid, that is, 0, and the $PERL variable in the malloc/Makefile should be replaced with the path to the interpreter - /usr/bin/perl - and it will simply be ignored during configuration.

    $ /usr/src/glibc-2.x.x/configure --prefix=/usr --enable-add-ons --libexecdir=/usr/bin &&

    & make

    & make install

    $ make localedata/install-locales

    $ /stat/bash --login

    If you did everything correctly, glibc will compile, “root” will finally appear at the prompt, and you can dynamically recompile all programs.

    Let's complete the kernel installation:

    $ make modules_install

    $ make install

    To move the new kernel to the /boot directory, run another command:

    $ make uninstall

    We collect all installed and some new programs, now without static compilation flags. We will need (at this stage it is very important not to forget to compile everything listed below) (see Table 1).

    Table 1. Required set of packages for assembly

    autoconf

    grep

    perl

    automake

    groff

    bash

    gzip

    procinfo

    bin86

    procps

    binutils

    less

    psmisc

    bzip2

    reiserfs-progs

    diffutils

    libtool

    e2fsprogs

    lilo

    sh-utils

    shadow

    file

    make

    sysklogd

    fileutils

    makedev

    sysvinit

    findutils

    man pages

    flex

    modutils

    texinfo

    gawk

    ncurses

    textutils

    netkitbase

    util-linux

    bison

    net-tools

    gettext

    patch

    After performing dynamic recompilation, you can delete the directory with statically built packages:

    $ rm -rf /stat

    You can breathe a sigh of relief and drink coffee - the most difficult, routine things are left behind. Let's move on to next stage– initial configuration of our system.

    Initial System Configuration

    Before we begin setting up, I note that all changes must be made in the directory files of the new OS, and not parent system.

    To set the system time, create a file /etc/sysconfig/clock containing just one line:

    UTC=0

    Now the computer clock will display the time in your time zone - provided that the time value in the BIOS is set correctly.

    Let's give the computer a name:

    echo "HOSTNAME=my_linux" > /etc/sysconfig/network

    Now we indicate the partitions that the system should mount at boot in /etc/fstab:

    # filesystem mount-point fs-type options dump fsck-order

    /dev/hda5/ext3 defaults 1 1

    /dev/hda3 swap swap pri=1 0 0

    proc /proc proc defaults 0 0

    Instead of /dev/hda3 and /dev/hda5, write your partitions (root and swap), supplement the file, if necessary, with mount points for other partitions of the hard drive and CD-ROM.

    Now let's make our system bootable.

    If in addition to lFS you use other Linux distributions, then now you need to enter old system– to do this we run the command:

    $ exit

    Already in the parent OS, add the following to the /etc/lilo.conf file:

    #LFS

    image=/boot/bzImage

    Label=lfs

    Root=

    Read-only

    It is clear that “/boot/bzImage” is the path to the system kernel you compiled, and “partition” is the disk partition where the root directory is located.

    If you do not plan to use other operating systems and Linux distributions, then proceed directly to setting up LILO in LFS.

    In this case, lilo.conf will look something like this:

    boot=/dev/hda

    Delay=40

    Compact

    Vga=normal

    Root=/dev/hda1

    Read-only

    Image=/boot/zImage-2.6.12

    Label=Linux

    Make the necessary changes depending on your configuration. We update the bootloader with the command:

    $ /sbin/lilo –v

    And, if all the previous steps were completed correctly, we will find ourselves in the new system. However, a long stage of “fine” tuning (special attention should be paid to the security of the new system, because LFS by default looks quite unprotected, like any newly installed OS) is still ahead. But you already have a self-assembled version of Linux.

    P.S

    Gerard Beekmans is not the only one who thought of creating his own Linux. Another project, BYOLinux, led by Jonathan Thorpe, has now ceased its development, although the documentation he wrote remains relevant today, but it is not as detailed as the LFS-book and has not been translated into Russian. The main difference between John's method is that the glibc library is transferred from the parent system to the child without recompilation; this is not as efficient, but it avoids many problems during assembly. Some FreeBSD users also want to feel like an OS designer.

    Now this is quite possible - at http://ezine.daemonnews.org/200302/fbsdscratch.html there is an article about building FreeBSD from sources entirely - from distributions to ports, and in a method not similar to the usual "rebuild" of the system, but similar to Gerard Beekmans method. Well, now you have your own personal, unique system based on Linux. If problems arise, look for their solution in the LFS-book, everything is described in detail there. I also recommend downloading the Linux Network Administrator’s Guide from the portal http://www.tldp.org; although it does not relate directly to LFS, it will be useful at the system setup stage. Do not forget that each program also comes with various man and info pages, also designed to make life easier for Linux users.

    1. LFS-book in Russian – http://multilinux.sakh.com/lfs.
    2. The official portal of the LFS project is http://www.linuxfromscratch.org.
    3. ByoLinux Portal – http://www.byolinux.org.
    4. Article about FreeBSD from scratch – http://ezine.daemonnews.org/200302/fbsdscratch.html.
    5. An article about compiling the Linux kernel - http://vikos.lrn.ru/MyLDP/kernel/kompil-2-6.html.
    6. Bayrak A. Review of Knoppix 3.7 Russian Edition. - Magazine " System administrator", No. 3, March 2005 – 4-6 p. ().

    The book "The Operating System from 0 to 1" is published on GitHub and has over 2,000 stars and 100 forks. As the name implies, after reading it, you can create your own operating system - and, perhaps, few things in the world of programmers could be cooler.

    With this book you will learn the following:

    • Learn how to create an operating system based on technical documentation gland. This is how it works in the real world, you won't be able to use Google for quick answers.
    • You will understand how computer components interact with each other, from software to hardware.
    • Learn to write code yourself. Blindly copying code is not learning, you will actually learn how to solve problems. By the way, blind copying is also dangerous.
    • Master the familiar tools for low-level development.
    • Get familiar with assembly language.
    • Find out what programs are made of and how the operating system runs them. We gave a short overview of this topic for the curious in .
    • You will figure out how to debug a program directly on hardware with GDB and QEMU.
    • The C programming language. You can quickly master it by following.
    • Basic knowledge of Linux. Just study on our website.
    • Basic knowledge in physics: atoms, electrons, protons, neutrons, voltage.
    • Ohm's law about the relationship between voltage, current and resistance.

    The book is being improved and edited almost every day: you yourself can make changes or correct a typo. The operating system, the development of which served as the “plot” for this book,

    Original: "Roll your own toy UNIX-clone OS"
    Author: James Molloy
    Publication date: 2008
    Translation: N. Romodanov
    Date of translation: January 2012

    This set of tutorials is designed to show you in detail how to program a simple UNIX-like operating system for the x86 architecture. In these tutorials, the programming language chosen is C, supplemented by assembly language where required. The purpose of the tutorials is to tell you about the design and implementation of solutions used in creating the OS operating system we are creating, which is monolithic in its structure (drivers are loaded in kernel module mode, and not in user mode as happens with programs), since such a solution more simple.

    This set of guides is very practical in nature. Each section provides theoretical information, but most of the manual concerns the implementation of the abstract ideas and mechanisms discussed in practice. It is important to note that the core is implemented as a training core. I know that the algorithms used are neither the most space efficient nor the optimal ones. They were generally chosen due to their simplicity and ease of understanding. The purpose of this is to give you the right mindset and a basis from which to work. This core is extensible and you can easily connect the best algorithms. If you have any problems regarding the theory, there are many sites that can help you figure it out. Most of the questions discussed on the OSDev forum concern implementation ("My gets function doesn"t work! help!") and for many, the theory question is a bit of a mouthful fresh air. References can be found at the end of this introduction.

    Preliminary preparation

    To compile and run the example code, I assume you only need GCC, ld, NASM and GNU Make. NASM is an open-source x86 assembler source code and many OS developers for the x86 platform choose it.

    However, there is no point in simply compiling and running the examples if you don't understand them. You have to understand what is being coded, and to do that you have to know the C language very well, especially when it comes to pointers. You should also understand some assembly language (these tutorials use Intel syntax), including what the EBP register is used for.

    Resources

    There are many resources if you know how to look for them. In particular, you will find the following links useful:

    • RTFM! Intel manuals are a godsend.
    • Wiki pages and forum of the site osdev.org.
    • There are many good tutorials and articles on Osdever.net and in particular Bran's kernel development tutorials, the earlier code of which this tutorial is based on. I used these tutorials myself to get started, and the code in them was so good that I did not change it for a number of years.
    • If you are not a beginner, then you can get answers to many questions in the group

    If we get to the point...

    An OS is a thing that implements multitasking (usually) and manages the distribution of resources between these tasks and in general. It is necessary to ensure that tasks cannot harm each other and work in different areas of memory and work with devices in turn, at least. You also need to provide the ability to transmit messages from one task to another.

    Another OS, if available long term memory, must provide access to it: that is, provide all the functions for working with file system. This is the minimum.

    Almost everywhere, the very first boot code must be written in assembly language - there are a lot of rules about where it should be, what it should look like, what it should do, and what size it should not exceed.

    For a PC, you need to write a bootloader on ASMA, which will be called by the BIOS and which should, without exceeding four and a few hundred bytes, do something and launch the main OS - transfer control to the main code, which in the near future can be written in C.

    For ARM you need to make an interrupt table on ASMA (reset, various errors, IRQ interrupts, FIQ, etc.) and transfer of control to the main code. Although, in many development environments such code is available for almost any controller.

    That is, for this you need:

    1. Know the assembler language of the target platform.
    2. Know the processor architecture and all sorts of service commands and registers in order to configure it to work in desired mode. In a PC, this is a transition to protected mode, for example, or to 64-bit mode... In ARM, this is setting the clocking of the core and peripherals.
    3. Know exactly how the OS will start, where and how you need to push your code.
    4. Know the C language - it is difficult to write large code in Asma without experience, maintaining it will be even more difficult. Therefore, you need to write the kernel in C.
    5. Know the operating principles of the OS. Well, there are a lot of books in Russian on this topic, although I don’t know if they are all good.
    6. Have lots and lots of patience and perseverance. There will be mistakes and they will need to be found and corrected. You will also need to read a lot.
    7. Have lots and lots of time.

    Next. Let's say you wrote something. We need to test this thing. Either you need a physical device on which the experiments will take place (debug board, second computer), or an emulator for it. The second one is usually easier and faster to use. For PC, for example, VMWare.

    There are also plenty of articles on this topic on the Internet, if you search well. There are also many examples of ready-made operating systems with source codes.

    If you really want to, you can even look at the source code of the old kernel of NT systems (Windows), both separately (which was posted by Microsoft, with comments and various kinds of reference materials), and in conjunction with the old OS (leaked).

    Sooner or later, every Linux user thinks about creating their own distribution. Some argue that you can “customize everything for yourself.” Others complain that among the distribution kits already presented in Vetka there is no ideal one. And they supposedly have super-conceptual ideas for their own system. Why did I start all this psychology? In order to immediately cut off the oxygen for beginners playing with Linux who have nothing to do. If you are already thinking about creating an OS, think to the end. So,

    I want to create an OS based on Linux.
    I warn you right away: if it were the 18th century, all those who choose another developed distribution (and, God forbid, popular...) as the basis for their future system would be hanging. The post is about creating a system from scratch, which means all sorts of Slax and Linux Mint we won't touch it.

    Step 1: Select media
    There are few options: either your OS runs from a LiveCD, or from a hard drive, or from a flash device. I’ll make a reservation right away: I won’t say a word about the hard drive in this post, because it’s much more convenient to create a flexible distribution kit from the “I carry everything I have with me” series, or a locked distribution kit on optical disk. If you learn how to create a LiveCD or LiveUSB system, there will be no problems with installation on your hard drive.

    Just in case, prepare a clean flash drive, CD, and finally install Virtualbox.

    Step 2. Compiling the kernel
    Regarding the release of the third Linux kernel, this step encourages further development... So, we need the kernel sources. Every user knows that they can be obtained on the website kernel.org. Under no circumstances, do you hear?, never attach to your system a foreign kernel that was not compiled by you!

    Since my laziness was off the scale, I created the /linuxkernel folder and unpacked the archive with the sources there. Logged in as root, I did the following:

    cd /linuxkernel
    make menuconfig

    In principle, the kernel can be configured in three ways: make config (conversational configuration), make menuconfig (pseudographic configuration via ncurses), and make xconfig (graphical configuration). The bottom line is that make config will ruin your mood for a long time, because... he will ask everything possible questions on all aspects of all topics. The problem with make xconfig does not occur to everyone, but I have encountered and continue to encounter it. If you want to do it through X, figure it out yourself. The best option- make menuconfig. This thing will open up a pseudo-graphical interface through which you can customize the kernel in your own way. The thing requires the ncurses library, which is easy to install.

    Basically, if your brain understands Linux at all, you will figure out the configuration. The process is interesting, there are really a lot of options, and the help, although English, but still pleases with its accessibility and simplicity.

    However, you will still have to be directed. Go to File Systems ---> and put the required asterisks. The letter M means that support for a particular driver is carried out by connecting an external module to the kernel (I hate them!). We will also need isofs support for reading disks. File Systems ---> CD-ROM/DVD Filesystems ---> ISO 9660 CDROM file system support. You can also support ancient Dos systems.

    The crappy Mandriva developers forgot to allow File systems ---> DOS/FAT/NT Filesystems ---> NTFS write support, and on one of their distributions I struggled with access to the Old Windows partition.

    Look at Processor type and features ---> Processor family, I was recommended to choose Pentium-MMX.

    Also have a look in Device Drivers, it's useful. Just for fun, you can select everything there and compile a kernel weighing > 50 MB.

    Next. The kernel, after loading itself, must load the system itself. Either from compiled files (used in embedded systems), or from a CPIO archive compressed by something, or from Initrd. This is not DOS, here you won’t be able to immediately refer to some init” file in the root directory of a disk or flash drive. In fact, it will work, don’t listen to Uncle Annix! This is wrong, even though there is already quite a debate about this on the Internet. We will use initrd in our system, because it is convenient and will not cause obscene language from third-party developers, unlike the CPIO archive.

    Oh yes, compile the kernel with the command

    If you have x86, you will find it at /linuxkernel/arch/x86/boot/bzImage.

    For tough Chelyabinsk programmers, you can use Cross-compiling...

    Creation of Ramdisk.

    Now we need an initrd with a simple shell installed there. We will use busybox, because this cutie can do everything. We will steal the method from Roberto de Leo, the creator of Movix (I would even start to respect him if it weren’t for my incredible love for Perl):

    dd if=/dev/zero of=/dev/ram0 bs=1k count=5000 - Create Ramdisk in RAM our computer.
    mke2fs -m0 /dev/ram0 5000 - Format Ramdisk on Ext2 system
    mkdir /distro - Create a folder
    mount /dev/ram0 /distro - Mount to the /distro folder

    That's it, now we have Ramdisk with a capacity of 5 MB. More is possible, but it’s not necessary. Unlike Thomas Matejisek, I'm not going to stuff the initrd with LZMA-compressed modules in Squashfs. Everything that is needed will be compiled with the kernel. Yes, this is not very logical and correct, but it’s a hundred times less hassle. And especially for those who condemn this approach, you can enable the modularity option in the kernel: Enable loadable module support.

    In our Ramdisk, mounted in /distro, there is such a folder, lost+found. This is because we formatted it in ext2. Under no circumstances should you delete it, although it is unlikely to help here, the image is fixed. For us I should install busybox first...

    Installing Busybox
    That's why such cool projects have such crappy websites? Although... this is no longer important if the sources are downloaded and successfully unpacked into the /busybox folder.

    You can configure busybox in the same way:

    cd /busybox
    make menuconfig

    If you still don’t understand what this is, I’ll explain. Busybox replaces tons of UNIX applications stored in /bin, /sbin, /usr/bin, /usr/sbin folders. Instead, only one application is created: /bin/busybox, and a bunch of links are created to it in the above folders. Install busybox with the following command:

    make CONFIG_PREFIX=/distro install

    Busybox will also create the /sbin/init and for some reason /linuxrc files so that your system starts correctly. But not all the necessary folders were created. So we finish everything by hand and create:

    /distro/etc
    /distro/lib
    /distro/dev
    /distro/mnt
    distro/proc
    /distro/root
    /distro/tmp
    /distro/root

    If you forgot something, remember it, because... It’s hard to forget these directories.

    Everything would be fine, but busybox requires libraries to work, which need to be copied to our distribution. It's very easy to find out which ones:

    ldd /distro/bin/busybox

    The program will show us the libraries required for our shell. I’ll say right away: linux gate is created by the kernel and cannot be copied.

    When copying libraries, you can cut off debugging information (as Roberto advises):

    objcopy --strip-debug from where to where

    Making Linux out of Linux

    You need to create several system text files:

    We need /etc/inittab. I’ll surprise you: at the beginning of its life, the system doesn’t even know what Root is. We even have a nameless user, but the file of system-wide low-level features (ONF) must be present. The pilot contents of the file are as follows:

    # The very first file to be launched, /sbin/init then.
    ::sysinit:/etc/rc.d/rc.S

    # Launch a shell in the console.
    ::respawn:-/bin/sh

    # Commands executed before shutdown and reboot.
    ::shutdown:/sbin/swapoff -a >/dev/null 2>&1
    ::shutdown:/bin/umount -a -r >/dev/null 2>&1

    The next file is /etc/fstab. This is a table that describes what to mount and where when loading. The thing is useless! We need to mount proc, otherwise nothing will work at all, so we write in the file:

    none /proc proc defaults 0 0

    For mount you also need the /etc/mtab file. Create it and leave it empty.

    But mount will do everything necessary only when we explicitly ask it to do so. And we will ask in the very first boot file /etc/rc.d/rc.S (rc.d - folder). We politely ask:

    /bin/mount -av -t nonfs

    We also need a profile file (b)(a)sh, there is generally freedom for imagination. Create a file /etc/profile and fill it with the following:

    PATH="$PATH:/bin:/sbin:/usr/bin:/usr/sbin:"
    LESS=-MM
    TERM=linux
    HOME=/root
    PS1=">"
    PS2=">"
    ignoreeof=10
    export PATH DISPLAY LESS TERM PS1 PS2 HOME ignoreeof

    You will also need the /etc/shell file, which indicates that there is a shell:

    /bin/sh
    /bin/ash
    /bin/bash

    That's all. You can write our Ramdisk to a file.

    mkdir /os - folder for "ready".
    umount /dev/ram0 - unmount a piece of RAM.
    dd if=/dev/ram0 of=/os/initrd bs=1k count=5000 - create a file.
    gzip /os/initrd - compress the initrd file

    Creating a bootable USB flash drive

    The “finish line” of our little development. We take a flash drive, insert it, format it in vfat (you can also use ext, but don’t forget that not all Windows users have shot themselves).

    On the flash drive we create a folder boot, in it there are the initrd and kernel folders.

    From the /os folder, copy the compressed Ramdisk to the boot/initrd folder on the flash drive, call it “main.gz”. From the folder with the kernel sources, copy bzImage to the boot/kernel folder on the flash drive, call it “main.lk”. We get the Syslinux bootloader files (on the Internet or from another distribution: it doesn’t matter), namely syslinux.bin, syslinux.boot, syslinux.cfg. We copy them to the root directory of our flash drive. In the syslinux.cfg file we write something like this:

    default mm
    prompt 1
    timeout 100
    label mm
    kernel /boot/kernel/main.lk

    label mc
    kernel /boot/kernel/main.lk

    label cm
    kernel /boot/kernel/custom.lk
    append initrd=/boot/initrd/main.gz load_ramdisk=1 ramdisk_size=5000 rw root=/dev/ram0
    label cc
    kernel /boot/kernel/custom.lk
    append initrd=/boot/initrd/custom.gz load_ramdisk=1 ramdisk_size=5000 rw root=/dev/ram0
    label hd
    localboot 0x80

    Thus, we supported custom initrd and kernel, which, for the sake of experimentation, can be connected to our distribution.

    Let's find out what device in the system our flash drive is (you can run mount without parameters and see). This is either /dev/sdb1, /dev/sdc1, or /dev/sdd1. It is worth unmounting the flash drive before starting the installation.

    Install syslinux (if the package is not on the system, apt-get install syslinux):

    syslinux -d path_to_device

    The file ldlinux.sys should appear in the root directory of the flash drive. If it is there, then syslinux.bin, syslinux.boot are no longer needed.

    I won’t tell you how to configure the BIOS to boot from a flash drive - it’s easy. I will only say that it is very convenient to create a folder /boot/initrd/init, into which you can mount /boot/initrd/main, for subsequent work with it. Just remember to decompress and compress it with gzip.

    Well, that's all.

    As if I had just told you how to create a Linux system from scratch. Easy, isn't it? Next, you can edit the /sbin/init script, because you still have a lot of work to do! You will have to write a script to mount the flash drive that chroots it to the root directory. Otherwise, you will be forced to work with a ReadOnly partition of 5 MB. But that's a completely different story.