在30天自制的操作系统上编写网卡驱动,对我来说,是件比较有挑战的事情。
资料难找,没有在30天自制操作系统上的驱动资料,现有的资料都是linux系统上的资料,或者windows系统上的资料,而30天自制操作系统本身是一个新的系统,是书上给出的一个操作系统样例,供大家学习的教学用的操作系统,所以,在这个操作系统上,还没对的驱动发开提供接口。比如linux操作系统或者是windows操作系统都对驱动开发做了支持的,其内核已经实现了对网卡的支持,然后驱动开发人员直接调用操作系统提供的函数去控制网卡就行了。
30天自制操作系统本身就没有对网卡的任何支持,更别说开发一些驱动开发的接口出来了。整体来说,比较有挑战。具体做的话,得先在操作系统内部把驱动运行起来,然后再把相关控制网卡的函数开放出来,供大家在此操作系统上开发驱动程序。
本来想看看linux系统的驱动程序是怎么写的,想移植过来,后来发现不可能直接抄linux系统的驱动程序,windows上的驱动程序,因为操作系统不同。
所以,要写网卡驱动,就得按照嵌入式开发的思路,在现有的30天自制的操作系统上,直接去控制网卡收发数据,网络协议解析等。
万事开头难,在自制操作系统上开发网卡驱动也是这样的。
首先的困难就是没有对网卡设备的发现程序。现在是在虚拟机上把30天自制操作系统运行起来的,虚拟机可能有虚拟的网卡,也可能没有。
后来通过对PCI总线的检测,发现了几个网卡的型号,也算解决了网卡的问题。用虚拟的网卡做实验。
然后紧接着一个问题就是:虚拟的网卡并没有将真实网卡的功能全部模拟。虚拟机只是模拟了真实网卡的部分功能,当你按照网卡的datasheet去操作虚拟网卡的时候,发现虚拟网卡没有反馈。
后来更换了虚拟机,发现有的虚拟机还是可以模拟出网卡的datasheet上的所有功能的。所以,是可以用虚拟机来开发网卡驱动的。
有了可以实验用的虚拟网卡,就可以开始着手开发网卡驱动了。按照datasheet以及嵌入式开发的一些例子,先尝试去读取和写入网卡芯片,然后再尝试让网卡发送数据,接收数据,然后再尝试去按照网络协议去组织数据发送出去,然后按照网络协议接收数据。这样一步一步的,步步为营。
想法虽然很好,但是真正开始开发时,又遇到一个问题:
我手头的虚拟机中的操作系统如何联网呢?
如果虚拟机里安装了一个windows,或者linux,那么我们很容易找到教程,去设置联网问题。现在我们手头的是一个还没有开发网卡驱动的操作系统,根本没有教程教怎么联网。甚至如果是真实的主板,我们还能把网线插上,这就表示它联网了,等着开发网卡驱动程序就行了,但是现在是虚拟机,怎么知道,怎么确认虚拟机的网线插上了?
不过以上问题最后都得到了解决。遇到问题是困难的,但是解决问题的那一瞬间就很幸福了。
我是如何找到网卡的因为在虚拟机里安装linux操作系统后,linux操作系统是可以联网的。
所以,虚拟机本身肯定是带有网卡的,并且这个网卡也是能用的。
那么,如何把虚拟机上的网卡用起来? 查看到网卡的型号,然后搜索网卡芯片的类型,芯片有datasheet,datasheet上就详细说明了网卡如何使用。
不过在去控制网卡之前,要解决一个问题:如何让30自制操作系统找到这个网卡呢?
通过查找资料,我们发现,网卡一般都是通过PCI设备连接到CPU的。所以可以通过对PCI设备做个检索。
那么如何在30天自制操作系统上检索PCI设备呢?
我们的虚拟机的X86架构的CPU,这个CPU要检索PCI设备,只用通过IO端口就可以了,通过对某些固定的IO端口进行读写,就可以检索PCI设备了。
于是写程序去对相应端口进行检索,检索以后,发现,果然有网卡,并且型号为RTL8029.
这样,我就在30自制操作系统上找到网卡了。
后来发现,其实虚拟机启动的时候,是可以设置网卡的。
比如qemu可以通过如下命令设置网卡型号为ne2k_PCI,即ne2000网卡,并且这个网卡是通过PCI与CPU相连的。所以,这样设置之后,我们就可以通过端口控制PCI,从而找到这个网卡了。
其实qemu上虚拟的网卡类型挺多的,如下:
其中e1000是qemu虚拟机默认的网卡,我们这里由于最先接触了TRL8029网卡,所以就选了与TRL8029网卡兼容的ne2k_pci。
除了可以把30天自制操作系统放到qemu虚拟机上,也可以放到parallels虚拟机上,parallels在配置界面上设置网卡型号:
可以看到,这两种虚拟机都实现了RTL8029网卡。
又是如何找到比较好用的虚拟网卡的但是,找到虚拟网卡是第一步。
为什么这样说呢?
真正对网卡进行控制的时候,就发现qemu中的ne2k网卡,其实不能按照8029datasheet所提供的方式去控制:有些寄存器可以设置,有的不可以。这就是说:可能qemu虚拟网卡的功能不全,也可能8029网卡虽然与ne2k兼容,但是又是不同的,所以不能用控制8029方式去控制ne2k。可是,我现在就只有8029网卡的datasheet比较全面,ne2k的找到了零散几页。
这里展示一下找到虚拟网卡后,发现虚拟网卡功能不全的细节:
使用30自制操作系统自带的qemu.exe虚拟机,发现对网卡芯片8029的RCR,TCR,IMR等配置寄存器无法写入与读取,但对CR寄存器等却可以读取。这意味着qemu.exe虚拟机的网卡只能按照某种方式去接收,发送数据,但是真实的网卡是可以按照很多方式去接收发送数据的,我们做驱动开发也是要多种方式去验证的,所以qemu.exe上自带的8029网卡就无法使用了。
这让我的网卡驱动开发工作暂时停了下来。
发现还是不行,无法控制几个重要的配置寄存器去做回环测试。
可能虚拟机中的网卡没有将这些配置寄存器虚拟化。
那怎么办?
直接。。
后来有尝试了将我的qemu更新到最新的版本,发现有一些寄存器可以使用了,但是还是有若干个寄存器无法使用。
看来得去找一块真正的而不是虚拟的TRL-8029网卡了?
不过还是虚拟网卡比较方便些。既然RTL8029不能操作,那么其他网卡型号能不能使用呢?比如e1000网卡。
于是我试着去找e1000网卡的datasheet,发现还是比较全面的,似乎也可以用。datasheet直接从Intel的官方,去下载就行了。不过操作办法有一些变化,之前很多专门控制8029的代码就不能用了。
通过 PCI配置发现,虚拟机默认的网卡是8086-100f的,这个网卡就是e1000网卡,那么这个网卡内部的芯片是什么呢?
http://pci-ids.ucw.cz/v2.2/pci.ids
在这个网站里,查到:
芯片是82545EM,那么就可以去找这个芯片的datasheet了。
其实在ubuntu上通过lspci -v命令,也可以查看到,网卡类型为e1000e时,其芯片是intel 的82574L
当指定了网卡类型为2k_pci后,就可以查看到TRL-8029了,如下图
ne2k_pci
可以看到,这个网卡的IO端口时C000,内存映射的位置是0xfeb80000,这里disabled的意思可能是指:当前网卡不支持内存映射访问,只支持IO端口。
不过,最终,我在paralles虚拟机上试了试它提供的RTL8029AS虚拟网卡,发现与我手头的datasheet是完全匹配的。原来在qemu上的那么不能操作的关键寄存器,现在都能够操作了。
这是一个关于qemu上关于虚拟网卡的处理过程,如果不是paralles上的虚拟网卡能用,我恐怕就要去详细看看qemu内部到底是如何虚拟化网卡的了:https://blog.csdn.net/dillanzhou/article/details/120169734
如何确定网卡驱动虚拟机有联网
虚拟机中的ubutu系统是有联网的
既然,虚拟机中的ubuntu可以联网,那么虚拟机中的自制操作系统也是可以联网的。
其实,qemu联网也是很方便的,按如下命令来启动:
这里的参数-net user,虚拟机就会简历一个局域网,虚拟一个DHCP服务器来让虚拟机中操作系统获取IP地址。这种连接方式对于我们来说就够用了,因为我们写好网卡的发送程序后,就可以发送一些DHCP消息,去和DHCP服务器互动。
qemu还有一种联网方式是利用网桥,但是这个就需要安装在虚拟机内部的操作系统去连接这个网桥。但是,我们现在手头的30天自制操作系统还没有任何网络设备可用,所以,就不可能去连接这个网桥了。当然,这种方法连接后,虚拟机是可以连接到真实的局域网内部的,就是可以获取一个IP地址,这个IP地址是与运行虚拟机的电脑同一个局域网的。
通过网桥的连接方式就等网卡驱动开发好之后,再尝试做。
不过,由于qemu中的8029网卡我们操作不好,所以,自制操作系统通过qemu虚拟机的联网方式,我没有机会去验证。
在paralles中的8029网卡的寄存器可以被操作,也试了paralles中是否可以联网,发现是可以的,每收到一些网络信息,paralles右上角的网络信号会闪烁:
右上角的蜘蛛网亮起,表示网卡有收到数据
右上角的蜘蛛网灭,网卡没有收到数据
闪烁这个很鼓励人的。当我们操作网卡尝试发送数据,但是接收多次方毫无反应,抓包软件也抓取不到,就会很失望:难道我们控制网卡发送数据的方式错了么?但是网卡的操作手册上就是这么写的呀?无从下手。当看到这个标志有闪烁的时候,并且它与我们的发送动作是一致的:每次我按发送键,它就亮;我就基本可以确定,我确实有控制到网卡。那问题就出在我发出去的数据,可能格式不对,所以抓包软件抓不到。
只要确定我们能真的控制到网卡发送出去数据,那就好办了:
就是继续详细的查看到底格式错在哪里?再把DHCP协议,IP协议,ethernet协议所要求的字段,每个字段的长度,以及需要补零的数量搞搞清楚。
这就是paralles中这个蜘蛛网闪烁的意义。
这就相当于真实网卡的网线头子的那两个灯了:
所以,网线头子插口处的link灯和act灯,就是驱动开发人员看到希望的指路明灯。
当前的进度实现了控制8029收发数据。
实现了按照DHCP协议去向DHCP服务器申请IP地址。其实实现DHCP,就是实现UDP,IP,ehternet协议。
实现了按照arp协议去数据,然后解读ARP消息,回应APR消息,
后续准备:1. 实现一下对ICMP消息的回应:即回应ping命令2. 尝试利用IP协议传输较长的数据,即IP协议中的分段传输在重组。3. 实现TCP协议,HTTP协议,尝试开发一个简单的网页服务器。不过这好像超出网卡驱动的范畴了,网页服务器还是不要在操作系统内部开发,要等网卡驱动接口通过0x40中断开放给APP后,开发一个网页服务器APP。4. 因为当前这些驱动都是在操作系统内部写的,所以后续需要将内部驱动程序中的函数做成接口,通过0x40中断开放出去,这样也就支持了在30天操作系统上进行网络编程,利用这些接口,可以开发一个ping,开发一个arp,或者开发一个网页服务器。
,