Gentoo genkernel
在解决 Gentoo Linux在MacBook Pro配置Wifi 安装 net-wireless/broadcom-sta
( Broadcom 的私有 wl
驱动),需要完成内核编译。为了方便完成内核编译,按照推荐先安装 sys-kernel/genkernel
,然后使用这个工具来完成自动的内核编译
genkernel
是一个由Gentoo创建的用于自动化完成 Kernel 和 initramfs 构建的工具:
配置内核源代码
编译压缩的内核
bzImage
并复制到/boot
创建 initramfs 并复制到
/boot
在
/boot
中创建软链接添加指向initramfs的定制内容,例如加密相关文件,启动splash图像,扩展模块等
配置bootloader来启动新创建的kernel和initramfs
备注
genkernel
并不是 "自动" 生成自定义内核配置,它只是自动执行内核构建过程并组装initramfs,所以并不会生成自定义配置文件。
如果没有提供内核配置,那么 genkernel
将使用 "通用内核配置" (generic kernel configuration) 文件,来生成适合日常使用的通用内核(代价就是非常大的模块化内核)
genkernel
的 initramfs
也是如此: initramfs 主要用途 是 调用挂载包含根文件系统的块设备,以便能够尽快将控制权转交给真实的系统(磁盘上的操作系统)
安装
安装
genkernel
:
genkernel
emerge --ask sys-kernel/genkernel
使用
genkernel
的大多数选线可以在 /etc/genkernel.conf
配置,或者通过 genkernel
命令参数传递。通过命令行参数传递的选项优先级高于配置文件
内核源代码
首先在系统中安装内核源代码:
emerge --ask sys-kernel/gentoo-sources
备注
在 在MacBook Pro上安装Gentoo Linux 安装的内核是 Distribution Kernel
,也就是通用的(庞大的) sys-kernel/gentoo-kernel
。需要注意这个 sys-kernel/gentoo-kernel
也是源代码,只不过gentoo为原生内核源代码打过补丁,并且每次(重新)安装 sys-kernel/gentoo-kernel
都会全面重新编译一次内核,这个内核编译是不需要任何人工干预的,编译生成的是最通用的内核。类似于其他发行版,如 Ubuntu Linux 安装的发行版内核
编辑
/etc/genkernel.conf
参考注释修改配置参数:
/etc/genkernel.conf
# 在编译内核前先运行 'make menuconfig' 以便微调配置
MENUCONFIG="yes"
# 内核编译前不执行 'make mrproper'
# 有关 make clean, make mrproper 和 make distclean 区别参考 https://blog.csdn.net/yi412/article/details/34900267
MRPROPER="no"
# 编译并发通常设置 <number of processors>*<number of cores per processor>+1
# 默认配置 MAKEOPTS="$(portageq envvar MAKEOPTS)" 就可以,能够自动计算出系统cpu core数量,除非你想限制少用一些cpu core
# Add LVM support: 我使用ZFS,所以去掉了LVM支持
LVM="no"
# Add LUKS support: Linux Unified Key Setup(LUKS) 是加密存储子系统 dm-crypt 所需,我没有用
LUKS="no"
# Add DMRAID support: device-mapper raid 我没有使用
DMRAID="no"
# Include busybox in the initramfs. If included, busybox is rebuilt
# if the cached copy is out of date.
BUSYBOX="yes"
UDEV="yes"
# Add MDRAID support: 我不使用software raid
MDADM="no"
# Add firmware(s) to initramfs
FIRMWARE="no"
执行创建内核:
genkernel all
采用 在MacBook Pro上安装Gentoo Linux 同样的 efibootmgr
设置启动,不过需要注意内核名称稍微有所调整(因为编译配置时修改了后缀名):
genkernel
新编译的内核efibootmgr --disk /dev/sda --part 1 --create --label "Gentoo Linux" --loader /vmlinuz-6.1.67-gentoo-x86_64 --unicode \
'root=PARTUUID=1c16164d-fab1-49f8-8d95-7c7dd02ec8ed rw initrd=\initramfs-6.1.67-gentoo-x86_64.img' --verbose
报错: failed to compile the "prepare" target
首次使用 genkernel all
遇到报错:
* >> Kernel config was not modified!
* ERROR: compile_generic() failed to compile the "prepare" target!
* Please consult '/var/log/genkernel.log' for more information and any
* errors that were reported above.
*
* Report any genkernel bugs to bugs.gentoo.org and
* assign your bug to genkernel@gentoo.org. Please include
* as much information as you can in your bug report; attaching
* '/var/log/genkernel.log' so that your issue can be dealt with effectively.
*
* Please do *not* report kernel compilation failures as genkernel bugs!
检查 /var/log/genkernel.log
:
genkernel.log
错误COMMAND: nice -n10 make -j4 ARCH='x86' AS='x86_64-pc-linux-gnu-as' AR='x86_64-pc-linux-gnu-ar' CC='x86_64-pc-linux-gnu-gcc' LD='x86_64-pc-linux-gnu-ld' NM='x86_64-pc-linux-gnu-nm' OBJCOPY='x86_64-pc-linux-gnu-objcopy' OBJDUMP='x86_64-pc-linux-gnu-objdump' READELF='x86_64-pc-linux-gnu-readelf' STRIP='x86_64-pc-linux-gnu-strip' HOSTAR='x86_64-pc-linux-gnu-ar' HOSTCC='x86_64-pc-linux-gnu-gcc' HOSTCXX='x86_64-pc-linux-gnu-g++' HOSTLD='x86_64-pc-linux-gnu-ld' prepare
make[1]: *** No rule to make target 'arch/x86/entry/syscalls/syscall_32.tbl', needed by 'arch/x86/include/generated/uapi/asm/unistd_32.h'. Stop.
make: *** [arch/x86/Makefile:242: archheaders] Error 2
* ERROR: compile_generic() failed to compile the "prepare" target!
参考 make[1]: *** No rule to make target 原因是系统中安装了两个Kernel source: 之前 在MacBook Pro上安装Gentoo Linux 安装了 Distribution Kernel
,也就是 sys-kernel/gentoo-kernel
,然后我又安装了 sys-kernel/gentoo-sources
,所以执行:
eselect kernel
检查系统中内核源代码eselect kernel list
输出显示:
eselect kernel
可以看到当前内核源代码是发行版内核Available kernel symlink targets:
[1] linux-6.1.67-gentoo
[2] linux-6.1.67-gentoo-dist *
此时检查 ls -lh /usr/src/linux
可以看到引用的是 -dist
内核:
lrwxrwxrwx 1 root root 24 Dec 17 15:22 /usr/src/linux -> linux-6.1.67-gentoo-dist
解决方法是修改 eselect kernel
,然后删除掉发行版源代码内核
修改成 kernel-srouce
:
kernel-source
源代码eselect kernel set 1
现在再次检查 eselect kernel list
输出就可以看到切换到了标准内核:
eselect kernel
可以看到当前内核源代码切换到标准内核Available kernel symlink targets:
[1] linux-6.1.67-gentoo *
[2] linux-6.1.67-gentoo-dist
此时可以手工删除 保留 /usr/src/linux-6.1.67-gentoo-dist
(只要安装了 sys-kernel/gentoo-kernel
这个目录即使手工删除也会在 升级Gentoo 时重新编译 gentoo-kerenl
发行版kernel,再次生成)
升级内核
我在部署初期Gentoo提供的内核是 6.1.67 ,但是近期升级提供了 6.6.9 ,我将原先 /usr/src/linux-6.1.67-gentoo
目录下 .config
复制到新的 /usr/src/linux-6.6.9-gentoo
目录下(以便减少重新配置项),然后执行 genkernel all
。
调用 make menuconfig
没有问题,正常的交互界面,稍作修改后,我保存退出。此时 genkernel
开始执行下一步时候报错:
genkernel
报错显示缺少 CONFIG_MICROCODE_AMD
配置项* >> Re-running 'make oldconfig' due to changed kernel options ...
* ERROR: Something went wrong: Required kernel option 'CONFIG_MICROCODE_AMD' which genkernel tried to set is missing!
* Please consult '/var/log/genkernel.log' for more information and any
* errors that were reported above.
...
检查 /var/log/genkernel.log
有报错详情:
genkernel.log
日志中有关 MICROCODE
错误#
# No change to .config
#
* >> Invoking menuconfig ...
COMMAND: nice -n10 make -j8 -s -j1 ARCH='x86' AS='x86_64-pc-linux-gnu-as' AR='x86_64-pc-linux-gnu-ar' CC='x86_64-pc-linux-gnu-gcc' LD='x86_64-pc-linux-gnu-ld' NM='x86_64-pc-linux-gnu-nm' OBJCOPY='x86_64-pc-linux-gnu-objcopy' OBJDUMP='x86_64-pc-linux-gnu-objdump' READELF='x86_64-pc-linux-gnu-readelf' STRIP='x86_64-pc-linux-gnu-strip' HOSTAR='x86_64-pc-linux-gnu-ar' HOSTCC='x86_64-pc-linux-gnu-gcc' HOSTCXX='x86_64-pc-linux-gnu-g++' HOSTLD='x86_64-pc-linux-gnu-ld' menuconfig
* >> Ensure that required kernel options for genkernel's initramfs usage are set ...
* - Option 'CONFIG_BLK_DEV_INITRD=y' already set in '/usr/src/linux/.config'; Skipping ...
* - Option 'CONFIG_MMU=y' already set in '/usr/src/linux/.config'; Skipping ...
* - Option 'CONFIG_SHMEM=y' already set in '/usr/src/linux/.config'; Skipping ...
* - Option 'CONFIG_TMPFS=y' already set in '/usr/src/linux/.config'; Skipping ...
* - Option 'CONFIG_TTY=y' already set in '/usr/src/linux/.config'; Skipping ...
* - Option 'CONFIG_UNIX98_PTYS=y' already set in '/usr/src/linux/.config'; Skipping ...
* Determining 'BEST' compression method for initramfs using kernel config '/usr/src/linux/.config' ...
* Checking if we can use 'XZ' compression ...
* Will use 'XZ' compression -- all requirements are met!
* - Option 'CONFIG_RD_XZ=y' already set in '/usr/src/linux/.config'; Skipping ...
* >> Ensure that CONFIG_LOCALVERSION is set ...
* - Option 'CONFIG_LOCALVERSION="-x86_64"' already set in '/usr/src/linux/.config'; Skipping ...
* >> Ensure that required kernel options for early microcode loading support are set ...
* - Option 'CONFIG_MICROCODE=y' already set in '/usr/src/linux/.config'; Skipping ...
* - Adding option 'CONFIG_MICROCODE_AMD' with value 'y' to '/usr/src/linux/.config'...
* - Adding option 'CONFIG_MICROCODE_INTEL' with value 'y' to '/usr/src/linux/.config'...
* >> Re-running 'make oldconfig' due to changed kernel options ...
COMMAND: nice -n10 make -j8 ARCH='x86' AS='x86_64-pc-linux-gnu-as' AR='x86_64-pc-linux-gnu-ar' CC='x86_64-pc-linux-gnu-gcc' LD='x86_64-pc-linux-gnu-ld' NM='x86_64-pc-linux-gnu-nm' OBJCOPY='x86_64-pc-linux-gnu-objcopy' OBJDUMP='x86_64-pc-linux-gnu-objdump' READELF='x86_64-pc-linux-gnu-readelf' STRIP='x86_64-pc-linux-gnu-strip' HOSTAR='x86_64-pc-linux-gnu-ar' HOSTCC='x86_64-pc-linux-gnu-gcc' HOSTCXX='x86_64-pc-linux-gnu-g++' HOSTLD='x86_64-pc-linux-gnu-ld' oldconfig
#
# configuration written to .config
#
* >> Checking if required kernel options are still present ...
* - 'CONFIG_TMPFS' is set to 'y'
* - 'CONFIG_TTY' is set to 'y'
* - 'CONFIG_UNIX98_PTYS' is set to 'y'
* - 'CONFIG_MICROCODE' is set to 'y'
* ERROR: Something went wrong: Required kernel option 'CONFIG_MICROCODE_AMD' which genkernel tried to set is missing!
* Please consult '/var/log/genkernel.log' for more information and any
* errors that were reported above.
这个问题在以下帖子中讨论:
原因是 CONFIG_MICROCODE_AMD
和 CONFIG_MICROCODE_INTEL
已经从内核中移除
解决方法
传递
--microcode=none
参数给genkernel
:
genkernel --micorcode=none
genkernel all --microcode=none
或者 修订
/etc/genkernel.conf
配置:
/etc/genkernel.conf
设置 MICROCODE="none"# Add in early microcode support: this sets the kernel options for early microcode loading
# Possible values: empty/"no", "all", "intel", "amd"
#MICROCODE="all"
MICROCODE="none"
genkernel
生成 initramfs
使用 genkernel
还可以用来构建 initramfs :