深入linux斗天地!

今天干了一件了不起的事,深入linux,修改驱动程序,掩盖了(不是修复了)一个错误。

事情是这样的,新买的HP Pavilion电脑,装了Ubuntu Linux系统,但是不久系里的网管发来
信说,你的电脑出现随机MAC地址,会耗尽IP资源。一查log,发现如下的信息:

/var/log/kern.log:Aug 10 14:06:35 xfliu-desktop kernel: [ 866.860000] Please complain to your hardware vendor. Switching to a random MAC.
网管不断的给我补充知识,说这是主板上nForce驱动有缺陷造成的。再后来知道,nForce由Nvidia公司提供支持,后来有黑客破解了驱动程序,因此Nvidia直接提供开源的程序,(linux就是这样走过来的?)但是,还是有缺陷,因此出现了我现在的情况: 电脑由Hibernate状态启动时,系统读取网卡的MAC地址有错误,便自动生成随即MAC地址。驱动程序forcedeth.c代码如下:

       if (!is_valid_ether_addr(dev->perm_addr)) {
/*
* Bad mac address. At least one bios sets the mac address
* to 01:23:45:67:89:ab
*/
printk(KERN_ERR "%s: Invalid Mac address detected: %02x:%02x:%02x:%02x:%02x:%02x\n",
pci_name(pci_dev),
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
printk(KERN_ERR "Please complain to your hardware vendor. Switching to a random MAC.\n");
dev->dev_addr[0] = 0x00;
dev->dev_addr[1] = 0x00;
dev->dev_addr[2] = 0x6c;
get_random_bytes(&dev->dev_addr[3], 3);
}

网管很含蓄的讲,这个问题几乎是不可能解决的,建议不要再使用Linux。这怎么行?自己好不容易有了一台高配置的电脑可以用linux,现在束之高阁,太可惜了。

尽管目前的问题是只自动生成一个MAC地址,并且我决定不再使用Hibernate休眠方式,可是
仍会给网管带来麻烦的--估计他看到网络log里的random mac字样就会骂我。必须找个解决方案。

简单推理了一下,不就是不能读取MAC地址吗,我不懂硬件不知如何修改驱动,但是我可以在
读取地址失败时,强制的告诉它正确的地址。于是驱动可以改成这个样子。

if (!is_valid_ether_addr(dev->perm_addr)) {
/*
* Bad mac address. At least one bios sets the mac address
* to 01:23:45:67:89:ab
*/
printk(KERN_ERR "%s: Invalid Mac address detected: %02x:%02x:%02x:%02x:%02x:%02x\n",
pci_name(pci_dev),
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
printk(KERN_ERR "The MAC address is forced to be 00:1b:fc:40:d7:8b (module forcedeth changed by Xuefeng Liu).\n");
dev->dev_addr[0] = 0x00;
dev->dev_addr[1] = 0x1b;
dev->dev_addr[2] = 0xfc;
dev->dev_addr[3] = 0x40;
dev->dev_addr[4] = 0xd7;
dev->dev_addr[5] = 0x8b;
//Modified by Xuefeng LIU on 200/08/17

//get_random_bytes(&dev->dev_addr[3], 3);

}

如此以来不就没有问题了吗!


"好的Idea往往不是好Idea" 这是我导师的名言。
“Idea是廉价的”,这是我的个人名言。

下面是一大推问题。如何找到驱动的位置,如何编译--似乎与linux的模块编译有关,如何导入模块。这些问题对我来说完全是一头雾水。不过几经努力,一切都解决了。下面是技术性的简单说明,留作Memo了。



1) 确定模块的加载情况。
$lsmod |grep forcedeth
2) 确定系统版本

$ uname -a
Linux xfliu-desktop 2.6.20-16-generic #2 SMP Thu Jun 7 20:19:32 UTC 2007 i686 GNU/Linux
3) 驱动的位置: /lib/modules/2.6.20-16-generic/kernel/drivers/net/forcedeth.ko

4)下载系统源代码(下载的文件自动保存于 /usr/src )
$sudo apt-get install linux-source-2.6.20
$cd /usr/src
$bzip2 -d linux-source-2.6.20.tar.bz2

5) 进入 /usr/src/linux-source-2.6.20/drivers/net/ 创建一个新的文件夹 tmp, 并进入tmp, 复制上一层的forcedeth.c 到当前的tmp下,并如上修改forcedeth.c代码,然后新建Makefile 如下。(偷懒的人注意了,如果想复制下面的代码来直接使用是不成的,因为命令行开头的空白需要换位TAB字符。)最后运行 $make编译,生成 forcedeth.ko。其中build的位置可能需要修改一下。

obj-m := forcedeth.o

KERNELDIR := /lib/modules/2.6.20-15-generic/build
#注意你的系统中的相应位置

PWD := $(shell pwd)

modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

6) 将新生成的forcedeth.ko 拷贝至 /lib/modules/2.6.20-16-generic/kernel/drivers/net,注意备份原有的文件。

7) 运行下面的命令来加载新的模块。由此大功告成!

$modprobe -r forcedeth
$modprobe forcedeth


可以安心休息去了。

评论

此博客中的热门博文

PIC12F683 备忘录

书生贩粥

中日文邮件收发建议