[Tutorials] 搬运手工编译linux桌面内核(二)——硬件驱动的配置
Tofloor
poster avatar
jiutian123
deepin
2022-05-27 23:51
Author

手工编译linux桌面内核(二)——硬件驱动的配置

上篇前言:

关于硬件驱动的配置,这可真是千差万别了,基本上每个人不同的电脑都有不同的硬件,CPU、核心显卡、独立显卡、声卡、有线网卡、无线网卡、读卡器等等,几乎找不到一样的配置。所以我觉得这是整个系列中最难写的一篇文章了,我没有办法为你们提供一个通用的模板配置,只能是尽可能的详细阐述配置驱动的方法和总体原则,并且以我的硬件配置过程为例子供大家更好地理解我的方法。授人以鱼,不如授之以渔,不是吗?如果按照我在文末分享的驱动配置无脑照搬照抄,那么你的电脑是很有可能无法正常启动的,因为那是我的电脑配置,不是你的。

配置硬件驱动的总体原则是:除了只选中那些自己电脑硬件真正需要的驱动外,其它的硬件驱动一概全部禁用。 一般来说一台个人电脑所需要的linux内核树内驱动仅20-30项,而内核的源码树里却集成了多达3000-4000个驱动。要把这些数目巨大的驱动全部编译一遍真是可怕,反正genkernel就是这样干的,而且是强制你这样干,我的i5 8400 CPU编译这些驱动至少需要25分钟,然后给你全部打包生成一个265mb的initramfs,非常耗时间、浪费电,而且没有意义;所以你需要认真地筛选出自己硬件确实需要的少数几个驱动选项,再把其他绝大多数不需要的驱动全部禁用,精简你的内核。一旦经过这样的内核裁减过程后,你的内核体积将会显著的减小,随之编译内核的时间也会明显缩短,比如我的内核现在总共就只有10mb,编译不会超过4分钟。

注意精简硬件驱动并不会给内核带来性能上的提升,但是能有效的减小内核的体积,所以我还是建议你尝试着去精简一下的。 想要提升内核性能,请参阅本系列第一篇文章,并且尽量做到把所有驱动全部直接编译进内核中。

本文涉及的是内核配置中的“Device Drivers”这一块内容,在图中用白色标出了

老规矩,以下是我电脑的硬件配置——

零、驱动直接编译进内核(静态加载) vs. 编译为模块(动态加载)

这里我只说,编译为模块modules的缺点——“May result in performance losses due to the addition of an API layer and slightly more memory usage”,这是gentoo官方wiki的原话。当看到这句话时,我就打定主意要尽量将自己所需要的驱动全部编译进内核了,因为我是一个性能追求者,任何一点在我可控范围内的性能损失都是不允许的,哪怕是潜在的损失。

其实论配置的复杂程度,直接编译进内核和编译为模块两种方式并没多大的差异,无非就是选定选项时一个按Y键一个按M键的差别而已。所以既然都差不多,那么为什么不干脆全按Y键呢?而且我也鼓励你们去尝试,直到你可以在总界面里把“Enable loadable module support”这一项直接禁用,从而实现一个0模块的完整、真正意义上的宏内核。宏内核和微内核最大的差异就是,真正的宏内核由于不需要调用内核外的模块,而是直接调用已经编译集成到内核中的驱动,所以省去了加载模块的中间层api,从而节省了很多的CPU和内存开销,实现了高性能。 理论上通过中间层api调用的模块越多,需要耗费的CPU和内存资源也就越多,这对性能越不利,这个问题完全可以通过将驱动直接编译进内核中来规避。

也许有的人会指出,把所有功能和驱动全部直接编译进内核会造成内核臃肿的问题,但是我觉得那只是基于genkernel式的思维作出的假想推论罢了。如果你按照我这篇文章的方法,先认真仔细的精简禁用所有不需要的驱动,再把剩下真正需要的驱动全部编译进内核,且从此抛弃initramfs,这样下来即便是以压缩率最低的lzo算法压缩内核,最终你的单内核vmlinux的体积也不会超过25mb。所以根本不存在所谓“内核臃肿”的问题,而且内核开机加载速度会很快。不来尝试一下,怎么会知道结果呢?

一、如何寻找你的硬件驱动?

linux内核的硬件驱动配置,最困难的一关恰巧就是在这第一步——怎么才能准确且全面地找出每个硬件所需的驱动呢? 很多人就是因为找寻不到一个合适的方法,而卡死在了这一关,最终只能放弃,向genkernel妥协。如同宫崎老贼的《黑暗之魂》、《只狼》里的第一关boss,打的你毫无还手之力,直接劝退。

目前网上很多人给出的方法就是先lspci、lspci -k、lsusb -t查看自己硬件信息,然后再根据这些信息自己上网查资料找相应的驱动——你们是唬人玩呢?就像我lspci出来的19条硬件信息,让我一条一条复制下来上网查找,结果是很难找到多少完全符合的资料;而且lspci -k、lsusb -t所罗列出来的driver信息是不全面的,如果你单纯只是按照这些信息去配置内核的话,那么你最终会发现总有那么几个硬件是缺少驱动的。

所以自己没有具体尝试过的方法,就请不要不负责任地、不经思考地、人云亦云地传播了,这种简单、原始、低效、不准确的方法不知坑了多少配置内核的新手。 接下来我将会为大家呈现一种更加有效和准确的方法——直接去内核的源码树目录里寻找硬件驱动的文件名及其相应的内核配置项名称。直接从源头查找,得到的结果是最准确的,你需要两把瑞士军刀。

首先,有请本文的主人公1号上台——

#!/bin/sh
#
# Find all modules and drivers for a given class device.
#

if [ $# != "1" ] ; then
	echo
	echo "Script to display the drivers and modules for a specified sysfs class device"
	echo "usage: $0 "
	echo
	echo "example usage:"
	echo "      $0 sda"
	echo "Will show all drivers and modules for the sda block device."
	echo
	exit 1
fi

DEV=$1

if test -e "$1"; then
	DEVPATH=$1
else
	# find sysfs device directory for device
	DEVPATH=$(find /sys/class -name "$1" | head -1)
	test -z "$DEVPATH" && DEVPATH=$(find /sys/block -name "$1" | head -1)
	test -z "$DEVPATH" && DEVPATH=$(find /sys/bus -name "$1" | head -1)
	if ! test -e "$DEVPATH"; then
		echo "no device found"
		exit 1
	fi
fi

echo "looking at sysfs device: $DEVPATH"

if test -L "$DEVPATH"; then
	# resolve class device link to device directory
	DEVPATH=$(readlink -f $DEVPATH)
	echo "resolve link to: $DEVPATH"
fi

if test -d "$DEVPATH"; then
	# resolve old-style "device" link to the parent device
	PARENT="$DEVPATH";
	while test "$PARENT" != "/"; do
		if test -L "$PARENT/device"; then
			DEVPATH=$(readlink -f $PARENT/device)
			echo "follow 'device' link to parent: $DEVPATH"
			break
		fi
		PARENT=$(dirname $PARENT)
	done
fi

while test "$DEVPATH" != "/"; do
	DRIVERPATH=
	DRIVER=
	MODULEPATH=
	MODULE=
	if test -e $DEVPATH/driver; then
		DRIVERPATH=$(readlink -f $DEVPATH/driver)
		DRIVER=$(basename $DRIVERPATH)
		echo -n "found driver: $DRIVER"
		if test -e $DRIVERPATH/module; then
			MODULEPATH=$(readlink -f $DRIVERPATH/module)
			MODULE=$(basename $MODULEPATH)
			echo -n " from module: $MODULE"
		fi
		echo
	fi

	DEVPATH=$(dirname $DEVPATH)
done

这是一段bash脚本执行代码,摘自2006年的书籍《LINUX KERNEL IN A NUTSHELL》by Greg Kroah-Hartman,感兴趣的同学可以去网上搜搜看这本书,里面讲了很多实用的配置内核的方法,是一本很不错的入门书籍。这段代码的作用是,迅速地找出你的硬件所依赖的内核驱动的真正名称。请将这段代码保存到一个名为get-driver-name.sh的文件中,并赋予这个脚本文件可执行权限(chmod +x)。稍后这个可执行脚本会在你寻找硬件驱动的过程中成为你的最得力助手之一! 具体使用方法很快就会讲到了。

其次,还再请本文的主人公2号——

find -type f -name Makefile | xargs grep -w "+= <驱动名称>.o"     

这段命令的作用是,根据get-driver-name.sh脚本寻找到的硬件设备驱动名称,直接到内核的源码树目录里,读取内核的makefile,并从中找出驱动名称所对应的真正的内核选项名称。

接下来开始进入本文的主体内容。

二、具体的操作流程——以我的驱动配置为例

(一)首先请先切换到genkernel出来的内核

sudo genkernel --install all

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

sudo reboot

用genkernel生成一个大而全面的内核(vmlinux+initramfs),然后用这个内核开机加载进入系统。

注释:

#为什么我那么讨厌genkernel,却还是用到了它呢?因为genkernel内核里集成的硬件驱动非常全面,可以说是过于全面了,使用这种内核能最大限度地保证你的电脑硬件全部都被系统识别出来,并加载相应的内核驱动,这对于后续想要尽可能全面地找出所有硬件驱动是很重要的。想要使用我的方法去寻找驱动,前提得是你的硬件驱动已经被当前的系统内核识别并加载了,所以这里我们先要借助genkernel这个大而全面的平台。如果是连genkernel内核都识别不出来的硬件,那么我的方法就失效了,不过这种情况是很少的,除非你使用的是目前最新的硬件、或是非常古旧的硬件,一个是kernel社区还没来得及做出最新的驱动来、一个是社区已经把古旧的驱动淘汰了。

#建议你先在桌面上打开4个console终端窗口,每一个终端分别只打开一个固定的目录、用于执行一个固定的功能,以便于后面可以方便地来回切换,提高操作效率。假如你只用一个终端干活,那么后面频繁的cd切换目录命令会把你逼疯呢。

(二)利用get-driver-name.sh脚本快速寻找硬件驱动名称

Console 1:

cd /sys/class

ls

你会看到当前genkernel内核加载的所有硬件信息,里面每一个目录都代表了一个硬件设备类别(class),如block目录代表硬盘储存设备(块设备)、graphics目录代表显卡设备、sound代表声卡设备、net代表网卡设备、input代表输入设备(鼠标、键盘、触摸板)。ls查看其中的一个目录,你就会发现具体的硬件设备名是以子目录的形式被包含在这个目录中的。这些子目录代表的就是我们电脑真正的硬件设备了,因而是我们寻找硬件驱动的最关键线索,是key!

比方说,如果你想寻找硬盘的驱动,那么请看上图,里面是不是有一个block目录呢?这个目录里面包含的就是你电脑的所有块设备,即硬盘了。然后,执行命令

ls block/

看到了吗?其中的sda设备就是我的SSD硬盘,sdb设备是我的机械硬盘;其它带数字的那些是我硬盘上的各个分区,可以不用管它们。接下来要用到sda和sdb这两个设备名称。

Console 2:

cd <你保存get-driver-name.sh的所在目录>

sudo ./get-driver-name.sh sda

sudo ./get-driver-name.sh sdb

如你所见,脚本已经“found driver”了,找到了!于是我就知道了,我电脑硬盘需要的驱动一共有两个,名叫sd和ahci。

注释:

#我在寻找sd驱动时总是找不到,最后才发现sd驱动是一个名为sd_mod驱动的子驱动。所以特此提出,避免大家遭坑。

(三)根据找到的内核驱动名称,到内核的源码树目录里找出对应的内核选项名称

Console 3:

cd /usr/src/linux

sudo find -type f -name Makefile | xargs grep -w "+= sd_mod.o"

sudo find -type f -name Makefile | xargs grep -w "+= ahci.o"

可以看到,sd_mod驱动对应的是“CONFIG_BLK_DEV_SD”这一项内核配置选项,ahci驱动对应的是“CONFIG_SATA_AHCI”这一项。于是乎,驱动所对应的内核选项名称也就找到了。

(四)根据找到的内核选项名称,到内核配置界面中找出该选项

Console 4:

cd /usr/src/linux

sudo make menuconfig

你看到了熟悉的内核配置界面。

按下键盘上的“/”键,进入搜索界面

复制粘贴上一步里找到的内核选项名称,然后按Enter键确认“Ok”

可以看到,已经找到这两个选项的真正名称和所在的位置了。选项真正的名称紧随在“Prompt: ”之后,选项的位置紧随在“Location:”的下方,我已经用黑色给你们标出了。一般搜索出来排在第一条的结果就是你真正需要的驱动选项,下面的那两个选项都是与我的电脑无关的驱动,所以无视它们。

CONFIG_BLK_DEV_SD的真正名称叫“SCSI disk support”,位于Device Drivers-->SCSI device support的目录下。具体的选项名我已经用蓝色给你们标出来了。

选中“SCSI disk support”这一项,按Y键将其直接编译进内核。至于其余的无关的驱动,全部按N键禁用即可。

同理,CONFIG_SATA_AHCI的真正名称叫“AHCI SATA support”,位于Device Drivers-->Serial ATA and Parallel ATA drivers (libata)的目录下。具体的选项名我已经用蓝色给你们标出来了。

同样选中“AHCI SATA support”这一项,按Y键将其直接编译进内核。

其余的无关的驱动,全部按N键禁用。

(五)再来看另一个栗子

cd /sys/class

ls

这次我们随便选一个,选的是sound目录,里面包含的是我电脑里的所有声音设备。

ls sound/

这次我们看到我的声音设备一共有8个,真是多到头晕。怎么办呢?没办法,那还不是得把每一个设备的驱动全都依次找出来,不要偷懒哦,不然你很有可能会遗漏驱动。

cd <你保存get-driver-name.sh的所在目录>

sudo ./get-driver-name.sh card0

sudo ./get-driver-name.sh card1

sudo ./get-driver-name.sh controlC0

sudo ./get-driver-name.sh controlC1

sudo ./get-driver-name.sh pcmC0D0c

sudo ./get-driver-name.sh pcmC0D0p

sudo ./get-driver-name.sh pcmC1D3p

sudo ./get-driver-name.sh timer

然后你就会发现,尽管设备很多,但我的所有声音设备全都是共用同一个驱动snd_hda_intel,真是万幸,不然8个设备8个驱动还不得找疯掉。从这里也可以看出我的声卡是Intel HD Audio。

有的设备会没有驱动,即没有“found driver: ”的结果,就如图片里的最后一条timer设备。不要惊慌,这并不是因为没有找到驱动;而是因为这类设备是系统内核自己创建出来的虚拟设备,虚拟设备一般都是没有驱动的,只有真实的物理硬件设备才会需要有驱动。

cd /usr/src/linux

sudo find -type f -name Makefile | xargs grep -w "+= snd_hda_intel.o"

然后你就发现,没有任何结果?!

是因为内核源码里没有snd_hda_intel的驱动吗?还是因为这条命名是错误的呢?然而都不是。

你只需要把“snd_hda_intel”里的所有“_”全部替换为“-”,变为“snd-hda-intel”,再来执行一遍命令试试看。

sudo find -type f -name Makefile | xargs grep -w "+= snd-hda-intel.o"

看,这不是就有结果了吗?

所以在这里教大家一个小技巧,一旦遇到驱动文件名中带有下划线“”的,如果执行上述命令没有结果,那么就把下划线“”替换为段横线“-”,再重新执行一遍命令,就能出来结果了。

cd /usr/src/linux

sudo make menuconfig

按下键盘上的“/”键,进入搜索界面

复制粘贴上一步里找到的内核选项名称,然后按Enter键确认“Ok”

可以看到,CONFIG_SND_HDA_INTEL的真正名称叫“HD Audio PCI”,位于Device Drivers-->Sound card support-->Advanced Linux Sound Architecture-->HD-Audio的目录下。一般搜索出来排在第一条的结果就是你真正需要的驱动选项,后面的结果全都与你电脑无关,请直接无视。来一层一层地找吧,具体的选项名我已经用颜色给你们标出来了。

选中“HD Audio PCI”这一项,按Y键将其直接编译进内核。

同样的,同级目录下的其余全部都是无关的驱动,全部按N键禁用。

这里由于我的声卡解码芯片是Realtek的,所以也启用了“Build Realtek HD-audio codec support”这一项。

三、操作流程总结

1.用genkernel出来的内核加载登陆系统

genkernel --install all

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

sudo reboot

2.用get-driver-name.sh脚本寻找硬件驱动名称

cd /sys/class

ls

罗列出系统内所有的设备类别,以目录的方式呈现。

ls <其中任意一个设备类别目录>/

罗列出属于该设备类别旗下的所有硬件设备名称,以子目录的方式呈现。

cd <你保存get-driver-name.sh的所在目录>

sudo ./get-driver-name.sh <其中任意一个硬件设备名称>

得到属于该硬件设备的驱动名称,在“found driver”那一行里。

3.根据找到的设备驱动名称,到内核的源码树目录里找出对应的内核选项名称

cd /usr/src/linux

sudo find -type f -name Makefile | xargs grep -w "+= <驱动名称>.o"

得到相应的内核配置选项名称,为括号里的大写字符串。

4.根据得到的内核选项名称,到内核配置界面中找出该选项

cd /usr/src/linux

sudo make menuconfig

进入内核配置界面

按下键盘上的“/”键,进入搜索界面

复制粘贴上一步里找到的内核选项名称,然后按Enter键确认“Ok”进行搜索

得到驱动选项的具体信息,选项真正的名称紧随在“Prompt: ”之后,选项的位置紧随在“Location:”的下方。

一般搜索出来排在第一条的结果才是你真正需要的驱动选项,后面的结果全都无关,直接无视。

根据选项的位置信息,一层一层寻找到该驱动选项,最后按Y键选择将其直接编译进内核。其余的都是和你电脑无关的驱动,所以全部按N键禁用。

5.建议同时打开4个终端窗口,console1 cd到/sys/class目录下进行设备的查找、console2 cd到get-driver-name.sh脚本所在的目录用于执行脚本寻找驱动名、console3 cd到/usr/src/linux下用于执行find命令寻找内核选项名称、console4 cd到/usr/src/linux下打开内核配置界面进行驱动配置。这样操作效率会提高很多。

6.为了精简内核,除了保留电脑硬件必须的驱动外,我鼓励你放心大胆的禁用一切无关的驱动。

注释:

#get-driver-name.sh脚本的代码和命令find -type f -name Makefile | xargs grep -w "+= <驱动名称>.o",可以说是用于寻找内核硬件驱动的两把至关重要的“黄金钥匙”了。我建议你连同你的内核配置文件bak.config,妥善保管,可以作为传家宝了。

四、弊端和建议

回到第二步,cd到/sys/class目录下,执行ls命令,你得到的是这么多的目录。这意味着你的电脑里有n多的硬件设备被归类到了这么多的设备类别(class)里,所以可想而知你的硬件设备是有很多的,lspci和lsusb里罗列出来的硬件信息只是其中的一小部分。因此只靠lspci和lsusb来找驱动是不靠谱的!

比如我们再来看看input(输入设备)类别里究竟包含了多少硬件设备。

ls input/

怎么样?是不是感到很绝望?怎么会这么多?!!鼠标、键盘、触摸板还有其它,应有尽有,琳琅满目~~

所以仔细一想事情并不简单。我们来做个保守估计,假设你的/sys/class下一共有48个设备类别目录,而每一个类别下均包含有4个硬件设备,于是作乘法的结果就是——你的电脑里一共有192个设备!开不开心?快不快乐??当然其中的绝大部分都是系统内核自己创建的虚拟设备,不需要驱动。但还是有一部分真实物理硬件设备,这些设备就必须要求编译驱动了。

所以,你以为我提供给你的是一种简单且快速的方法吗?并不是的哦~尽管我的方法能够保证准确且全面的找出所有必要的硬件驱动,但我可从来没有说过我的方法很有效率哦~~我猜你们一定很绝望,好不容易知道了一个比较好的方法,好不容易终于能够自己独立地寻找配置硬件驱动,然而开始动手后才发现有那么多的设备等着你去找驱动。这就好比一个游戏新手卡关卡在了宫崎英高设计的《黑魂》系列或《只狼》的第一关boss那里,上网各种看视频、查攻略,最后习得了卡位、盾反、走位、闪避、甚至是卡bug的各种“奇淫技巧”,然后信心满满、屁颠屁颠地去挑战第一关boss了,结果打起来才发现——尽管你已经能够应对boss的各种攻击招式了,但是天哪boss的血量怎么会这么厚呀?!单凭你那羸弱的小身板、攻击力低下的普通小刀,到底什么时候才能把boss的血量削到0呢?

如果你们问我还有没有更有效率的方法呢?我的回答是——没有。。。

我的做法就是,按照上述流程,从头开始不停地机械重复“sudo ./get-driver-name.sh <设备名>”找驱动-->内核配置中选中驱动,直到把/sys/class下所有的类别目录里包含的总共200多个设备全部找了个遍,总共花了2个小时,才把驱动找全的,单纯的人力劳动。所以我终于过了第一关了!那么你呢?

“听说你们觉得linux内核的驱动配置简单?”

其实书籍《LINUX KERNEL IN A NUTSHELL》里还提供了一个自动化的找寻硬件驱动的脚本,名叫“find_all_modules.sh”。尽管出结果非常快,不到一秒钟的时间就全给你找出来了,但是其中却参杂了很多无关的驱动。比如我的电脑通过find_all_modules.sh找出了137项驱动出来,但是我手工找出来的明确用得到的驱动就只有24项,可想而知这个脚本是多么的不准确。脚本的代码如下——

#!/bin/bash
for i in `find /sys/ -name modalias -exec cat {} \;`; do
	/sbin/modprobe --config /dev/null --show-depends $i ;
done | rev | cut -f 1 -d '/' | rev | sort -u

所以实在是嫌麻烦的同学,可以用用这个脚本的。但是呢,让你到内核配置界面里去把这100多项驱动找出来也是非常费时间的,和通过人力到/sys/class里搜驱动的耗时基本上相差不了多少。所以考虑到精简内核,我觉得你不如和我一样老老实实地把自己电脑真正需要的20-30项驱动找出来,尽管耗费精力和时间,但是一旦完成后,把内核配置保存到bak.config文件里,那么你的配置就固定下来了,以后每次编译内核时就不用再重新配置一遍了。这是个一劳永逸的事情,所以值得去做,请耐心完成。

寻找驱动时请不要偷懒,请务必把/sys/class下所有类别目录里的所有设备全部过一遍,可以拿一张草稿纸记录下来进度,避免遗漏。因为说不定你遗漏掉的设备是真实的物理硬件设备,那么你就漏掉一个驱动了,后面出问题的时候再回头来找会很麻烦——你都记不得究竟是漏掉哪一个设备了,所以只能又从头开始找起,这是没有意义的。比如event0、event1、input3、input4这些名字毫不起眼的设备(路人甲、路人乙、路人丙、路人),你以为他们是虚拟设备可以跳过,但其实里面是有你的鼠标、键盘、触摸板这些物理硬件的!试想一下跳过的后果——满心欢喜的编译完内核重启电脑后,鼠标、键盘全都不能用,只能看着屏幕发呆。所以骚年,寻找、配置内核硬件驱动这一块是不存在所谓“逃课打法”滴~~

我的方法从效率上看着实令人着急,但是目前我找不到其他更快速有效的方法了。如果有人有更好的方法,请务必联系我或分享出来哦,真的感激不尽!

五、为硬件开启必要/额外的内核功能

如果你按照我的方法认真地寻找硬件驱动,那么是基本上能够保证能把所有驱动配置全的。但是有的硬件除了需要驱动之外,还要求你开启额外的内核功能,才能正常发挥作用。比如

input device(输入设备)驱动的界面里,如果你要使用桌面系统,除了键盘、鼠标、触摸板的驱动之外,你还得开启“Event interface”这一项功能。否则就会出现桌面系统下鼠标、键盘、触摸板完全无响应,但是在纯命令行tty系统界面下却能正常使用的问题。

查阅gentoo的官方wiki,你会看到wiki里已经明确写出了关于input_devices的内核配置要求

所以,如果你在配置完所有驱动后,却发现有几个硬件不能正常工作,那么极有可能是你没有把硬件要求的内核功能连同选中。那么你就得到gentoo的wiki里查找相关硬件的“Kernel options”,把缺漏的内核选项补上。

六、添加必要的硬件固件firmware

一些硬件除了要求有驱动外,还要求你把属于该硬件的固件firmware也一同编译进内核中。

首先你得把这些硬件的固件文件全部下载到你的/lib/firmware目录里,gentoo官方源里已经为你汇总打包好了所有的常用固件了。gentoo真良心,直接省去了你去网上一个一个搜索下载固件的麻烦。

sudo emerge sys-kernel/linux-firmware

来看看/lib/firmware目录里都有些什么

看到了吧,里面收集了当前主流硬件的所有固件。虽然看上去非常多,但一般每个人的电脑只需要其中的4-6个固件文件。

缺少了firmware,即便是你已经编译好驱动了,硬件还是不能正常工作。所以当你配置完内核驱动后,还是发现有几个硬件不能正常使用,那么除了可能缺漏了必要的内核功能外,还有可能就是你缺少这个硬件的firmware。这时你就得到gentoo的wiki里查找相关硬件的“Kernel options”了。

比如我电脑的wifi驱动

> 要求1:把/lib/firmware目录下的regulatory.db和regulatory.db.p7s这两个文件添加编译进内核中。

> 要求2:除了iwlwifi驱动之外,还得选上DVM和MVM这两个firmware固件一起编译。

> 要求3:把/lib/firmware目录下的iwlwifi-xxxx.ucode这个固件文件添加编译进内核中。(xxxx代表固件的型号和版本号)

再来看看Intel核心显卡的要求

> 要求你把/lib/firmware目录下的i915/skl_dmc_ver1_27.bin、i915/kbl_guc_ver9_33.bin和i915/kbl_huc_ver01_07_1398.bin这三个固件添加编译进内核中。

那么该怎么往内核中添加固件呢?很简单

首先在内核配置界面里顺着这个location层层查找:Device Drivers ---> Generic Driver Options ---> Firmware loader ---> Build named firmware blobs into the kernel binary

选中“Build named firmware blobs into the kernel binary”,按Enter键“Select”进入

然后复制粘贴上所需要的即可,最后“Ok”。每个固件文件名之间以“空格”相隔开。

注释:

#如果你想把硬件驱动直接编译进内核,那么硬件所需的firmware固件也必须一起添加编译进内核之中。但如果是把驱动编译为模块module,那么就不用这么费事,内核在加载驱动模块的时候就会顺带把firmware也自动加载上了。 所以你若是怕麻烦的话,大可把驱动编译为module动态加载,当然可能会牺牲内核的部分性能。

七、dmesg命令诊断驱动问题

在配置完所有的内核驱动、功能、固件之后,基本上算是大功告成了。接下来你就可以编译出你的定制内核来替换genkernel内核,开机加载进入系统了。

成功进入系统登陆桌面后,我建议你首先做的第一件事是:打开一个console,执行命令

sudo dmesg

来看看你的系统内核加载硬件驱动时是否存在问题

会滚动出很多条结果出来,这些结果反映的就是你的内核开机加载的整个过程。请耐心从上到下仔细检查,但凡发现用红色的字体显示的结果,务必留意。红色代表的意思是“error”,表示该项硬件驱动加载出错了,必须解决,否则硬件不能正常工作。

比如上图中我的声卡驱动snd_hda_intel就加载出错了,表现为电脑的扬声器、耳机都没有声音。

通过在网上查阅了很多资料,我终于找到了解决方法——修改grub(bootloader)的默认配置,在开机时通过grub向内核传递一项引导参数“snd_hda_intel.probe_mask=1”。具体的做法是

sudo vim /etc/default/grub:

GRUB_CMDLINE_LINUX_DEFAULT="snd_hda_intel.probe_mask=1"


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

sudo reboot

重启后,再次运行sudo dmesg

可以看到我的snd_hda_intel驱动能够正常加载了,没有红字输出。而且扬声器、耳机也有声音了。

至于那些加粗了字体的白色输出结果,则是代表“warning”信息,表示驱动没有完全正常的加载,但并不影响硬件正常发挥功能。有能力者可以去解决这个问题,让硬件完全正常地加载;没有能力解决的,也不会影响硬件正常工作。比如

这是我的nvidia独显闭源驱动的加载信息。因为nvidia的闭源驱动模块是一个linux内核树外驱动,而且其许可签名是“NVIDIA”,不符合linux内核标准树内驱动模块要求的“GPL”许可签名,所以内核认为nvidia驱动模块是一个来历不明的“野”驱动,可能会对系统造成损害。但是我的nvidia显卡是能够正常工作的,没有造成任何影响。

注释:

#关于我的intel无线网卡驱动iwlwifi,在执行dmesg诊断时会输出红色字体的“error”结果

#如图,“BIOS contains WGDS but no WRDS”,但是我却能够正常使用wifi。我去kernel、ubuntu、arch的社区查了论坛,才知道这是一个由来已久的bug。那就不管了,反正也不影响我正常用wifi,直接忽视掉吧。当然如果有人知道怎么解决这个问题,麻烦请留言分享~~

最后:

大家可以来扫一眼我大体上的驱动配置——

如你们所见,除了选中了少数与我电脑需要的驱动外,其它绝大部分无关的驱动一律被我禁用掉了。而且我把这些驱动全部直接编译进了内核里,没有任何一个模块module,干净整洁。

后记:

终于熬夜把最难的一篇文章写完了,花了我一天的时间。真是辛苦,睡了睡了~~

补充:

前段时间在翻看linux kernel document的时候无意间看到有“make localmodconfig”和“make localyesconfig”,大概意思就是系统自动检测现有内核加载了哪些模块,然后在内核源码的config设置里将已加载的模块自动标记为“M”或“*”,没加载的模块自动去除选择。我觉得这是个很有突破性的方案,自动配置内核驱动只可能比人工查找驱动手动配置内核快速高效100倍!!

所以大体思路就是——

1.先安装一个通用发行版如Fedora、Manjaro等;

2.从http://kernel.org下载一份内核源码;

3.将所有以后用到的硬件设备全部插到电脑上激活使用一遍(包括蓝牙、wifi、鼠标、u盘、拓展坞、摄像头等),让通用发行版的内核加载这些设备的驱动;

4.解压下载来的内核源码,执行“make localyesconfig”命令,完成后再执行“make menuconfig”命令,然后“save”你的内核配置,于是你就得到了一份专属于自己电脑的.config内核配置文件了,接下来只需要参考我第一篇里的优化方案设置内核就ok了。

附:make help的输出结果,作为参考和启发。

"make config"      Plain text interface.
"make menuconfig"  Text based color menus, radiolists & dialogs.
"make nconfig"     Enhanced text based color menus.
"make xconfig"     Qt based configuration tool.
"make gconfig"     GTK+ based configuration tool.
"make oldconfig"   Default all questions based on the contents of
                   your existing ./.config file and asking about
                   new config symbols.
"make olddefconfig"
                   Like above, but sets new symbols to their default
                   values without prompting.
"make defconfig"   Create a ./.config file by using the default
                   symbol values from either arch/$ARCH/defconfig
                   or arch/$ARCH/configs/${PLATFORM}_defconfig,
                   depending on the architecture.
"make ${PLATFORM}_defconfig"
                   Create a ./.config file by using the default
                   symbol values from
                   arch/$ARCH/configs/${PLATFORM}_defconfig.
                   Use "make help" to get a list of all available
                   platforms of your architecture.
"make allyesconfig"
                   Create a ./.config file by setting symbol
                   values to 'y' as much as possible.
"make allmodconfig"
                   Create a ./.config file by setting symbol
                   values to 'm' as much as possible.
"make allnoconfig" Create a ./.config file by setting symbol
                   values to 'n' as much as possible.
"make randconfig"  Create a ./.config file by setting symbol
                   values to random values.
"make localmodconfig" Create a config based on current config and
                      loaded modules (lsmod). Disables any module
                      option that is not needed for the loaded modules.

                      To create a localmodconfig for another machine,
                      store the lsmod of that machine into a file
                      and pass it in as a LSMOD parameter.

                      Also, you can preserve modules in certain folders
                      or kconfig files by specifying their paths in
                      parameter LMC_KEEP.

              target$ lsmod > /tmp/mylsmod
              target$ scp /tmp/mylsmod host:/tmp

              host$ make LSMOD=/tmp/mylsmod \
                      LMC_KEEP="drivers/usb:drivers/gpu:fs" \
                      localmodconfig

                      The above also works when cross compiling.

"make localyesconfig" Similar to localmodconfig, except it will convert
                      all module options to built in (=y) options. You can
                      also preserve modules by LMC_KEEP.
"make kvmconfig"   Enable additional options for kvm guest kernel support.
"make xenconfig"   Enable additional options for xen dom0 guest kernel
                   support.
"make tinyconfig"  Configure the tiniest possible kernel.
Reply Favorite View the author
All Replies
deepin-superuser
deepin
2022-05-28 00:01
#1

必须给个大大的赞like

Reply View the author
jjcui8595
deepin
2022-05-28 00:12
#2

适合于发烧友

Reply View the author
jiutian123
deepin
2022-05-28 00:18
#3
deepin-superuser

必须给个大大的赞like

大佬,原图特清晰的 但是复制粘贴过来就 不太清晰了 试了 网页打印pdf方式保存 图片也不太 清晰,,,有没有方法把原文板式 原图给原样给弄下来保存tail

Reply View the author
jiutian123
deepin
2022-05-28 00:19
#4
jjcui8595

适合于发烧友

也适合 想折腾 没办法的 人like

Reply View the author
deepin-superuser
deepin
2022-05-28 00:31
#5
jiutian123

大佬,原图特清晰的 但是复制粘贴过来就 不太清晰了 试了 网页打印pdf方式保存 图片也不太 清晰,,,有没有方法把原文板式 原图给原样给弄下来保存tail

看到 图片地址那里有个 _720w 没?删除掉就可以了

image.png

Reply View the author
jiutian123
deepin
2022-05-28 01:10
#6
deepin-superuser

看到 图片地址那里有个 _720w 没?删除掉就可以了

image.png

哦哦 我试试 谢谢指点tail

Reply View the author
jiutian123
deepin
2022-05-28 01:17
#7
deepin-superuser

看到 图片地址那里有个 _720w 没?删除掉就可以了

image.png

我点编辑帖子 没看到这个图片网址链接呀

Reply View the author
jiutian123
deepin
2022-05-28 01:57
#8
deepin-superuser

必须给个大大的赞like

00:1f.4 SMBus: Intel Corporation 100 Series/C230 Series Chipset Family SMBus (rev 31)

    Subsystem: CLEVO/KAPOK Computer 100 Series/C230 Series Chipset Family SMBus

** Kernel driver in use: i801_smbus**

    Kernel modules: i2c_i801

像这种内核驱动和模块驱动都有的 是不是两个驱动是通用的?内核模块没有搜索到,但是模块驱动搜到一模一样的了

Reply View the author
deepin-superuser
deepin
2022-05-28 02:54
#9
jiutian123

我点编辑帖子 没看到这个图片网址链接呀

image.png

类似这样的

image.png

Reply View the author
jiutian123
deepin
2022-05-28 22:44
#10
deepin-superuser

image.png

类似这样的

image.png

谢谢了 ,似乎论坛mark不支持替换功能

Reply View the author
jiutian123
deepin
2022-05-29 01:12
#11
deepin-superuser

必须给个大大的赞like


这个skl_uncore是个啥驱动呀 没找到一模一样的

Reply View the author
jiutian123
deepin
2022-06-02 22:16
#12
deepin-superuser

必须给个大大的赞like

像这样选好的 有没有办法原模原样 导出来 并且显示已选和未选?kissing_heart

Reply View the author
deepin-superuser
deepin
2022-06-02 23:06
#13
jiutian123

像这样选好的 有没有办法原模原样 导出来 并且显示已选和未选?kissing_heart

我不知道....

Reply View the author
jiutian123
deepin
2022-06-02 23:22
#14
deepin-superuser

我不知道....

好的 我再问问

Reply View the author
归暝
deepin
2022-06-03 19:53
#15

执行:find -type f -name Makefile | xargs grep -w "+= <驱动名称>.o"

显示:find: ‘./.config/browser/Default/virtual’: 权限不够

怎么办confused

Reply View the author
归暝
deepin
2022-06-03 19:59
#16
归暝

执行:find -type f -name Makefile | xargs grep -w "+= <驱动名称>.o"

显示:find: ‘./.config/browser/Default/virtual’: 权限不够

怎么办confused

已经执行了chmod +x get-driver-name.sh

Reply View the author
jiutian123
deepin
2022-06-03 21:30
#17
归暝

已经执行了chmod +x get-driver-name.sh

没图 不好看 只能猜 前面加sudo 提升权限

Reply View the author
归暝
deepin
2022-06-06 01:40
#18
jiutian123

没图 不好看 只能猜 前面加sudo 提升权限

截图_选择区域_20220605173955.png

Reply View the author
jiutian123
deepin
2022-06-06 02:22
#19
归暝

截图_选择区域_20220605173955.png

sudo su

以后再使用 加sudo 我也遇到过说权限不够的 不知为何

Reply View the author