📜 ⬆️ ⬇️

LFS: The dark side of power. Part 3

Foreword


So, it's time to put the last dots on “i” and tell you how to finally get Linux from the heap of executable files and libraries that we heroically collected and set up in the last article .

1. Unix System V Initialization Subsystem


This initialization subsystem has been used for a long time in Linux and has been the de facto standard. However, time passes, and one cannot, in general, call this approach obsolete. It is much more accurate to note that this initialization subsystem, in the trend of development of the GNU / Linux family of systems, has given way to systemd, born in the depths of Red Hat Corporation. There are distributions that still use initialization scripts. However, all the popular Linuxes almost every time came to the use of systemd, with the latter finally giving in to the conservative Debian with its daughter Ubuntu.

Actually, I regret that I didn’t immediately begin to build an LFS version using systemd. Simply, after the first unsuccessful attempt at assembly, I didn’t want to deviate from a stable path. Maybe I will come back to this issue, maybe just as I will not return. Time will tell. In the meantime, consider the basic principles of the System V initialization scripts.

When booting the system, the boot loader reads the Linux kernel from the root partition of the bootable media. After the kernel is initialized, control is transferred to the init process, which receives the PID = 1 (physically located in the / sbin / init file). This process works according to the settings specified in the / etc / inittab file.
')
The default is seven levels of system initialization.



Each startup level corresponds to initialization scripts, in the case of LFS located in the /etc/rc.d/init.d/ directory. You don’t have to write them yourself - the LFS authors took care of this by including everything you need to configure in the LFS-Bootscripts package, which lies along the $ LFS / source path. We just have to install this package and make some minimum settings.

2. Installing LFS-Bootscripts, network configuration, / etc / inittab


Suppose the assembly of packages at the previous stage, you tired, and there were other things and you turned off the machine. Now you need to get into the collected system again. This requires chroot

Mount the partition with the system and VFS:

$ su - root # export LFS=/mnt/lfs # mount /dev/sda6 $LFS # mount -v --bind /dev $LFS/dev # mount -vt devpts devpts $LFS/dev/pts -o gid=5,mode=620 # mount -vt proc proc $LFS/proc # mount -vt sysfs sysfs $LFS/sys # mount -vt tmpfs tmpfs $LFS/run 

Perform root change:

 # chroot "$LFS" /usr/bin/env -i \ > HOME=/root TERM="$TERM" PS1='[\u:\w]\$ ' \ > PATH=/bin:/usr/bin:/sbin:/usr/sbin \ > /bin/bash --login 

Go to the source directory and install the necessary package.

 # cd /source # tar -pxf lfs-bootscripts-20150222.tar.bz2 # cd lfs-bootscripts-20150222 # make install 

Nothing particularly tricky and was not supposed - the scripts will simply be installed along the right paths.

And now proceed to configure. Generate Udev rules:

 # bash /lib/udev/init-net-rules.sh 

Further, the manual offers us to check and edit the rule for naming network interfaces, located in /etc/udev/rules.d/70-persistent-net.rules. And here I was waiting for a bummer - the generation script gave an error - I can not generate this file.

The answer is in the same manual:
In some cases, such as when it comes to the network rules, it’s not. In these cases, this method cannot be used.


Yes, but the case with “Qemu or Xen” is just mine - I collected it under a virtual machine (VirtualBox, as is known, using the Qemu code). Well, let's write the rule for naming a network card manually. And now we don’t need to use the cat command to create the file - because we have collected and configured the whole Vim! And Vim is power

 # vim /etc/udev/rules.d/70-persistent-net.rules 

We type the text of the rule:

 # net device e1000 SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:f8:4c:26", ATTR{dev_id}="0x0", ATTR{type}="1", KERNEL=="eth*", NAME=="eth0" 

This rule, when the kernel detects a network device, with the MAC address specified by us as an attribute, assigns it the name eth0. The MAC address of your network card can be learned by giving the following command in the terminal:

 # ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 08:00:27:f8:4c:26 brd ff:ff:ff:ff:ff:ff 

The link / ether parameter of the enp03s device is the required poppy. The device is named the host system (and we remember that we only changed the root and meaning of some environment variables by running the “combat” bash, but we remained in the host system and all devices are available to us).

Now you can set up access to the network. In my case, when building on a VM, it goes to the network through virtual NAT, so a DHCP client is required. We specifically downloaded the dhcpcd package, now we will build it and install it on the system:

 # tar -pxf dhcpcd-6.7.1.tar.bz2 # cd dhcpcd-6.7.1 # ./configure --libexecdir=/lib/dhcpcd --dbdir=/var/tmp # make # make install # cd .. # rm -rf dhcpcd-6.7.1/ 

In addition, install the scripts necessary for dhcpcd to work:

 # tar -pxf blfs-bootscripts-20150304.tar.bz2 # cd blfs-bootscripts-20150304 # make install-service-dhcpcd 

And finally, let's create a config:

 # vim /etc/sysconfig/ifconfig.eth0 


With contents:

 ONBOOT="yes" IFACE="eth0" SERVICE="dhcpcd" DHCP_START="" DHCP_STOP="-k" 

The meaning of the parameters is as follows:



Create a file / etc / hostname, in which we write the host name:

 echo "lfs" > /etc/hostname 

After these operations, you can count on the fact that after a reboot, we will have a network.

Now let's set up init.

 # vim /etc/inittab 

The manual offers the following script:

 # Begin /etc/inittab #      - 3 id:3:initdefault: #   (   ) si::sysinit:/etc/rc.d/init.d/rc S #    #     l0:0:wait:/etc/rc.d/init.d/rc 0 l1:S1:wait:/etc/rc.d/init.d/rc 1 l2:2:wait:/etc/rc.d/init.d/rc 2 l3:3:wait:/etc/rc.d/init.d/rc 3 l4:4:wait:/etc/rc.d/init.d/rc 4 l5:5:wait:/etc/rc.d/init.d/rc 5 l6:6:wait:/etc/rc.d/init.d/rc 6 #    Ctrl + Alt + Del -  ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now #      su:S016:once:/sbin/sulogin #    1:2345:respawn:/sbin/agetty --noclear tty1 9600 2:2345:respawn:/sbin/agetty tty2 9600 3:2345:respawn:/sbin/agetty tty3 9600 4:2345:respawn:/sbin/agetty tty4 9600 5:2345:respawn:/sbin/agetty tty5 9600 6:2345:respawn:/sbin/agetty tty6 9600 # End /etc/inittab 

The lines of this file consist of four fields separated by colons:

 <id>:<runlevels>:<action>:<process> 



To implement actions at various execution levels, LFS provides the /etc/rc.d/init.d/rc script, which accepts a launch level as a parameter.

To perform a single-user login in case of a boot failure, the / sbin / sulogin command is called, this single-user login and executes.

The / sbin / shutdown process starts when the system is stopped / rebooted

/ sbin / agetty - creates and initializes a virtual terminal.

You can change the execution level during system operation by issuing a command from root

 # init <runlevel> 

specifying the trigger level as a parameter. The halt command known to most is the alias to init 0, and the reboot command is the alias to init 6.

You can find out the current launch level by issuing the command:

 # runlevel 

or:

 # who -r 

3. Clocks, localization and other pleasant things


For correct operation of the system clock, create a config.

/ etc / sysconfig / clock
 # Begin /etc/sysconfig/clock UTC=1 # Set this to any options you might need to give to hwclock, # such as machine hardware clock type for Alphas. CLOCKPARAMS= # End /etc/sysconfig/clock 


Here it is indicated that the hardware clock will go according to universal universal time, and we have already made an amendment to the time zone when setting up the GLibc package.

Now you need to correctly configure the console font. We set all the locales we needed with GLibc. We are interested in Cyrillic, so we create a console configuration file in this form

/ etc / sysconfig / console
 # Begin /etc/sysconfig/console UNICODE="1" KEYMAP="us" FONT="UniCyr_8x16" # End /etc/sysconfig/console 




Set the locale by setting the default bash profile

/ etc / profile
 # Begin /etc/profile export LANG=ru_RU.UTF-8 # End /etc/profile 


For order, you should also “bind” some keyboard settings used by the shell and the readline library, which is responsible for keyboard input.

/ etc / inputrc
 # Begin /etc/inputrc #       set horizontal-scroll-mode Off #  8-   set meta-flag On set input-meta On #   8-  set convert-meta Off #  8-    set output-meta On # ,    set bell-style none #   -   escape- , #    ,    # readline "\eOd": backward-word "\eOc": forward-word # for linux console "\e[1~": beginning-of-line "\e[4~": end-of-line "\e[5~": beginning-of-history "\e[6~": end-of-history "\e[3~": delete-char "\e[2~": quoted-insert # for xterm "\eOH": beginning-of-line "\eOF": end-of-line # for Konsole "\e[H": beginning-of-line "\e[F": end-of-line # End /etc/inputrc 


I don’t want to give particular attention to this configuration, so we’ll leave a detailed analysis of it as homework.

The following config defines the names of the shells, the use of which is allowed in the system

/ etc / shells
 # Begin /etc/shells /bin/sh /bin/bash # End /etc/shells 


This is where the initial system setup is over, only a few finishing touches remain.

4. Building the kernel


The irony is that the kernel build is a smaller part of the whole work. Go to the / sources directory and unpack (once again) the source code:

 # cd /sources # tar -pxf linux-3.19.tar.bz2 # cd linux-3.19 

Prepare the kernel for compilation by checking the source tree:

 # make mrproper 

It is necessary to generate the kernel build config:

 # make menuconfig 

This will launch a configurator familiar to many not by hearsay.

What can be said about the required configuration. First, the LFS assembly manual recommends checking the installation of the following option:



Support for mounting the devtmpfs virtual file system in / dev - dynamically creating device files in memory and mounting / dev at an early stage of kernel boot.

Everything else depends on your hardware configuration and the features that you would like to include in the kernel. For example, I added only full support for NTFS, the rest left by default.

Save the config as .config, exit the configurator and build the kernel

 # make 

Install kernel modules:

 # make modules_install 

Copy the compiled kernel into the / boot directory, renaming it:

 # cp -v arch/x86_64/boot/bzImage /boot/vmlinuz-3.19-lfs-7.7 

Save the map file and the config of the assembled kernel:

 # cp -v System.map /boot/System.map-3.19 # cp -v .config /boot/config-3.19 

We are installing the documentation:

 # install -d /usr/share/doc/linux-3.19 # cp -r Documentation/* /usr/share/doc/linux-3.19 

Create configs for optional module loading, for example, for USB support:

 # install -v -m755 -d /etc/modprobe.d # vim /etc/modprobe.d/usb.conf 

/etc/modprobe.d/usb.conf
 # Begin /etc/modprobe.d/usb.conf install ohci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i ohci_hcd ; true install uhci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i uhci_hcd ; true # End /etc/modprobe.d/usb.conf 

We clean up after ourselves:
 # cd .. # rm -rf linux-3.19/ 


5. Mounting File Systems and Bootloader Configuration


Create a mount config / etc / fstab. I looked like this:

/ etc / fstab
 /dev/sda6 / ext4 defaults 1 1 /dev/sda2 swap swap pri=1 0 0 proc /proc proc nosuid,noexec,nodev 0 0 sysfs /sys sysfs nosuid,noexec,nodev 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 tmpfs /run tmpfs defaults 0 0 devtmpfs /dev devtmpfs mode=0755,nosuid 0 0 


/ dev / sda2 and / dev / sda6 are the swap and the root partition of the LFS system, respectively.

Since I collected LFS from a system already installed on the HDD (Arch Linux), then for its first boot I preferred to use the Grub2 boot loader already installed on the hard disk. To configure, I used the config to create a custom boot menu item.

We leave from the collected system:

 # loguot 

And in the host system, edit the file:

/etc/grub.d/40_custom
 #!/bin/sh exec tail -n +3 $0 # This file provides an easy way to add custom menu entries. Simply type the # menu entries you want to add after this comment. Be careful not to change # the 'exec tail' line above. menuentry "GNU/Linux, Linux 3.19-lfs-7.7" { insmod=ext2 set root=(hd0,6) linux /boot/vmlinuz-3.19-lfs-7.7 root=/dev/sda6 ro } 

Then we regenerate the bootloader config:

 # grub-mkconfig -o /boot/grub/grub.cfg 

And ... reboot:

 # systemctl reboot 

If everything is in order and we were not mistaken, the OS selection menu will appear:



Choose the last item of our LFS system ...



Yes! The download started, you can see how the network interface rises, waiting for when we get the ip and ... login screen:



Login as root:



And we run something that will show us the correct locale setting:

 # vim 



Russian language is where it should be. Check the network:

 # ping ya.ru 

And watch the ping go:



Well then

Now that the goal has been achieved .... Instead of concluding


We tried our hand at building Linux from scratch (from scratch). And we succeeded. We have a minimal working system with which you can continue to do anything - transfer to real hardware, try to turn it into a home system. You can admire and forget, because maintaining a home system without a package manager is pretty hard.

I did it just for fun, got some new knowledge, and in general I was satisfied, which I wish my readers.

PS: the system collected by me can be downloaded here . Under the link - a disk image for VirtualBox. The input parameters are as follows.

login: root
passwd: 123456

login: maisvendoo
passwd: maisvendoo

Source: https://habr.com/ru/post/258227/


All Articles