继续构造LFS,从系统配置开始
系统配置
现在需要配置内核引导过程
一定一定一定注意当前是否处于chroot环境
LFS-Bootscripts
解压LFS-Bootscripts
cd /sources/
tar -xf lfs-bootscripts-20240825.tar.xz
cd lfs-bootscripts-20240825
安装软件包
make install
之前安装了Udev程序,现在需要进行一些配置来管理设备,生成Udev初始规则
bash /usr/lib/udev/init-net-rules.sh
检查文件 /etc/udev/rules.d/70-persistent-net.rules,确认网络设备与命名的对应关系
cat /etc/udev/rules.d/70-persistent-net.rules
记住NAME
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="e8:9c:25:97:d0:3b", ATTR{dev_id}=="0x0", ATTR{type}=="1", NAME="eno1"
现在开始网络配置,需要为网络接口创建一个静态IP配置,上面已经记录了接口的名字,也就是eno1
(NAME=”eno1”),所以配置如下
cd /etc/sysconfig/
cat > ifconfig.eno1 << "EOF"
ONBOOT=yes
IFACE=eno1
SERVICE=ipv4-static
IP=192.168.1.2
GATEWAY=192.168.1.1
PREFIX=24
BROADCAST=192.168.1.255
EOF
现在要配置DNS解析,配置如下
cat > /etc/resolv.conf << "EOF"
# Begin /etc/resolv.conf
8.8.8.8
8.8.4.4
# End /etc/resolv.conf
EOF
配置系统主机名
echo "LFS" > /etc/hostname
配置IP地址
cat > /etc/hosts << "EOF"
# Begin /etc/hosts
127.0.0.1 localhost.localdomain localhost
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# End /etc/hosts
EOF
现在配置SysVinit,首先创建/etc/inittab文件
cat > /etc/inittab << "EOF"
# Begin /etc/inittab
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
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
su:S06:once:/sbin/sulogin
s1:1:respawn:/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
EOF
配置系统时钟,先检查硬件时钟是否被设置成UTC,如果有则下面的UTC=1
,否则UTC=0
hwclock --localtime --show
cat > /etc/sysconfig/clock << "EOF"
# 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
EOF
下面配置console,这里采用手册提供的第一个例子作为配置
cat > /etc/sysconfig/console << "EOF"
# Begin /etc/sysconfig/console
UNICODE="1"
FONT="Lat2-Terminus16"
# End /etc/sysconfig/console
EOF
现在配置系统locale,可以使用下面命令列出Glibc支持的所有locale
locale -a
配置locale,在此之前需要检查是否支持选择的locale
LC_ALL=zh_CN locale language
LC_ALL=zh_CN locale charmap
LC_ALL=zh_CN locale int_curr_symbol
LC_ALL=zh_CN locale int_prefix
如果其中有以下输出,说明该locale没有被安装,或者Glibc不支持
locale: Cannot set LC_* to default locale: No such file or directory
创建/etc/profile
以设定locale
cat > /etc/profile << "EOF"
# Begin /etc/profile
for i in $(locale); do
unset ${i%=*}
done
if [[ "$TERM" = linux ]]; then
export LANG=C.UTF-8
else
export LANG=zh_CN.UTF-8
fi
# End /etc/profile
EOF
创建/etc/inputrc
文件
cat > /etc/inputrc << "EOF"
# Begin /etc/inputrc
# Modified by Chris Lynn <roryo@roryo.dynup.net>
# Allow the command prompt to wrap to the next line
set horizontal-scroll-mode Off
# Enable 8-bit input
set meta-flag On
set input-meta On
# Turns off 8th bit stripping
set convert-meta Off
# Keep the 8th bit for display
set output-meta On
# none, visible or audible
set bell-style none
# All of the following map the escape sequence of the value
# contained in the 1st argument to the readline specific functions
"\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
EOF
创建/etc/shells
文件
cat > /etc/shells << "EOF"
# Begin /etc/shells
/bin/sh
/bin/bash
# End /etc/shells
EOF
使 LFS 系统可引导
创建/etc/fstab
文件,这里涉及到文件系统的“名字”,我选择用UUID,可以通过blkid
命令来查看文件系统的UUID,然后将值填入/etc/fstab
中
blkid
输出如下,其中/dev/sdc1
是当前LFS分区所在的文件系统上,对应的UUID就是315ffc52-a533-4a9d-954a-a1d6c891a25f
/dev/nvme0n1p3: UUID="a9642acd-3e82-459c-b7ec-f0f846a5485d" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="e697a942-04c6-4f27-9514-ff7496ce1fe9"
/dev/nvme0n1p1: UUID="270E-0D67" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="364861e4-27a5-4c6c-9ff3-45eb29888856"
/dev/nvme0n1p2: UUID="bc12805b-5399-46f8-94af-4ba4f1884420" TYPE="swap" PARTUUID="b90ad2a6-f3bb-4374-b9cc-88cd70e5ad57"
/dev/sdc1: UUID="315ffc52-a533-4a9d-954a-a1d6c891a25f" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="0127e901-01"
/dev/sdb1: UUID="bc14ec76-1e31-bdf8-b20b-4d19768c23eb" UUID_SUB="84c7d62a-420b-232d-5625-af84e9ad8d93" LABEL="debian:0" TYPE="linux_raid_member" PARTUUID="8a56aa87-01"
/dev/md0: UUID="ee5405d0-c592-41cc-946c-d25e8c99fa3a" BLOCK_SIZE="4096" TYPE="ext4"
/dev/sda1: UUID="bc14ec76-1e31-bdf8-b20b-4d19768c23eb" UUID_SUB="acfe69f5-9f53-56b8-cf6b-bd4cba4f4c5d" LABEL="debian:0" TYPE="linux_raid_member" PARTUUID="37f959a3-01"
修改文件系统和类型,因为之前没有制作交换分区,故这里注释掉swap,而这里使用了UUID,所以需要使用UUID=文件系统的UUID
的格式
cat > /etc/fstab << "EOF"
# Begin /etc/fstab
UUID=315ffc52-a533-4a9d-954a-a1d6c891a25f / ext4 defaults 1 1
# /dev/nvme0n1p2 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
tmpfs /dev/shm tmpfs nosuid,nodev 0 0
cgroup2 /sys/fs/cgroup cgroup2 nosuid,noexec,nodev 0 0
# End /etc/fstab
EOF
现在可以安装内核了,首先准备编译内核
cd /sources/
rm -rf linux-6.10.5
tar -xf linux-6.10.5.tar.xz
cd linux-6.10.5
make mrproper
配置内核选项
make menuconfig
我的配置如下
General setup --->
[ ] Compile the kernel with warnings as errors [WERROR]
CPU/Task time and stats accounting --->
[*] Pressure stall information tracking [PSI]
[ ] Require boot parameter to enable pressure stall information tracking
... [PSI_DEFAULT_DISABLED]
< > Enable kernel headers through /sys/kernel/kheaders.tar.xz [IKHEADERS]
[*] Control Group support ---> [CGROUPS]
[*] Memory controller [MEMCG]
[ ] Configure standard kernel features (expert users) ---> [EXPERT]
Processor type and features --->
[*] Build a relocatable kernel [RELOCATABLE]
[*] Randomize the address of the kernel image (KASLR) [RANDOMIZE_BASE]
[*] Support x2apic [X86_X2APIC]
General architecture-dependent options --->
[*] Stack Protector buffer overflow detection [STACKPROTECTOR]
[*] Strong Stack Protector [STACKPROTECTOR_STRONG]
Device Drivers --->
Generic Driver Options --->
[ ] Support for uevent helper [UEVENT_HELPER]
[*] Maintain a devtmpfs filesystem to mount at /dev [DEVTMPFS]
[*] Automount devtmpfs at /dev, after the kernel mounted the rootfs
... [DEVTMPFS_MOUNT]
Graphics support --->
< /*/M> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
... [DRM]
# If [DRM] is selected as * or M, this must be selected:
[ /*] Enable legacy fbdev support for your modesetting driver
... [DRM_FBDEV_EMULATION]
Console display driver support --->
# If [DRM] is selected as * or M, this must be selected:
[ /*] Framebuffer Console support [FRAMEBUFFER_CONSOLE]
[*] PCI support ---> [PCI]
[*] Message Signaled Interrupts (MSI and MSI-X) [PCI_MSI]
[*] IOMMU Hardware Support ---> [IOMMU_SUPPORT]
[*] Support for Interrupt Remapping [IRQ_REMAP]
现在开始编译内核
make
编译完成后复制内核映像到/boot
目录下
cp -iv arch/x86/boot/bzImage /boot/vmlinuz-6.10.5-lfs-12.2
System.map 是内核符号文件,它将内核 API 的每个函数入口点和运行时数据结构映射到它们的地址。它被用于调查分析内核可能出现的问题。执行以下命令安装该文件
cp -iv System.map /boot/System.map-6.10.5
保留一份内核配置文件供参考
cp -iv .config /boot/config-6.10.5
安装 Linux 内核文档
cp -r Documentation -T /usr/share/doc/linux-6.10.5
保留内核源码树
chown -R 0:0 .
配置 Linux 内核模块加载顺序,创建文件 /etc/modprobe.d/usb.conf
install -v -m755 -d /etc/modprobe.d
cat > /etc/modprobe.d/usb.conf << "EOF"
# 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
EOF
安装GRUB
grub-install /dev/sdc --target i386-pc
因为是在U盘中制作LFS,所以需要进行额外步骤,也就是安装initrd
首先安装cpio,因为mkinitramfs依赖于cpio
exit
cd $LFS/sources/
wget https://ftp.gnu.org/gnu/cpio/cpio-2.15.tar.bz2
chroot "$LFS" /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
PS1='(lfs chroot) \u:\w\$ ' \
PATH=/usr/bin:/usr/sbin \
MAKEFLAGS="-j$(nproc)" \
TESTSUITEFLAGS="-j$(nproc)" \
/bin/bash --login
cpio
解压cpio
cd /sources
tar -xf cpio-2.15.tar.bz2
cd cpio-2.15
准备并编译cpio
./configure --prefix=/usr \
--enable-mt \
--with-rmt=/usr/libexec/rmt &&
make &&
makeinfo --html -o doc/html doc/cpio.texi &&
makeinfo --html --no-split -o doc/cpio.html doc/cpio.texi &&
makeinfo --plaintext -o doc/cpio.txt doc/cpio.texi
测试编译结果
make check
安装软件包
make install &&
install -v -m755 -d /usr/share/doc/cpio-2.15/html &&
install -v -m644 doc/html/* \
/usr/share/doc/cpio-2.15/html &&
install -v -m644 doc/cpio.{html,txt} \
/usr/share/doc/cpio-2.15
现在需要创建两个脚本
cat > /usr/sbin/mkinitramfs << "EOF"
#!/bin/bash
# This file based in part on the mkinitramfs script for the LFS LiveCD
# written by Alexander E. Patrakov and Jeremy Huntwork.
copy()
{
local file
if [ "$2" = "lib" ]; then
file=$(PATH=/usr/lib type -p $1)
else
file=$(type -p $1)
fi
if [ -n "$file" ] ; then
cp $file $WDIR/usr/$2
else
echo "Missing required file: $1 for directory $2"
rm -rf $WDIR
exit 1
fi
}
if [ -z $1 ] ; then
INITRAMFS_FILE=initrd.img-no-kmods
else
KERNEL_VERSION=$1
INITRAMFS_FILE=initrd.img-$KERNEL_VERSION
fi
if [ -n "$KERNEL_VERSION" ] && [ ! -d "/usr/lib/modules/$1" ] ; then
echo "No modules directory named $1"
exit 1
fi
printf "Creating $INITRAMFS_FILE... "
binfiles="sh cat cp dd killall ls mkdir mknod mount "
binfiles="$binfiles umount sed sleep ln rm uname"
binfiles="$binfiles readlink basename"
# Systemd installs udevadm in /bin. Other udev implementations have it in /sbin
if [ -x /usr/bin/udevadm ] ; then binfiles="$binfiles udevadm"; fi
sbinfiles="modprobe blkid switch_root"
# Optional files and locations
for f in mdadm mdmon udevd udevadm; do
if [ -x /usr/sbin/$f ] ; then sbinfiles="$sbinfiles $f"; fi
done
# Add lvm if present (cannot be done with the others because it
# also needs dmsetup
if [ -x /usr/sbin/lvm ] ; then sbinfiles="$sbinfiles lvm dmsetup"; fi
unsorted=$(mktemp /tmp/unsorted.XXXXXXXXXX)
DATADIR=/usr/share/mkinitramfs
INITIN=init.in
# Create a temporary working directory
WDIR=$(mktemp -d /tmp/initrd-work.XXXXXXXXXX)
# Create base directory structure
mkdir -p $WDIR/{dev,run,sys,proc,usr/{bin,lib/{firmware,modules},sbin}}
mkdir -p $WDIR/etc/{modprobe.d,udev/rules.d}
touch $WDIR/etc/modprobe.d/modprobe.conf
ln -s usr/bin $WDIR/bin
ln -s usr/lib $WDIR/lib
ln -s usr/sbin $WDIR/sbin
ln -s lib $WDIR/lib64
# Create necessary device nodes
mknod -m 640 $WDIR/dev/console c 5 1
mknod -m 664 $WDIR/dev/null c 1 3
# Install the udev configuration files
if [ -f /etc/udev/udev.conf ]; then
cp /etc/udev/udev.conf $WDIR/etc/udev/udev.conf
fi
for file in $(find /etc/udev/rules.d/ -type f) ; do
cp $file $WDIR/etc/udev/rules.d
done
# Install any firmware present
cp -a /usr/lib/firmware $WDIR/usr/lib
# Copy the RAID configuration file if present
if [ -f /etc/mdadm.conf ] ; then
cp /etc/mdadm.conf $WDIR/etc
fi
# Install the init file
install -m0755 $DATADIR/$INITIN $WDIR/init
if [ -n "$KERNEL_VERSION" ] ; then
if [ -x /usr/bin/kmod ] ; then
binfiles="$binfiles kmod"
else
binfiles="$binfiles lsmod"
sbinfiles="$sbinfiles insmod"
fi
fi
# Install basic binaries
for f in $binfiles ; do
ldd /usr/bin/$f | sed "s/\t//" | cut -d " " -f1 >> $unsorted
copy /usr/bin/$f bin
done
for f in $sbinfiles ; do
ldd /usr/sbin/$f | sed "s/\t//" | cut -d " " -f1 >> $unsorted
copy $f sbin
done
# Add udevd libraries if not in /usr/sbin
if [ -x /usr/lib/udev/udevd ] ; then
ldd /usr/lib/udev/udevd | sed "s/\t//" | cut -d " " -f1 >> $unsorted
elif [ -x /usr/lib/systemd/systemd-udevd ] ; then
ldd /usr/lib/systemd/systemd-udevd | sed "s/\t//" | cut -d " " -f1 >> $unsorted
fi
# Add module symlinks if appropriate
if [ -n "$KERNEL_VERSION" ] && [ -x /usr/bin/kmod ] ; then
ln -s kmod $WDIR/usr/bin/lsmod
ln -s kmod $WDIR/usr/bin/insmod
fi
# Add lvm symlinks if appropriate
# Also copy the lvm.conf file
if [ -x /usr/sbin/lvm ] ; then
ln -s lvm $WDIR/usr/sbin/lvchange
ln -s lvm $WDIR/usr/sbin/lvrename
ln -s lvm $WDIR/usr/sbin/lvextend
ln -s lvm $WDIR/usr/sbin/lvcreate
ln -s lvm $WDIR/usr/sbin/lvdisplay
ln -s lvm $WDIR/usr/sbin/lvscan
ln -s lvm $WDIR/usr/sbin/pvchange
ln -s lvm $WDIR/usr/sbin/pvck
ln -s lvm $WDIR/usr/sbin/pvcreate
ln -s lvm $WDIR/usr/sbin/pvdisplay
ln -s lvm $WDIR/usr/sbin/pvscan
ln -s lvm $WDIR/usr/sbin/vgchange
ln -s lvm $WDIR/usr/sbin/vgcreate
ln -s lvm $WDIR/usr/sbin/vgscan
ln -s lvm $WDIR/usr/sbin/vgrename
ln -s lvm $WDIR/usr/sbin/vgck
# Conf file(s)
cp -a /etc/lvm $WDIR/etc
fi
# Install libraries
sort $unsorted | uniq | while read library ; do
# linux-vdso and linux-gate are pseudo libraries and do not correspond to a file
# libsystemd-shared is in /lib/systemd, so it is not found by copy, and
# it is copied below anyway
if [[ "$library" == linux-vdso.so.1 ]] ||
[[ "$library" == linux-gate.so.1 ]] ||
[[ "$library" == libsystemd-shared* ]]; then
continue
fi
copy $library lib
done
if [ -d /usr/lib/udev ]; then
cp -a /usr/lib/udev $WDIR/usr/lib
fi
if [ -d /usr/lib/systemd ]; then
cp -a /usr/lib/systemd $WDIR/usr/lib
fi
if [ -d /usr/lib/elogind ]; then
cp -a /usr/lib/elogind $WDIR/usr/lib
fi
# Install the kernel modules if requested
if [ -n "$KERNEL_VERSION" ]; then
find \
/usr/lib/modules/$KERNEL_VERSION/kernel/{crypto,fs,lib} \
/usr/lib/modules/$KERNEL_VERSION/kernel/drivers/{block,ata,nvme,md,firewire} \
/usr/lib/modules/$KERNEL_VERSION/kernel/drivers/{scsi,message,pcmcia,virtio} \
/usr/lib/modules/$KERNEL_VERSION/kernel/drivers/usb/{host,storage} \
-type f 2> /dev/null | cpio --make-directories -p --quiet $WDIR
cp /usr/lib/modules/$KERNEL_VERSION/modules.{builtin,order} \
$WDIR/usr/lib/modules/$KERNEL_VERSION
if [ -f /usr/lib/modules/$KERNEL_VERSION/modules.builtin.modinfo ]; then
cp /usr/lib/modules/$KERNEL_VERSION/modules.builtin.modinfo \
$WDIR/usr/lib/modules/$KERNEL_VERSION
fi
depmod -b $WDIR $KERNEL_VERSION
fi
( cd $WDIR ; find . | cpio -o -H newc --quiet | gzip -9 ) > $INITRAMFS_FILE
# Prepare early loading of microcode if available
if ls /usr/lib/firmware/intel-ucode/* >/dev/null 2>&1 ||
ls /usr/lib/firmware/amd-ucode/* >/dev/null 2>&1; then
# first empty WDIR to reuse it
rm -r $WDIR/*
DSTDIR=$WDIR/kernel/x86/microcode
mkdir -p $DSTDIR
if [ -d /usr/lib/firmware/amd-ucode ]; then
cat /usr/lib/firmware/amd-ucode/microcode_amd*.bin > $DSTDIR/AuthenticAMD.bin
fi
if [ -d /usr/lib/firmware/intel-ucode ]; then
cat /usr/lib/firmware/intel-ucode/* > $DSTDIR/GenuineIntel.bin
fi
( cd $WDIR; find . | cpio -o -H newc --quiet ) > microcode.img
cat microcode.img $INITRAMFS_FILE > tmpfile
mv tmpfile $INITRAMFS_FILE
rm microcode.img
fi
# Remove the temporary directories and files
rm -rf $WDIR $unsorted
printf "done.\n"
EOF
chmod 0755 /usr/sbin/mkinitramfs
mkdir -p /usr/share/mkinitramfs &&
cat > /usr/share/mkinitramfs/init.in << "EOF"
#!/bin/sh
PATH=/usr/bin:/usr/sbin
export PATH
problem()
{
printf "Encountered a problem!\n\nDropping you to a shell.\n\n"
sh
}
no_device()
{
printf "The device %s, which is supposed to contain the\n" $1
printf "root file system, does not exist.\n"
printf "Please fix this problem and exit this shell.\n\n"
}
no_mount()
{
printf "Could not mount device %s\n" $1
printf "Sleeping forever. Please reboot and fix the kernel command line.\n\n"
printf "Maybe the device is formatted with an unsupported file system?\n\n"
printf "Or maybe filesystem type autodetection went wrong, in which case\n"
printf "you should add the rootfstype=... parameter to the kernel command line.\n\n"
printf "Available partitions:\n"
}
do_mount_root()
{
mkdir /.root
[ -n "$rootflags" ] && rootflags="$rootflags,"
rootflags="$rootflags$ro"
case "$root" in
/dev/* ) device=$root ;;
UUID=* ) eval $root; device="/dev/disk/by-uuid/$UUID" ;;
PARTUUID=*) eval $root; device="/dev/disk/by-partuuid/$PARTUUID" ;;
LABEL=* ) eval $root; device="/dev/disk/by-label/$LABEL" ;;
"" ) echo "No root device specified." ; problem ;;
esac
while [ ! -b "$device" ] ; do
no_device $device
problem
done
if ! mount -n -t "$rootfstype" -o "$rootflags" "$device" /.root ; then
no_mount $device
cat /proc/partitions
while true ; do sleep 10000 ; done
else
echo "Successfully mounted device $root"
fi
}
do_try_resume()
{
case "$resume" in
UUID=* ) eval $resume; resume="/dev/disk/by-uuid/$UUID" ;;
LABEL=*) eval $resume; resume="/dev/disk/by-label/$LABEL" ;;
esac
if $noresume || ! [ -b "$resume" ]; then return; fi
ls -lH "$resume" | ( read x x x x maj min x
echo -n ${maj%,}:$min > /sys/power/resume )
}
init=/sbin/init
root=
rootdelay=
rootfstype=auto
ro="ro"
rootflags=
device=
resume=
noresume=false
mount -n -t devtmpfs devtmpfs /dev
mount -n -t proc proc /proc
mount -n -t sysfs sysfs /sys
mount -n -t tmpfs tmpfs /run
read -r cmdline < /proc/cmdline
for param in $cmdline ; do
case $param in
init=* ) init=${param#init=} ;;
root=* ) root=${param#root=} ;;
rootdelay=* ) rootdelay=${param#rootdelay=} ;;
rootfstype=*) rootfstype=${param#rootfstype=} ;;
rootflags=* ) rootflags=${param#rootflags=} ;;
resume=* ) resume=${param#resume=} ;;
noresume ) noresume=true ;;
ro ) ro="ro" ;;
rw ) ro="rw" ;;
esac
done
# udevd location depends on version
if [ -x /sbin/udevd ]; then
UDEVD=/sbin/udevd
elif [ -x /lib/udev/udevd ]; then
UDEVD=/lib/udev/udevd
elif [ -x /lib/systemd/systemd-udevd ]; then
UDEVD=/lib/systemd/systemd-udevd
else
echo "Cannot find udevd nor systemd-udevd"
problem
fi
${UDEVD} --daemon --resolve-names=never
udevadm trigger
udevadm settle
if [ -f /etc/mdadm.conf ] ; then mdadm -As ; fi
if [ -x /sbin/vgchange ] ; then /sbin/vgchange -a y > /dev/null ; fi
if [ -n "$rootdelay" ] ; then sleep "$rootdelay" ; fi
do_try_resume # This function will not return if resuming from disk
do_mount_root
killall -w ${UDEVD##*/}
exec switch_root /.root "$init" "$@"
EOF
现在可以构建initramfs
cd /boot
mkinitramfs
生成 /boot/grub/grub.cfg,这里需要获取到文件系统的UUID和分区的UUID,前面也已经通过blkid
获取到了,其中文件系统的UUID指UUID
,分区的UUID指PARTUUID
可以通过
cat > /boot/grub/grub.cfg << "EOF"
# Begin /boot/grub/grub.cfg
set default=0
set timeout=5
insmod part_gpt
insmod ext2
search --set=root --fs-uuid 315ffc52-a533-4a9d-954a-a1d6c891a25f
menuentry "GNU/Linux, Linux 6.10.5-lfs-12.2" {
linux /boot/vmlinuz-6.10.5-lfs-12.2 root=PARTUUID=0127e901-01 ro rootdelay=5
initrd /boot/initrd.img-no-kmods
}
EOF
收尾工作
创建/etc/lfs-release
来定义LFS系统版本
echo 12.2 > /etc/lfs-release
后续安装在系统上的软件包可能需要两个描述当前安装的系统的文件,这些软件包可能是二进制包,也可能是需要构建的源代码包。
第一个文件根据 Linux Standards Base (LSB) 的规则描述系统状态。运行命令创建该文件
修改DISTRIB_CODENAME
cat > /etc/lsb-release << "EOF"
DISTRIB_ID="Linux From Scratch"
DISTRIB_RELEASE="12.2"
DISTRIB_CODENAME="Miku"
DISTRIB_DESCRIPTION="Linux From Scratch"
EOF
第二个文件基本上包含相同的信息,systemd 和一些图形桌面环境会使用它。运行命令创建该文件
修改VERSION_CODENAME
cat > /etc/os-release << "EOF"
NAME="Linux From Scratch"
VERSION="12.2"
ID=lfs
PRETTY_NAME="Linux From Scratch 12.2"
VERSION_CODENAME="Finale"
HOME_URL="https://www.linuxfromscratch.org/lfs/"
EOF
现在所有工作都完成了,退出chroot环境
logout
解除虚拟文件系统的挂载
umount -v $LFS/dev/pts
mountpoint -q $LFS/dev/shm && umount -v $LFS/dev/shm
umount -v $LFS/dev
umount -v $LFS/run
umount -v $LFS/proc
umount -v $LFS/sys
解除 LFS 文件系统的挂载
umount -v $LFS
安装到虚拟硬盘上
之前已经安装好了整个LFS,但因为是在U盘上安装的,接下来会讲如何做可启动的镜像
首先确认LFS占用了多大空间,然后用dd
制作一个大小差不多的文件,这里选择30G
dd if=/dev/zero of=/path/to/your/img bs 1M count 30000
把这个文件挂载成回环设备,然后通过losetup -l
确认回环设备的名字,我的是/dev/loop0
losetup -fP /path/to/your/img
losetup -l
对这个回环设备进行分区操作
fdisk /dev/loop0
在这个块设备上建立一个分区,然后在这个分区上建立一个ext4
文件系统,我的分区名字叫做/dev/loop0p1
mkfs.ext4 /dev/loop0p1`
现在挂载这个分区
mount /dev/loop0p1 /mnt/temp/
把LFS复制到分区里
cp $LFS/* /mnt/temp
把环境变量$LFS改成现在这个目录,像之前一样挂载好内核虚拟文件系统,然后进入chroot环境
export LFS=/mnt/temp
mount -v --bind /dev $LFS/dev
mount -vt devpts devpts -o gid=5,mode=0620 $LFS/dev/pts
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
mount -vt tmpfs tmpfs $LFS/run
if [ -h $LFS/dev/shm ]; then
install -v -d -m 1777 $LFS$(realpath /dev/shm)
else
mount -vt tmpfs -o nosuid,nodev tmpfs $LFS/dev/shm
fi
chroot "$LFS" /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
PS1='(lfs chroot) \u:\w\$ ' \
PATH=/usr/bin:/usr/sbin \
MAKEFLAGS="-j$(nproc)" \
TESTSUITEFLAGS="-j$(nproc)" \
/bin/bash --login
现在再安装一遍GRUB,这样就可以用虚拟硬盘上的GRUB启动系统了
grub-install --boot-directory /boot --target i386-pc --allow-floppy /dev/loop0 --directory /usr/lib/grub/i386-pc
因为重新制作了文件系统,所以相应的/etc/fstab
和/boot/grub/grub.cfg
都需要像之前提到的一样修改
退出系统并卸载所有分区,现在可以用QEMU启动系统了
exit
umount -v $LFS/dev/pts
mountpoint -q $LFS/dev/shm && umount -v $LFS/dev/shm
umount -v $LFS/dev
umount -v $LFS/run
umount -v $LFS/proc
umount -v $LFS/sys
umount -v $LFS
losetup -d /dev/loop0
qemu-system-x86_84 -hda /path/to/your/img