BIOS/UEFI基础——UEFI网络框架之SNP
来源:互联网 发布:免费英语口语软件 编辑:程序博客网 时间:2024/05/17 22:27
SNP
SNP全称是Simple Network Protocol。
该模块的作用有以下的几个部分:
1. 网卡操作,比如初始化网卡,打开/关闭网口等;
2. 提供数据的传输接口,供上层协议使用;
SNP驱动依赖于UNDI/NII驱动,即网卡驱动。该驱动执行后会安装gEfiNetworkInterfaceIdentifierProtocolGuid_31对应的协议。
SNP驱动执行时就会去查看该协议是否存在,如果存在,就会据此构造SNP_DRIVER结构体来表示这张网卡。
后续对该网卡的操作都是通过SNP_DRIVER结构体,及其中的SNP来完成。
SNP驱动的初始化主要做了以下的是事情:
1. 初始化SNP_DRIVER结构体;
2. 创建ExitBootServicesEvent事件,是为了在退出UEFI之前关闭网络,避免网络的DMA写坏了OS启动需要的内存空间;
3. 安装gEfiSimpleNetworkProtocolGuid对应的Protocol,供上层接口使用;
所以对于SNP来说,最重要的其实是两点,一个是SNP_DRIVER这个结构体,另一个是SNP提供的接口。
SNP_DRIVER structure
SNP_DRIVER定义在Snp.h文件中,如下所示:
typedef struct { UINT32 Signature; EFI_LOCK Lock; EFI_SIMPLE_NETWORK_PROTOCOL Snp; EFI_SIMPLE_NETWORK_MODE Mode; EFI_HANDLE DeviceHandle; EFI_DEVICE_PATH_PROTOCOL *DevicePath; // // Local instance data needed by SNP driver // // Pointer to S/W UNDI API entry point // This will be NULL for H/W UNDI // ISSUE_UNDI32_COMMAND IssueUndi32Command; BOOLEAN IsSwUndi; // // undi interface number, if one undi manages more nics // PXE_IFNUM IfNum; // // Allocated tx/rx buffer that was passed to UNDI Initialize. // UINT32 TxRxBufferSize; VOID *TxRxBuffer; // // mappable buffers for receive and fill header for undi3.0 // these will be used if the user buffers are above 4GB limit (instead of // mapping the user buffers) // UINT8 *ReceiveBufffer; VOID *ReceiveBufferUnmap; UINT8 *FillHeaderBuffer; VOID *FillHeaderBufferUnmap; EFI_PCI_IO_PROTOCOL *PciIo; UINT8 IoBarIndex; UINT8 MemoryBarIndex; // // Buffers for command descriptor block, command parameter block // and data block. // PXE_CDB Cdb; VOID *Cpb; VOID *CpbUnmap; VOID *Db; // // UNDI structure, we need to remember the init info for a long time! // PXE_DB_GET_INIT_INFO InitInfo; VOID *SnpDriverUnmap; // // when ever we map an address, we must remember it's address and the un-map // cookie so that we can unmap later // struct MAP_LIST { EFI_PHYSICAL_ADDRESS VirtualAddress; VOID *MapCookie; } MapList[MAX_MAP_LENGTH]; EFI_EVENT ExitBootServicesEvent; // // Whether UNDI support reporting media status from GET_STATUS command, // i.e. PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED or // PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED // BOOLEAN MediaStatusSupported; // // Whether UNDI support cable detect for INITIALIZE command, // i.e. PXE_STATFLAGS_CABLE_DETECT_SUPPORTED or // PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED // BOOLEAN CableDetectSupported; // // Array of the recycled transmit buffer address from UNDI. // UINT64 *RecycledTxBuf; // // The maximum number of recycled buffer pointers in RecycledTxBuf. // UINT32 MaxRecycledTxBuf; // // Current number of recycled buffer pointers in RecycledTxBuf. // UINT32 RecycledTxBufCount;} SNP_DRIVER;这些值的介绍如下:
1. Signature:就是一个标识,对应的值是"sdns";
2. Lock:是UEFI下的锁。UEFI下没有多线程,所以这个锁应该是用于中断的,目前并不清楚它具体想要锁什么;
3. Snp:这个就Simple Network Protocol,下面会介绍它的所以成员;
4. Mode:在Snp中也有一个成员Mode,两者的值是一致的,后面会介绍;
5. DeviceHandle:每个SNP_DRIVER结构体对应一个设备,所以也就对应到一个Handle上;
6. DevicePath:同上,每个SNP_DRIVER结构体也对应到一个DevicePath上;
7. IssueUndi32Command:这个是UEFI下的执行函数,通过它可以调用UNDI中的接口,可以有软件和硬件两种形式,不过SNP目前只实现了软件形式的;
8. IsSwUndi:如果是软件形式的UNDI,就设置为TRUE;
9. IfNum:表示一个!PXE结构体控制的网卡数目;
10. TxRxBufferSize,TxRxBuffer:这两个值确定一段内存空间,是UNDI需要使用的。UEFI通过UNDI的PXE_OPCODE_GET_INIT_INFO操作符获取UNDI的初始化信息(即TxRxBufferSize),再通过这个初始化信息来分配一段内容空间(由TxRxBuffer指定),在SNP中调用PxeInit()函数时,会将TxRxBuffer放到Cpb中传递给UNDI。至于这段内存空间到底是干什么的,从名字上看应该是UNDI收发数据的缓存区;
11. ReceiveBufffer,ReceiveBufferUnmap,FillHeaderBuffer,FillHeaderBufferUnmap:这4个参数并没有用到;
12. PciIo,IoBarIndex,MemoryBarIndex:前面已经说过一个SNP_DRIVER对应一个网卡,所以这里的PciIo就是用来访问该设备的接口,通过它也可以确定IoBarIndex和MemoryBarIndex,这两个参数指定了网卡在系统中映射的资源空间;
13. Cdb,Cpb,CpbUnmap,Db:CpbUnmap并没有使用,剩下的三个参数是UNDI调用需要的参数,Cdb中放置的数据表示需要进行什么操作,Cpb表示操作需要的参数,Db存放的是具体需要传递的参数;
14. InitInfo:SNP调用PXE_OPCODE_GET_INIT_INFO之后会保留到这个参数中,具体的调用函数如下:
Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO; Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED; Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED; Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED; Snp->Cdb.DBsize = (UINT16) sizeof (Snp->InitInfo); Snp->Cdb.DBaddr = (UINT64)(UINTN) (&Snp->InitInfo);//作为参数传入,UNDI会去填充 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE; Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; Snp->Cdb.IFnum = Snp->IfNum; Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; DEBUG ((EFI_D_NET, "\nSnp->undi.get_init_info() ")); (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);15. SnpDriverUnmap:又是一个并没有使用的参数;
16. MapList:一个映射数组,似乎是给DMA用的,但是看不出来怎么样的;
17. ExitBootServicesEvent:一个事件,在UEFI调用gBS->ExitBootServices()是调用;
18. MediaStatusSupported:如果UNDI支持上报网卡的连接信息,则为TRUE;
19. CableDetectSupported:如果UNDI支持测试网线是否连接,则为TRUE;
20. RecycledTxBuf,MaxRecycledTxBuf,RecycledTxBufCount:这三个值共同管理一段内存空间,内存空间的大小是32个64位数,这段内存空间由UEFI分配,在SNP调用PxeGetStatus时会使用,现在还不知道这个函数有什么用。
以上就是所有的参数。
SNP Interface
SNP提供的接口如下:
////// The EFI_SIMPLE_NETWORK_PROTOCOL protocol is used to initialize access /// to a network adapter. Once the network adapter initializes, /// the EFI_SIMPLE_NETWORK_PROTOCOL protocol provides services that /// allow packets to be transmitted and received.///struct _EFI_SIMPLE_NETWORK_PROTOCOL { /// /// Revision of the EFI_SIMPLE_NETWORK_PROTOCOL. All future revisions must /// be backwards compatible. If a future version is not backwards compatible /// it is not the same GUID. /// UINT64 Revision; EFI_SIMPLE_NETWORK_START Start; EFI_SIMPLE_NETWORK_STOP Stop; EFI_SIMPLE_NETWORK_INITIALIZE Initialize; EFI_SIMPLE_NETWORK_RESET Reset; EFI_SIMPLE_NETWORK_SHUTDOWN Shutdown; EFI_SIMPLE_NETWORK_RECEIVE_FILTERS ReceiveFilters; EFI_SIMPLE_NETWORK_STATION_ADDRESS StationAddress; EFI_SIMPLE_NETWORK_STATISTICS Statistics; EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC MCastIpToMac; EFI_SIMPLE_NETWORK_NVDATA NvData; EFI_SIMPLE_NETWORK_GET_STATUS GetStatus; EFI_SIMPLE_NETWORK_TRANSMIT Transmit; EFI_SIMPLE_NETWORK_RECEIVE Receive; /// /// Event used with WaitForEvent() to wait for a packet to be received. /// EFI_EVENT WaitForPacket; /// /// Pointer to the EFI_SIMPLE_NETWORK_MODE data for the device. /// EFI_SIMPLE_NETWORK_MODE *Mode;};extern EFI_GUID gEfiSimpleNetworkProtocolGuid;
如UNDI章节所述,上面的接口都是通过UNDI来实现的。
SNP提供的数据接口是纯数据包的传输,并不涉及到具体的网络协议。
理论上我们可以自己构造网络协议并传输。
当然也可以使用SNP之上的各个模块提供的接口来传输数据。
在SNP的初始化过程中会安装gEfiSimpleNetworkProtocolGuid:
// // add SNP to the undi handle // Status = gBS->InstallProtocolInterface ( &Controller, &gEfiSimpleNetworkProtocolGuid, EFI_NATIVE_INTERFACE, &(Snp->Snp) );另外,在完成SNP的初始化之后,网络设备并没有一直打开:
// // We should not leave UNDI started and initialized here. this DriverStart() // routine must only find and attach the SNP interface to UNDI layer that it // finds on the given handle! // The UNDI layer will be started when upper layers call Snp->start. // How ever, this DriverStart() must fill up the snp mode structure which // contains the MAC address of the NIC. For this reason we started and // initialized UNDI here, now we are done, do a shutdown and stop of the // UNDI interface! // PxeShutdown (Snp); PxeStop (Snp);
所以在SNP被初始化完成之后,UEFI的网络收发并没有被打开。
- BIOS/UEFI基础——UEFI网络框架之SNP
- BIOS/UEFI基础——UEFI网络框架之概述
- BIOS/UEFI基础——UEFI网络框架之UNDI
- BIOS/UEFI基础——UEFI网络框架之MNP
- BIOS/UEFI基础——UEFI网络框架之ARP
- BIOS/UEFI基础——UEFI网络框架之TCP4
- BIOS/UEFI基础——UEFI网络框架之MNP2
- BIOS/UEFI基础——UEFI网络框架之IP4
- BIOS/UEFI基础——UEFI网络框架之支撑模块DPC
- BIOS/UEFI基础——基础知识
- BIOS/UEFI基础——EDK
- BIOS/UEFI基础——EFI_HANDLE
- BIOS/UEFI基础——变量
- BIOS/UEFI基础——定时器
- BIOS/UEFI基础——DEBUG
- BIOS/UEFI基础——Device Path
- BIOS/UEFI基础——x86架构中断基础介绍
- BIOS/UEFI基础——第一条指令
- 模式匹配、字符串匹配(蛮力法)
- 上课笔记set_new_handler的实现
- python 中的算数运算符
- POJ 3087Shuffle'm Up(模拟)
- 分享两款强大的文本编辑器
- BIOS/UEFI基础——UEFI网络框架之SNP
- 学习C++ -> 向量(vector)
- android四大组件之Activity复习
- 笔试面试常考排序算法总结
- 嵌入式调试器---GDB
- 二分法搜索
- 开始前端的学习了
- 【Servlet】(一)初识Servlet
- 将浮点数转换成人民币读法字符串(整数部分在12位以内)