linux没有网卡驱动能pxe吗,PXE所需要的网卡驱动制作

2023-05-16

对PXE 来说:

vmlinuz:就是引导内核文件

initr.img:就是驱动文件

如果遇到机器网卡不被PXE支持怎么办?

解决思路

如果熟悉 Linux 的启动过程和驱动程序,那么要解决本文的问题,基本上有两条路可走。第一就是将网卡驱动编译进内核(静态链接进内核),第二种方法就是将网卡驱动做成模块,然后想办法在 Linux 启动的时候让 Linux 内核能找到并挂载该驱动。面对这两种方案,第二种方法有更好的可行性和扩展性。因为首先有些网卡驱动本身就不能被静态链接进入内核,而只能被编译成一个模块,例如下文要举的例子 - e1000 网卡驱动;其次,驱动做成模块的方式,可以适应多个内核版本,用方法 1,更换一个内核版本就要重新编译一次内核;最后,等会会看到,相比编译内核,方法 2 更简单和可操作。

方法 2 的实现手段就是定制 initrd.img,将我们的网卡驱动加进去。initrd.img 是一个小型的根文件系统,在 Linux 内核没有挂载硬盘上的根分区的时候,initrd.img 将在内存中展开。一般情况下,initrd.img 中将包含一些必需的命令和驱动,如 insmod 命令和磁盘驱动。有了 insmod,才能将磁盘驱动挂载进内核,有了磁盘驱动,内核才能挂载位于磁盘上的根文件系统。

大部分的 Linux 发行版都提供了用于网络安装 Linux 的 initrd.img,一般位于第一张安装光盘的 images/pxeboot 目录下。在一台已经装好 Linux 的机器中,在 /boot 目录下我们也能找到 initrd.img,比较一下这两个 initrd.img,会发现 pxeboot 目录下的 initrd.img 会比 /boot 下的大很多,这是因为在网络安装的情况下,Linux 不会尝试去挂载位于磁盘上的根分区(事实上,在没有安装Linux的机器上,此时磁盘中可能什么数据都没有),所以此时的 initrd.img 需要包含大量的驱动,使 Linux 能识别大量的硬件。位于 /boot 下的 initrd.img,基本上唯一需要的东西就是磁盘驱动,只要内核能访问磁盘,那么其余所需的东西都可以从磁盘取得而不需要依赖 initrd.img。

--------------------------------------------------------------------------------

具体操作和实例

从安装光盘中取得 initrd.img 之后,就可以开始对其进行定制。这里要感谢 Jeremy Mates,他写的 initrd-util.sh 能很好的解开和生成一个 initrd.img。脚本可以在下载到。

下面我们以RedHat Enterprise Linux Advance Server 4 Update 2 x86_64,Intel e1000网卡驱动为例,讲述具体的操作过程(在本例中,服务器和客户机拥有相同的Intel e1000网卡,而且我们已经手动在服务器上安装完成了正确的e1000驱动):

首先从光盘取到initrd.img,登录到服务器,然后用initrd-util.sh解开:

命令输出 1. 解开initrd.img

[root@ericvm ~]# cd `./initrd-util.sh unpack initrd.img |tail -1`

info: initrd unpack expanded into: /var/tmp/initrd-util.workdir.DA29317

[root@ericvm initrd-util.workdir.DA29317]# pwd

/var/tmp/initrd-util.workdir.DA29317

[root@ericvm initrd-util.workdir.DA29317]# ls

2.6.9-22.EL  bin  dev  etc  linuxrc  lost+found  modules

proc  sbin  selinux  sys  tmp  var

initrd-util.sh很简单,利用gunzip, mount和cpio这些工具将initrd.img解开,其中驱动包位于modules目录下,名为modules.cgz,将这个文件解开后,生成了2.6.9-22.EL目录,进入该目录,就能找到包含在initrd.img中的驱动。本例中,RedHat已经包含了一个e1000的驱动,但是这个驱动不能驱动我们新的Intel e1000网卡。为此,我们在e1000网站下载新版的驱动,然后在服务器上编译完成,生成ko模块文件,然后拷贝到2.6.9-22.EL目录下,覆盖原文件即可。

驱动更新完毕后,现在我们需要将2.6.9-22.EL这个目录重新制作成modules.cgz,这个功能initrd-util.sh不能为我们完成,所以我们手动操作:

命令输出 2. 加入驱动并重新打包

[root@ericvm initrd-util.workdir.DA29317]# find 2.6.9-22.EL | cpio -o -H crc > newmodules

16582 blocks

[root@ericvm initrd-util.workdir.DA29317]# gzip -n -9 newmodules

[root@ericvm initrd-util.workdir.DA29317]# mv newmodules.gz modules

[root@ericvm initrd-util.workdir.DA29317]# cd modules

[root@ericvm modules]# rm -f modules.cgz

[root@ericvm modules]# mv newmodules.gz modules.cgz

[root@ericvm modules]# pwd

/var/tmp/initrd-util.workdir.DA29317/modules

驱动包重新生成了并不意味着Linux就可以识别网卡了,因为Linux必须依靠一种逻辑,将硬件设备和驱动模块文件对应起来。这个逻辑就被定义在modules目录下的除modules.cgz之外的文件中:

命令输出 3. 设备驱动识别信息文件

[root@ericvm modules]# ls

module-info  modules.cgz  modules.dep  modules.pcimap  modules.usbmap  pci.ids  pcitable

如上所示,pcitable, modules.pcimap中定义了PCI设备和驱动模块之间的对应关系,modules.dep中定义了模块和模块之间的依赖关系(比如,各种SCSI设备都会依赖一个基础的SCSI驱动模块),module-info中定义了驱动的静态描述信息......

要填写这些文本文件,也很简单,首先我们必须要知道这块e1000网卡的PCI设备信息,由于在服务器上e1000这块网卡已经安装完成了,所以我们可以在服务器上取到我们想要的信息:

命令输出 4. 查看网卡硬件信息

[root@ericvm ~]# lspci

............  ignore some outputs

04:00.0 Ethernet controller: Intel Corporation Enterprise Southbridge DPT LAN Copper

04:00.1 Ethernet controller: Intel Corporation Enterprise Southbridge DPT LAN Copper

............  ignore some outputs

lspci列出了服务器上两块网卡的设备信息,根据网卡设备的ID号码(04:00.0, 04:00.1),我们就可以在lspci –n的输出中找到设备的vendor code和device code(请参考lspci的manual了解lspci):

命令输出 5. 查看网卡code

[root@ericvm ~]# lspci –n

............  ignore some outputs

04:00.0 Class 0200: 8086:1096 (rev 01)

04:00.1 Class 0200: 8086:1096 (rev 01)

............  ignore some outputs

在lspci –n的输出中,我们找到了两块网卡的vendor code和device code – 8086和1096。得到了vendor code和device code之后,就可以更新initrd.img中modules目录下的pcitable, modules.pcimap等这些文件了。举例来说,在pcitable中查找e1000,能发现很多设备和e1000这个驱动关联,但是唯独没有8086:1096的组合,这就是为什么Linux无法驱动这块e1000网卡的原因了,我们需要手动将8086, 1096这两个code加入到pcitable中,并将这个设备对应到e1000驱动上。照此方法,更新其余的文件,如module-info, modules.pcimap等。

这样我们就完成了对initrd.img的完全修改,用initrd-util.sh重新将目录打包,生成一个新的initrd.img:

命令输出 6. 重新生成initrd.img

[root@ericvm ~]# ./initrd-util.sh pack /var/tmp/initrd-util.workdir.DA29317/

notice: new initrd size: 6144K

6144+0 records in

6144+0 records out

mke2fs 1.35 (28-Feb-2004)

info: initrd packed into: /var/tmp/initrd-util.initrd-new.IV29439.gz

/var/tmp/initrd-util.initrd-new.IV29439.gz

[root@ericvm ~]# ls -lh /var/tmp

total 3.7M

-rw-r--r--   1 root root 3.7M Jun 20 17:10 initrd-util.initrd-new.IV29439.gz

drwxr-xr-x  12 root root 4.0K Jun 20 17:10 initrd-util.workdir.DA29317

drwxr-xr-x  13 root root 4.0K Jun 20 15:53 initrd-util.workdir.ID29288

initrd-util.sh首先创建一个“空洞文件”,然后在这个文件中建立ext2 文件系统,然后将这个文件mount到一个目录中,最后用rsync这种方式将我们更新过的文件“拷贝”到了mount的目录下,这样“空洞”文件中就有了内容,最后对文件进行压缩,生成最终的img文件。

将/var/tmp/initrd-util.initrd-new.IV29439.gz改名成initrd.img,放到tftp配置的目录下,就可以让客户机在网络启动的时候取到新的initrd.img了,从而识别网卡开始网络安装。

--------------------------------------------------------------------------------

回页首

到此为止了么?

到目前为止,一切看起来都很好。客户机通过网络启动,能把网卡驱动起来并从服务器上得到所有需要的东西,并开始安装。但是,如果没有做特殊处理的话,客户机上Linux安装完成后,启动进入Linux,会发现网卡依旧驱动不了,典型的出错信息就是“无法成功挂载XXX驱动”,“ethX的MAC地址和预计的不一样”等。出现这样问题的原因很简单,这是因为正确的网卡驱动只存在于服务器上的 initrd.img 中,而没有体现到客户机的硬盘上。客户机在网络启动的时候得到了服务器上的 initrd.img,但 Linux 还没有智能到能自动解开这个 initrd.img 并将里面的驱动拷贝到客户机的硬盘上。一旦客户机完成安装重启,从硬盘启动之后,所有的驱动文件和信息就都从硬盘读取了。

还举刚才的例子,e1000 网卡驱动在 RedHat 中其实自带就有一个,但不适用于我们的 Intel e1000 网卡,用 rpm 命令可以查到安装在硬盘上的这个 e1000 驱动属于哪个RPM包:

命令输出 7. 查看驱动所在的 RPM 包

# rpm -qf /lib/modules/2.6.9-42.ELsmp/kernel/drivers/net/e1000/e1000.ko

kernel-smp-2.6.9-42.EL

所以,很明显的就是,要解决这样的问题,我们需要重新生成这个 kernel RPM 包。但是要在 RPM 包中替换一个文件,或是加入一个文件,可不像在 RAR 文件中用鼠标直接拖拽那么简单。有兴趣的可以参考 RPM 的相关资料。

除了重新生成 RPM 之外,还有一些简单的办法也是可行的,但不如重新生成 RPM 来的中规中矩。有兴趣的读者可以和我交流,这里就不赘述了。

参考资料

Jeremy Mates的initrd-utils, ,帮助我们创建/解开 initrd.img

Adding driver modules to a Fedora Core 2 CD for kickstart install:

实际制作案例:

网络安装 RedHat 4.8 支持82578DM网卡芯片

一 编译网卡驱动

使用2.6.9-89.EL 内核进入系统,

下载INTEL e1000e-1.1.2源码安装包 (或者更高版本)

yum groupinstall “Development Tools” -y

yum install kernel-devel -y

tar vxf e1000e-1.1.2.tar.gz

cd e1000e-1.1.2/src

make install

安装结束之后会新建一个/lib/modules/2.6.18-53.el5/kernel/drivers/net/e1000e/e1000e.ko模块文件,这个文件做为initrd.img的e1000e.ko网卡驱动(与平时使用的2.6.9-89.ELsmp内核系统的e1000e.ko不同)。

二从光盘取到initrd.img,登录到服务器,然后用initrd-util.sh解开:

命令输出 1. 解开initrd.img

[root@ericvm ~]# cd `./initrd-util.sh unpack initrd.img |tail -1`

info: initrd unpack expanded into: /var/tmp/initrd-util.workdir.DA29317

[root@ericvm initrd-util.workdir.DA29317]# pwd

/var/tmp/initrd-util.workdir.DA29317

[root@ericvm initrd-util.workdir.DA29317]# ls

2.6.9-22.EL  bin  dev  etc  linuxrc  lost+found  modules

proc  sbin  selinux  sys  tmp  var

initrd- util.sh很简单,利用gunzip, mount和cpio这些工具将initrd.img解开,其中驱动包位于modules目录下,名为modules.cgz,将这个文件解 开后,生成了 2.6.9-22.EL目录,进入该目录,就能找到包含在initrd.img中的驱动。本例中,RedHat已经包含了一个e1000的驱动,但是这个 驱动不能驱动我们新的Intel e1000网卡。为此,我们在e1000网站下载新版的驱动,然后在服务器上编译完成,生成ko模块文件,然后拷贝到2.6.9-22.EL目录下,覆盖 原文件即可。

驱动更新完毕后,现在我们需要将2.6.9-22.EL这个目录重新制作成modules.cgz,这个功能initrd-util.sh不能为我们完成,所以我们手动操作:

命令输出 2. 加入驱动并重新打包

[root@ericvm initrd-util.workdir.DA29317]# find 2.6.9-22.EL | cpio -o -H crc > newmodules

16582 blocks

[root@ericvm initrd-util.workdir.DA29317]# gzip -n -9 newmodules

[root@ericvm initrd-util.workdir.DA29317]# mv newmodules.gz modules

[root@ericvm initrd-util.workdir.DA29317]# cd modules

[root@ericvm modules]# rm -f modules.cgz

[root@ericvm modules]# mv newmodules.gz modules.cgz

[root@ericvm modules]# pwd

/var/tmp/initrd-util.workdir.DA29317/modules

驱动包重新生成了并不意味着Linux就可以识别网卡了,因为Linux必须依靠一种逻辑,将硬件设备和驱动模块文件对应起来。这个逻辑就被定义在modules目录下的除modules.cgz之外的文件中:

命令输出 3. 设备驱动识别信息文件

[root@ericvm modules]# ls

module-info  modules.cgz  modules.dep  modules.pcimap  modules.usbmap  pci.ids  pcitable

如 上所示,pcitable, modules.pcimap中定义了PCI设备和驱动模块之间的对应关系,modules.dep中定义了模块和模块之间的依赖关系(比如,各种 SCSI设备都会依赖一个基础的SCSI驱动模块),module-info中定义了驱动的静态描述信息......

要填写这些文本文件,也很简单,首先我们必须要知道这块e1000网卡的PCI设备信息,由于在服务器上e1000这块网卡已经安装完成了,所以我们可以在服务器上取到我们想要的信息:

命令输出 4. 查看网卡硬件信息

[root@ericvm ~]# lspci

............  ignore some outputs

04:00.0 Ethernet controller: Intel Corporation Enterprise Southbridge DPT LAN Copper

04:00.1 Ethernet controller: Intel Corporation Enterprise Southbridge DPT LAN Copper

............  ignore some outputs

lspci列出了服务器上两块网卡的设备信息,根据网卡设备的ID号码(04:00.0, 04:00.1),我们就可以在lspci –n的输出中找到设备的vendor code和device code(请参考lspci的manual了解lspci):

命令输出 5. 查看网卡code

[root@ericvm ~]# lspci –n

............  ignore some outputs

04:00.0 Class 0200: 8086:1096 (rev 01)

04:00.1 Class 0200: 8086:1096 (rev 01)

............  ignore some outputs

在lspci –n的输出中,我们找到了两块网卡的vendor code和device code – 8086和1096。得到了vendor code和device code之后,就可以更新initrd.img中modules目录下的pcitable, modules.pcimap等这些文件了。举例来说,在pcitable中查找e1000,能发现很多设备和e1000这个驱动关联,但是唯独没有 8086:1096的组合,这就是为什么Linux无法驱动这块e1000网卡的原因了,我们需要手动将8086, 1096这两个code加入到pcitable中,并将这个设备对应到e1000驱动上。照此方法,更新其余的文件,如module-info, modules.pcimap等。

这样我们就完成了对initrd.img的完全修改,用initrd-util.sh重新将目录打包,生成一个新的initrd.img:

命令输出 6. 重新生成initrd.img

[root@ericvm ~]# ./initrd-util.sh pack /var/tmp/initrd-util.workdir.DA29317/

notice: new initrd size: 6144K

6144+0 records in

6144+0 records out

mke2fs 1.35 (28-Feb-2004)

info: initrd packed into: /var/tmp/initrd-util.initrd-new.IV29439.gz

/var/tmp/initrd-util.initrd-new.IV29439.gz

[root@ericvm ~]# ls -lh /var/tmp

total 3.7M

-rw-r--r--   1 root root 3.7M Jun 20 17:10 initrd-util.initrd-new.IV29439.gz

drwxr-xr-x  12 root root 4.0K Jun 20 17:10 initrd-util.workdir.DA29317

drwxr-xr-x  13 root root 4.0K Jun 20 15:53 initrd-util.workdir.ID29288

initrd- util.sh首先创建一个“空洞文件”,然后在这个文件中建立ext2 文件系统,然后将这个文件mount到一个目录中,最后用rsync这种方式将我们更新过的文件“拷贝”到了mount的目录下,这样“空洞”文件中就有 了内容,最后对文件进行压缩,生成最终的img文件。

将/var/tmp/initrd-util.initrd-new.IV29439.gz改名成initrd.img,放到tftp配置的目录下,就可以让客户机在网络启动的时候取到新的initrd.img了,从而识别网卡开始网络安装。

三 为RedHat 4.8 系统安装 网卡/显卡驱动

在ks.cfg 文件最后%port 部分中添加:

rm –rf /lib/modules/2.6.9-89ELsmp/kernel/drivers/net/e1000e ;

mkdir /lib/modules/2.6.9-89ELsmp/kernel/drivers/net/e1000e ;

cd /lib/modules/2.6.9-89ELsmp/kernel/drivers/net/e1000e ;

wget

#***为kickstart 服务器地址,e1000e.ko为2.6.9-89ELsmp内核模块系统中编译出的驱动

Cd /tmp ; wget ; rpm -ivh nvidia-260.19.12-1.x86_64.rpm

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux没有网卡驱动能pxe吗,PXE所需要的网卡驱动制作 的相关文章

  • 如何在 GNU/Linux 上设置 Subversion (SVN) 服务器 - Ubuntu [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一台运行 Ubuntu 的笔记本电脑 我想将其用作 Subversion 服务器 既让我自己在本地承诺 也让其他人远程承诺 要使其
  • 后台分叉无法正常工作[重复]

    这个问题在这里已经有答案了 我运行这个程序 在前景和背景中 int main int pid printf App Start pid d n getpid while 1 pid fork if pid 0 printf Child n
  • 嵌入式linux编写AT命令

    我在向 GSM 模块写入 AT 命令时遇到问题 当我使用 minicom b 115200 D dev ttySP0 term vt100 时它工作完美 但我不知道如何在 C 代码中做同样的事情 我没有收到任何错误 但模块对命令没有反应 有
  • Linux中使用管道进行进程间通信

    我已经编写了在 linux 中写入数字以进行管道传输的代码 如下所示 但显示错误 任何人都可以帮助我解决这个问题 基本上该程序的问题陈述如下 一个程序将打开一个管道 向管道写入一个数字 其他程序将打开同一管道 读取数字并打印它们 关闭两个管
  • 无法在 64 位 Linux 上从汇编 (yasm) 代码调用 C 标准库函数

    我有一个函数foo以汇编语言编写 并在 Linux Ubuntu 64 位上使用 yasm 和 GCC 编译 它只是使用以下命令将消息打印到标准输出puts 如下所示 bits 64 extern puts global foo secti
  • 如何将后台作业的输出分配给 bash 变量?

    我想在 bash 中运行后台作业并将其结果分配给一个变量 我不喜欢使用临时文件 并且希望同时运行多个类似的后台任务 root root var echo hello world root root echo var hello world
  • 在 Linux 上访问 main 之外的主要参数

    是否可以访问参数main在外面main 即在共享库构造函数中 在 Linux 上除了通过解析之外 proc self cmdline 您可以通过将构造函数放入 init array部分 功能在 init array 不像 init 使用相同
  • 推荐用于小型站点的 IRC 服务器 (ircd)? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 情况 我想使用 IRC 机器人作为我正在研究的其他代码的通用通信接口 服务器硬件陈旧且内存不足 但运行在相对最新的 Debian GNU
  • 找出 Linux 上的默认语言

    有没有办法从C语言中找出Linux系统的默认语言 有 POSIX API 可以实现这个功能吗 例如 我想要一个人类可读格式的字符串 即德语系统上的 German 或 Deutsch 法语系统上的 French 或 Francais 等 有类
  • 从 php/linux 获取 pdf 的布局模式(横向或纵向)

    给定一个 PDF 如何使用 PHP lib 或 Linux 命令行工具获取 PDF 的布局模式 或相对宽度 高度 Using http www tecnick com public code cp dpage php aiocp dp tc
  • 未找到 Gem 命令

    我已经在 Ubuntu 10 10 32 位上安装了 gem apt get install gem y 但当我尝试跑步时 gem install something gem 我收到未找到命令的错误 bash gem command not
  • 错误:命令“c++”失败,退出状态为 1

    所以我尝试按照以下说明安装 Pyv8https andrewwilkinson wordpress com 2012 01 23 integrating python and javascript with pyv8 https andre
  • 使用 gcc 理解共享库

    我试图理解 C 中共享库的以下行为 机器一 cat one c include
  • 无需 root 访问权限即可安装 zsh? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 有可能 以及如何 我确实需要在几台具有 ssh 访问权限 但没有 root 访问权限 的远程计算机上使用此功能 下载 zsh wget O zsh t
  • 将node.js +expressjs应用程序的NODE_ENV设置为ubuntu下的守护进程

    我按照这些说明让守护进程正常工作 http kevin vanzonneveld net techblog article run nodejs as a service on ubuntu karmic http kevin vanzon
  • 计算 TCP 重传次数

    我想知道在LINUX中是否有一种方法可以计算一个流中发生的TCP重传的次数 无论是在客户端还是服务器端 好像netstat s解决了我的目的
  • 在 Linux 控制台中返回一行?

    我知道我可以返回该行并用以下内容覆盖其内容 r 现在我怎样才能进入上一行来改变它呢 或者有没有办法打印到控制台窗口中的特定光标位置 我的目标是使用 PHP 创建一些自刷新的多行控制台应用程序 Use ANSI 转义码 http en wik
  • 如何反汇编、修改然后重新组装 Linux 可执行文件?

    无论如何 这可以做到吗 我使用过 objdump 但它不会产生我所知道的任何汇编器都可以接受的汇编输出 我希望能够更改可执行文件中的指令 然后对其进行测试 我认为没有任何可靠的方法可以做到这一点 机器代码格式非常复杂 比汇编文件还要复杂 实
  • 可以作为命令行参数传递多少数据?

    在 Linux 下生成进程时可以发送多少字节作为命令行参数 gahooa 推荐了一篇好文章http www in ulm de mascheck various argmax http www in ulm de mascheck vari
  • 为什么默认情况下不启用 arp 忽略/通告 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我有一个需要经验才能回答的具体问题 为什么 arp ignore arp announce 在 Linux 安装 例如 debian 上默认不启用 有

随机推荐