Toucan Linux Project - 12
A Roll Your Own Distribution
Goal 1 – Base System
Stage 2 – Building the Base System
In this chapter we'll do a few more steps to finish the system. There is a big difference now because now you have booted into your new system and you no longer need the host (though you may still wish to use it the mount.sh and chroot_to_lfs scripts since you can still work in the graphical environment.) We did install a text based web browser that you can use to still read this while you work.
You can use two virtual terminals for this. When you first login you are in the first terminal. Then press CTRL-ALT-F2 to switch to another terminal, and login again. From it, use
links
https://toucanlinuxproject.blogspot.com
I have done my best to make it readable with a text browser (but you will miss console mouse support for now so this chapter can be done using the host if you want to avoid a lot of typing.)
Now you can switch back and forth from your work window to the browser by using CTRL-ALT-F1 and CTRL-ALT-F2.
You can, of course, still boot into the host, mount the partitions, and chroot to the target and continue working if you choose.
Step 1 - Disable Intermediate Tools
Just to make sure there is nothing using the tools directory from a PATHmv /tools /tools-old
chmod 000 /tools-old
A note on these tools, now that you have built them there you can use them for another system. All you need to do to setup a new system is create partitions, create the file systems, mount them on a host OS, and put them in the root partition of the new system just like we did here. Then you can proceed building the new host.
If you choose, you can tar up the whole system onto a mountable media with something like this:
mkdir -v /mnt/backup
mount /dev/REMOVEABLE /mnt/backup
cd /mnt/backup
tar -czf /mnt/backup/mysys.tar.gz / --exclude /mnt/backup
You can put this on any filesystem, build and install the kernel and the bootloader, and you will have a working system without going through all the steps again we have so far.
Step 2 Distro Release File
To comply with the Linux Standards Basecat > /etc/ttlp-release << "EOF"
DISTRIB_ID="The Toucan Linux Project"
DISTRIB_RELEASE="1r"
DISTRIB_CODENAME="KilledBill"
DISTRIB_DESCRIPTION="The Toucan Linux Project"
EOF
Since this is your distro do what you want here. The above is only if you want to stick solely with TTLP.
Step 3 - Fixing /dev/root Debacle
Depending on the boot options, how the system was booted, and several other things you might find yourself trapped into the /dev/root debacle. When Linux boots without an initramfs (initial ram filesystem) it uses a small, in-memory file system called rootfs that contains just the /dev directory and the console node (you can see this code in the kernel source tree in the file init/noinitramfs.c) for kernel startup and this uses a device called /dev/root. Later it mounts the real root device, probably a drive partition, as the root device. But /proc/mounts will still say that the root device is /dev/root and now there is no device /dev/root. This isn't problem for most things but it is a problem for utilities that use /proc/mounts to get the name of the root device.There's several solutions to this problem. The first is simply making a symbolic link from the real root device to /dev/root. This solves the problem but requires a script to parse the kernel command line to find the real root. Another solution is to patch the kernel to only add /dev/root to /proc/mounts if the root has not been specified on the kernel command line. This is the solution I like because it preserves the real root device in listings and fixes a problem with the kernel (it shouldn't use a device that is later not available). In this method the kernel and user utilities will agree on the truth. It's not that the kernel isn't telling the truth, it's just telling it as it knows it not as everyone else does.
You can find the original patch from William Hubbs on LKML at https://lkml.org/lkml/2013/1/31/574 but I have modified it for newer kernels.
Choice 1) Create the link using s script
This might be more to what the kernel developers intended and it means you don't have to patch the kernel. For this to work we need to parse the kernel command line at /proc/cmdline for the root entry, get the real device, and make the link. Since /dev is actually a virtual filesystem (devfs) we have to make this link after we mount the virtual filesystems. Recall this is handled by a bootscript called mountvirtfs. Here's a script that will use commands available at system initialization to create the link by using the kernel command line to determine to root device. If you change the root device, this will still work.
#!/bin/bash
# Script to create sym link for /dev/root
# real root dev as specified on kernel cmd line
# Micheal R Stute for The Toucan Linux Project
#
for i in `cat /proc/cmdline`; do
var=`echo $i|cut -c 1-5`
if [ $var == "root=" ]; then
dev=`echo $i|cut -f 2 -d '='`
ln -s $dev /dev/root
fi ;
done
This can be added to a bootscript like mountvirtfs itself at the bottom of the script. This is a pretty good choice, except it means you can't update the bootscripts without making this change.
To use this option do
cat > /bin/make_root_link.sh << "EOF"
#!/bin/sh
# Script to create sym link for /dev/root for
# root dev as specified on kernel cmd line
# Micheal R Stute for The Toucan Linux Project
#
for i in `cat /proc/cmdline`; do
var=`echo $i|cut -c 1-5`
if [ $var == "root=" ]; then
dev=`echo $i|cut -f 2 -d '='`
ln -s $dev /dev/root
fi ;
done
EOF
sed -i "s#ln -sfn /run/shm /dev/shm#ln -sfn /run/shm /dev/shm\\n /bin/make_root_link.sh\\n#" mountvirtfs
Choice 2) Create a startup script
This is probably a better choice, because it makes the script entirely independent. In this case we'll just put the code in the script.
cat > /etc/rc.d/init.d/makerootlink << "EOF"
#!/bin/sh
########################################################################
# Begin makerootlink
#
# Description : Create the /dev/root link in /dev
#
# Authors : Michael R Stute - michaelrstute@gmail.com
#
# Version : TTLP 1.0
#
########################################################################
### BEGIN INIT INFO
# Provides: makerootlink
# Required-Start:
# Should-Start:
# Required-Stop:
# Should-Stop:
# Default-Start: S
# Default-Stop:
# Short-Description: Creates the /dev/root link to proper device
# Description: Use /proc/cmdline to create link to /dev/root
# from real root device
### END INIT INFO
. /lib/lsb/init-functions
case "${1}" in
start)
log_info_msg "Creating /dev/root link"
for i in `cat /proc/cmdline`; do
var=`echo $i|cut -c 1-5`
if [ $var == "root=" ]; then
dev=`echo $i|cut -f 2 -d '='`
ln -s $dev /dev/root || $failed=1
fi ;
done
(exit ${failed})
evaluate_retval
exit $failed
;;
*)
echo "Usage: ${0} {start}"
exit 1
;;
esac
# End makerootlink
EOF
chmod 754 /etc/rc.d/init.d/makerootlink
pushd /etc/rc.d/rcS.d
ln -s ../init.d/makerootlink S02makerootlink
popd
Choice 3) Let udev make it
Create a rule to force udev to make the link when creating the real root device. This is very straight forward and is exactly what udev is intended to do. But it if you change your root device, you'll have to change the rule. Very straight forward. If your root partition never changes, then this makes the most sense. Setting it up is very simple
echo 'KERNEL=="sda3", SYMLINK+="root"' > /etc/udev/rules.d/90-make-root-link.rules
Choice 4) Patch the kernel
Patch the kernel to ensure it doesn't add /dev/root to the mounts in the first place. Whether this is intended by the kernel developers or not, adding /dev/root to /proc/mounts does create trouble for many programs that need to know the root device. As you create your own distro you'll find you have a growing list of patches you'll want to add to the kernel anyway, especially in an experimental distro like TTLP. What's one more? This is the official TTLP method of handling this situation. HIGHLY RECOMMEND method especially for BOFHs, purists, and minimalists.
First make the patch
pushd /sources
cat > kernel-fix-root-device.patch << "EOF"
diff -u a/init/do_mounts.c b/init/do_mounts.c
--- a/init/do_mounts.c 2019-09-13 09:52:03.732857317 -0500
+++ b/init/do_mounts.c 2019-09-13 09:51:38.881704523 -0500
@@ -511,7 +511,11 @@
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
- fd = ksys_open("/dev/root", O_RDWR | O_NDELAY, 0);
+
+ if (saved_root_name[0])
+ fd = sys_open(saved_root_name, O_RDWR | O_NDELAY, 0);
+ else
+ fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0);
if (fd >= 0) {
ksys_ioctl(fd, FDEJECT, 0);
ksys_close(fd);
@@ -555,11 +559,16 @@
#endif
#ifdef CONFIG_BLOCK
{
- int err = create_dev("/dev/root", ROOT_DEV);
-
- if (err < 0)
- pr_emerg("Failed to create /dev/root: %d\n", err);
- mount_block_root("/dev/root", root_mountflags);
+ if (saved_root_name[0]) {
+ int err = create_dev(saved_root_name, ROOT_DEV);
+ if(err < 0)
+ pr_emerg("Failed to create root device: %d\n", err);
+ mount_block_root(saved_root_name, root_mountflags);
+ } else {
+ int err = create_dev("/dev/root", ROOT_DEV);
+ if(err < 0)
+ pr_emerg("Failed to create /dev/root: %d\n", err);
+ mount_block_root("/dev/root", root_mountflags);
}
#endif
}
EOF
popd
Now you need to unpack the kernel source (unless you left the source tree intact as recommended), copy in your config file, and apply the patch. You should be in the kernel source tree underneath /sources such as /sources/linux-5.2.9.
Apply the patch with
patch -Np1 -i ../kernel-fix-root-device.patch
and recompile the kernel, modules, and reinstall using the directions from last chapter.
Step 4 - Limit the Size of the Logs (Optional)
One problem that might occur with our system is that /var is part of the root partition and a user might generate enough messages to fill it up, creating an issue for maintenance. We can use the XFS project quota system to limit the directory to a smaller size to ensure it can't fill the root. If you are the only one using your computer and you aren't concerned about some malicious code using the age old denial of service of filling the root device by causing the system to log a lot of lines, then you can skip this step entirely. Quotas of any kind do slow down the filesystem and if you are looking for extreme performance then you want to avoid quotas anyway. TTLP will not use the standard log daemons by default (syslogd/klogd) but we will replace it later with one that will make sure the logs don't grow too large anyway, rendering this step entirely optional. However, it is still a good tutorial for XFS quotas.XFS has it's own quota system that can be used to limit the amount of space that users, groups, and projects are allowed. This is beyond what the standard kernel quota support allows. One of the nicest features of XFS is that it allows a directory and all its sub-directories to be considered part of a project and that project can be limited in the amount of disk space it is allowed. This is for any directory (including sub-directories) on the partition, not just mount points.
XFS does this by using extended attributes to mark every file in a directory with a project number and then marking all newly created files with the project number as well using inheritance from the parent directory. Their can be many projects and a hard and soft limit for inodes, blocks, and realtime blocks (realtime is a special sub-partition that XFS supports for fast disk space allocation intended to write streaming data we will cover much later in TTLP). Before we can this we need to add a mount option to the root drive.
If you created your own /var as a separate partition then you might opt out of this step since the logs can't fill the root drive but if you intended to limit the space of /tmp using this method (see the next step) you'll need to do this anyway. If /var is a separate partition then you only need to add the mount option "prjquota" to the options in /etc/fstab. But if /var is part of the root partition the we need to add the mount option in the bootloader. The file we need to modify is /boot/grub/grub.cfg.
Currently there should be a menu entry created at the bottom of the file that looks like this (from last chapter)
menuentry "LFS kernel 5.2-pf Toucan Linux" {
insmod part_gpt
insmod fat
insmod xfs
set root=(hd0,gpt1)
linux /vmlinuz-5.2-pf5.ttlp rootfstype=xfs root=/dev/sda3 ro rootfstype=xfs
}
On the line to load the linux kernel starting with "linux" we need to add a boot parameter called rootflags that is the mount options for the root partition. That line should be modified as follows
linux /vmlinuz-5.2-9.ttlp rootfstype=xfs root=/dev/sda3 ro rootfstype=xfs rootflags=prjquota
where /dev/sda3 is your root device. This will enable project quotas for the root partition.
You now need to reboot before resuming.
You must use one of the methods from step 3 to resolve the /dev/root problem or XFS commands won't work.
Setting Up the Limits
XFS defines a project using two files. The first assigns a project number (called project ID) to a directory tree. This is called /etc/projects. The second assigns a name to a project to make it easier to use. This is recorded in /etc/projid. The project numbers can be any 32-bit number (0 - 4,294,967,295). For the log space allowed we will use a project name "logfiles" and an ID of 11.Add the project ID to the system log area (/var/log)
echo "11:/var/log" > /etc/projects
Give project 11 the name "logfiles"
echo "logfiles:11" > /etc/projid
The command to control XFS quotas sis xfs_quota. Within xfs_quota are two modes, one for users to check their own usage and quota, and another for the administrator to make changes to the quotas which is only allowed as the superuser (root). The -x option allows the use of the superuser commands. In this case we have defined a project called logfiles with a project number of 11 and applied it to the /var/log directory tree in the root device. So far we haven't applied this to the filesystem. To do so we first must apply the project to the filesystem which will go through the process of creating the project extended attributes and applying them to all the current files and directories of the project. To do this use
xfs_quota -x -c 'project -s logfiles' /
Now that the current files are marked and the inheritance flags are set on the sub-directories we can now create the limits. As of this moment, no limits have been set.
There are three kinds of limits. The first is the number of inodes the user is allowed to use. The second is the number of blocks of data space the user is allowed to use. The third is the number of blocks in the realtime space that the user is allowed to use. In addition there are two types of limits. The first is the hard limit which determines how much of the given resource is allowed. Once the user has hit this amount, all further allocations of the resources are denied. There is also a soft limit which is the amount of the resource the user is expected to stay under. When the soft limit is exceeded a timer starts and when the timer reaches zero the soft limits are enforced as though they are hard limits. This gives the user a grace period to use more resources than the soft limit, but if the situation is the same when the timer runs out they aren't allowed any more usage until they first delete enough data or inodes to go below the soft limit then the timer is reset. For the logfiles project we want hard limits.
The xfs_quota command is used to administrate XFS quotas. To set the hard limit to 4GB of log file space use
xfs_quota -x -c 'limit -p bhard=4g logfiles' /
The -x option turns on "expert" mode which is superuser mode. The -c specifies the command to run which is limit to adjust the limits. The -p options specifies you are modifying a project quota. The bhard option selects the data block hard limit and sets it to the number of blocks required to allow 4GB space for the project named "logfile". The last required parameter is the filesystem (XFS partition) on which to enforce the quota.
Now we can check it a couple of ways. We can show the filesystem paths with the path command.
# xfs_quota -x -c path
Filesystem Pathname
[000] / /dev/sda3 (pquota)
001 /home /dev/sda4
002 /usr/local /dev/sda5
003 /var/log /dev/sda3 (project 11, logfiles)
Here we see all the XFS filesystems on the computer (I have my work laptop partitioned as a root, boot, home, /usr/local primary and secondary, the boot is not XFS and the secondary /usr/local is not mounted). Here you can see that only root has been mounted with the pquota (same a prjquota) support. It also shows the project 11, "logfiles", applied to /var/log. We can see how much the of limit is used with the report command.
# xfs_quota -x -c report
Project quota on / (/dev/sda3)
Blocks
Project ID Used Soft Hard Warn/Grace
---------- --------------------------------------------------
#0 17514628 0 0 00 [--------]
logfiles 7088 0 4194304 00 [--------]
You can find more information about XFS quotas in the man page for xfs_quota. Quota for realtime sub-partitions is not supported nor is the soft limit warning system built into XFS. You'll need to use the warnquota command instead.
Step 5 - Handling /tmp
The /tmp directory is an area used for short term transitory space. This might be for creating an intermediate file in a print process or some temporary data used during processing. All users can write to the directory but the sticky bit is set only the file owner, directory owner, or root can delete or rename files in the directory. But files are readable by anyone by default for any distros so this is not a place to store data that should be private. TTLP modifies the umask so that files are not publicly readable, however using /tmp is still not a good idea for private data. Since a user can read the data (unless the default umask is changed per TTLP) they can make a copy of it. However, many programs will still use it and adjust permissions on file creation to limit access. This is often a place for named pipes (a device which one process writes to and another reads from with a name and location on a drive -- also called a FIFO), Unix domain sockets (another inter-process communication device), or temporary directories applications might use. A programmer might choose /tmp over something in the user's directory because the system will clean the /tmp periodically which ensures these temporary devices get deleted.The speed of the temporary directory can help with the speed of overall processes that use it for temporary storage, making if beneficial to put on a fast device. Exactly how big it should be is another question entirely. Users (and applications) should not be encouraged to write large amounts of data to the /tmp directory so keeping it small will certainly discourage misuse. If it is part of the root partition, it can be used to fill up the partition and cause problems. Generally the most it should have is 500MB but even 200MB is sufficient (it seems strange to think of a 200MB temporary area when my first hard drive was 10MB maximum) There are three good ways to handle the /tmp directory.
1) Keep it in the root partition.
This is a good choice especially if the root drive is on an NVMe or SSD drive. But you should put a project quota on it like we did the /var/log directory. To set up the quota
echo "10:/tmp" >> /etc/projects
echo "tmp:10" >> /etc/projid
xfs_quota -x -c 'project -s tmp' /
xfs_quota -x -c 'limit -p bhard=200m logfiles' /
This sets the maximum size of the temporary area to be 200m for all users except the superuser.
2) Put it on a different partition. You may opt for a faster drive such as an SSD or NVMe if your main drive is a hard drive. In this case you create the partition, create a file system on it (XFS is still a good choice), and mount it using /tmp as the mount point. For this example we'll assume that /dev/sdX2 is the partition you wish to use for /tmp but you'll need to replace it with the proper device.
mkfs.xfs /dev/sdX2
echo "/dev/sdX2 /tmp xfs defaults,noatime,nosuid 0 1" >> /etc/fstab
mount /tmp
In future system starts, /tmp will be automatically mounted. Be sure to use the real device in the command above.
Using a separate partition ensures it can't be used to fill up the root partition. If you do have applications that write large amounts of data to /tmp this is probably your best choice so you can use an SSD or NVMe drive for better performance.
3) Use a tmpfs. The Linux kernel has a type of filesystem called tmpfs which is designed to be exactly what we want. It is a RAM disk but it automatically shrinks and grows depending on the data it holds. It expands as data is written to it (up to an optional upper limit) and frees the memory when files are removed. This is ideal for /tmp and is the option we will use for TTLP. The only caveat here is if you have low RAM in your system this might not be a good choice, but with an upper limit of 200M it shouldn't be a problem for any system with at least 2GB of RAM. Remember it won't use all 200MB unless it is full.
Using it is very easy.
echo "tmpfs /tmp tmpfs size=200,defaults,nosuid,noatime 0 0" >> /etc/fstab
mount /tmp
Now you have a super fast RAM disk for the temporary storage area and it will be mounted automatically whenever you boot. It will use, at most, 200M of RAM. If you want a bigger or smaller temporary area change the 200M above to the size you want.
It is possible to specify the size of the tmpfs as a percentage of memory using size=xx% such as size=20% and if you don't specify a size it defaults to 50% which could be a real problem on a 2GB system.
Step 6 - CPU microcode
CPU vendors often issue new microcode for their CPUs. This often is to handle security problems and sometimes as a way to increase performance. Unless you really need an older version of microcode you should always run the latest version from your vendor. But before you do that, first update the BIOS to latest version available from your system vendor since the BIOS will load the microcode and the latest from your CPU vendor (AMD or Intel) will be included in your BIOS.Once your BIOS is up to date, check to see if you need to update the microcode.
There are two ways to load new microcode for your system. The easiest is called "late loading" and loads after the kernel has brought up user space. If the microcode contains essential security patches they are loaded in the system initialization phase which might be too late. It is still a good way to test a version of the microcode.
The procedure is different for AMD and Intel CPUs so we'll handle them separately.
Intel
First you'll need to determine the three byte code that identifies your processor.head /proc/cpuinfo
Look for the following lines
cpu family : 6
model : 142
model name : Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz
stepping : 11
Write down family, model, and stepping then convert them to hexadecimal. Run the following to do this
printf "%x\n" `grep 'cpu family' /proc/cpuinfo|uniq |cut -f 2 -d ':'`
printf "%x\n" `grep model /proc/cpuinfo|grep -v name|uniq |cut -f 2 -d ':'`
printf "%x\n" `grep stepping /proc/cpuinfo|uniq |cut -f 2 -d ':'`
For the above the numbers are 6 for the family, 8e for the model, and b for the stepping, giving 06-83-0b. With that three byte combination in hand go to
https://downloadcenter.intel.com/download/28087/Linux-Processor-Microcode-Data-File
and download the file that is named using those three numbers
06-83-b0
for the above CPU. If Intel has changed the download site, the page at the link above will have a link to the correct page.
Once the file is downloaded place it in the area where the kernel expects to find it
mkdir -pv /lib/firmware/intel-ucode
mv -v xx-yy-zz /lib/firmware/intel-ucode
Verify the kernel is setup to load Intel microcode
General Setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
() Initramfs source file(s)
[*] Support initial ramdisk/ramfs compressed using gzip
[*] Support initial ramdisk/ramfs compressed using bzip2
[*] Support initial ramdisk/ramfs compressed using LZMA
[*] Support initial ramdisk/ramfs compressed using XZ
[*] Support initial ramdisk/ramfs compressed using LZO
[*] Support initial ramdisk/ramfs compressed using LZ4
Processor type and features --->
[*] CPU microcode loading support
[*] Intel microcode loading support
The make defconfig will add support for both Intel and AMD processors, making it unlikely these are not already specified. If you made changes to the kernel you need to recompile, reinstall, and then continue with the next step.
Test the loading of the microcode but first making sure you have nothing running you haven't saved. Then test using "load late" with
echo 1 > /sys/devices/system/cpu/microcode/reload
It all goes well, it will return and nothing will appear to have happened. If it fails, then the system might lock up and you'll need to power off to restart. If it looks like all went well then check it will
dmesg | grep 'microcode'
It will return something like the following
[ 0.158208] MDS: Vulnerable: Clear CPU buffers attempted, no microcode
[ 1.757722] microcode: sig=0x806eb, pf=0x80, revision=0x98
[ 1.758267] microcode: Microcode Update Driver: v2.2.
In the above case it is showing that the CPU already has the proper version of microcode and it doesn't need to be updated. If that's the case, you're done but it might be updated in the future, so continue reading so you'll know what to do if that happens.
The sig= line shows the version (in little-endian) currently loaded. Since the versions are the same, nothing needs to be done (for my system updating the BIOS also updated it to the most current version of the microcode). Here is from a different system with a need to update the microcode
[ 0.827634] microcode: sig=0x806e9, pf=0x80, revision=0xb4
[ 0.827735] microcode: Microcode Update Driver: v2.2.
[ 520.005457] microcode: sig=0806e9, pf=80, revision=0x38
[ 520.057063] microcode: updated to revision 0xb4, date = 2019-04-01
[ 520.057731] microcode: sig=0x806e9, pf=0x80 revision=0xb4
Here we can see on line 1 that the file is revision 0xb4. Line 3 shows the current version as revision 0x38 which is an older version requiring an update. The kernel updated the microcode as shown on line 4 and prints the loaded version on line 5. If you see "updated to revision" if means you need to load new microcode.
We need to switch the microcode load to "early load" where the kernel will load it as soon as possible. See the section "Early Loading" below.
AMD
Find the family of your CPUcat /proc/cpuinfo | grep family
It will return something like
cpu family : 15
This shows the family. Now download the proper microcode file from
https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/amd-ucode
Families 10h to 14h (16 to 20) are in microcode_amd.bin. Families 15h, 16h and 17h have their own files. Install the microcode with
mkdir p /lib/firmware/amd-ucode
mv microcode_amd_famxxh.bin /lib/firmware/amd-ucode
Verify the kernel can install the AMD microcode. As with Intel the default configuration for the architecture will enable, but if you enabled them, recompile the kernel, install it, and reboot before continuing.
General Setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
() Initramfs source file(s)
[*] Support initial ramdisk/ramfs compressed using gzip
[*] Support initial ramdisk/ramfs compressed using bzip2
[*] Support initial ramdisk/ramfs compressed using LZMA
[*] Support initial ramdisk/ramfs compressed using XZ
[*] Support initial ramdisk/ramfs compressed using LZO
[*] Support initial ramdisk/ramfs compressed using LZ4
Processor type and features --->
[*] CPU microcode loading support
[*] AMD microcode loading support
Now test the firmware in "load late" mode. Be sure any data you want is saved then.
echo 1 > /sys/devices/system/cpu/microcode/reload
Now check the kernel logs with
dmesg | grep -e 'microcode
If returns something along this lines
[ 0.307619] microcode: CPU0: patch_level=0x010000b6
[ 0.307671] microcode: CPU1: patch_level=0x010000b6
[ 0.307743] microcode: Microcode Update Driver: v2.2.
the there is no need to update your microcode. It is the latest available for your chip as supplied (probably) by your BIOS. If instead it shows
[ 0.307619] microcode: CPU0: patch_level=0x010000b6
[ 0.307671] microcode: CPU1: patch_level=0x010000b6
[ 0.307743] microcode: Microcode Update Driver: v2.2.
[ 187.928891] microcode: CPU0: new patch_level=0x010000c8
[ 187.928899] microcode: CPU1: new patch_level=0x010000c8
It shows the microcode was updated, requiring an "early load" initial disk.
Early Load
To early load the microcode we need to create an initial ramdisk (initrd) that contains a cpio archive of the file with a given name located in a given directory. While this can be done manually the kernel maintainers have provided a tool that can be used instead.Here's a crude example how to prepare an initrd with microcode (this is normally done automatically by the distribution, when recreating the initrd, so you don't really have to do it yourself unless, of course, you are creating your own distribution.) The tool as provided loads all the microcode for all processors into the archive, instead we'll use only the microcode file we need.
Make the script
echo > /usr/bin/create_ucode_initd << "EOF"
#!/bin/bash
if [ -z "$1" ]; then
echo "You need to supply an initrd file"
exit 1
fi
if [ -z "$2" ]; then
echo "You need to supply an microcode file"
exit 1
fi
INITRD="$1"
MCFILE="$2"
DSTDIR=kernel/x86/microcode
TMPDIR=/tmp/initrd
rm -rf $TMPDIR
mkdir $TMPDIR
cd $TMPDIR
mkdir -p $DSTDIR
if [ -d /lib/firmware/amd-ucode ]; then
cat /lib/firmware/amd-ucode/$MCFILE > $DSTDIR/AuthenticAMD.bin
fi
if [ -d /lib/firmware/intel-ucode ]; then
cat /lib/firmware/intel-ucode/$MCFILE > $DSTDIR/GenuineIntel.bin
fi
find . | cpio -o -H newc >../ucode.cpio
cd ..
mv $INITRD $INITRD.orig
cat ucode.cpio $INITRD.orig > $INITRD
rm -rf $TMPDIR
EOF
Now use the script to create the initrd
mount /boot
create_ucode_initrd /boot/early_ucode.cpio <your ucode file>
replacing <your ucode file> with the AMD or Intel microcode file as determined above. Then enable the initrd in Grub's config file. You simply need to add the following to the menuentry section after the linux line in the grub.cfg. It should now look like this
menuentry "Toucan Linux, Linux 5.2.29" {
set root=(hd0,1)
insmod xfs
linux /vmlinuz-5.2.9-ttlp root=/dev/sda2 ro rootfstype=xfs
initrd /early_ucode.cpio
}
Now reboot. If all goes well then you can use the dmesg command to verify the microcode was loaded (as we did before).
If something goes wrong and the system fails to boot, you can go to the menu entry in Grub, press 'e' to edit with BACKSPACE or DEL, and remove the "initrd /early_ucode.cpio" line, and press CTRL-X to complete booting. You can then remove the line from the Grub config file or place a '#' in front of the line to ignore it. But if the "late load" test worked, there is little chance of trouble.
Step 7 - Firmware
Many hardware components including network interfaces (both wired and wireless), sound cards, video cards, and USB controllers might need firmware updates in order to work. This is certainly true with many wireless network adapters. If you have failed to get your wireless network working, this is probably the reason.Fortunately it is easy to install the firmware. For now we'll do it manually, but later we'll have the package manager handle it for us.
First, retrieve the firmware using
pushd /sources
wget https://cdn.kernel.org/pub/linux/kernel/firmware/linux-firmware-20190815.tar.xz --no-check-certificate
Then exploded it and remove the unnecessary license files
tar -xf linux-firmware-20190815.tar.xz
cd linux-firmware-20199815
rm LICEN[SC]E*
Rename it and move it where the kernel expects to find it.
cd ..
mv -v linux-firmware-20190815 /lib/firmware
If you created the firmware directory to install microcode above run this
mv -v firmware/* /lib/firmware
If you didn't create the firmware directory use this command
mv -v firmware /lib
Now reboot the system and boot into TLLP Linux. When it has finished, login as root and check which firmware is loaded with
dmesg|grep firmware
Return to your previous working directory with
popd
For me it returned
[ 5.888806] iwlwifi 0000:00:14.3: Direct firmware load for iwlwifi-9000-pu-b0-jf-b0-46.ucode failed with error -2
[ 6.021114] [drm] Finished loading DMC firmware i915/kbl_dmc_ver1_04.bin (v1.4)
[ 6.175951] Bluetooth: hci0: Minimum firmware build 1 week 10 2014
[ 6.178349] Bluetooth: hci0: Found device firmware: intel/ibt-17-16-1.sfi
[ 7.512657] Bluetooth: hci0: Waiting for firmware download to complete
[ 67.483737] iwlwifi 0000:00:14.3: Direct firmware load for iwlwifi-9000-pu-b0-jf-b0-45.ucode failed with error -2
[ 128.923158] iwlwifi 0000:00:14.3: Direct firmware load for iwlwifi-9000-pu-b0-jf-b0-44.ucode failed with error -2
[ 190.372566] iwlwifi 0000:00:14.3: loaded firmware version 43.95eb4e97.0 op_mode iwlmvm
Showing it loaded firmware for the Intel i915 video hardware, the Intel Bluetooth hardware, and the Intel IWL wireless hardware. Notice the driver tried loading version 46, then 45 and 44, before version 43 for the IWL. That is normal for some drivers though it can be undesirable because some drivers wait 30 seconds before trying another version making your boot time (or when the module is loaded on use) very long. Don't worry, we can fix this later.
Next time, we'll start by making the boot Grub screen a wee bit more fancy with our mascot Killbill, move on to our second goal, angband, and start on the package manager.
But Wait My NIC Still Doesn't Work!
If you have newer hardware this can still be a problem, especially for wireless interfaces. If that's the case switch to a wired interface as they generally are much simpler. If you don't have a wired interface then you might get a USB Ethernet adapter to try a wire or even a different (and common) USB wireless adapter. Here's a site that has a list of USB wireless adapters that are known to work with Linux (https://www.wirelesshack.org/top-linux-compatible-usb-wireless-adapters.html). If the host could use your network but the target can not it is a matter of configuration or missing firmware. Some vendors don't license their firmware in a way that is Linux friendly and you'll need to go to their site to get it. If you buy a lot of newer gear you'll need on of these anyway. It is a way to get a network connection long enough to download what you need to get the built-in hardware working.Copyright (C) 2019 Michael R Stute

No comments:
Post a Comment