【UEFI基础】UEFI网络框架之SNP

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. TxRxBufferSizeTxRxBuffer:这两个值确定一段内存空间,是UNDI需要使用的。UEFI通过UNDI的PXE_OPCODE_GET_INIT_INFO操作符获取UNDI的初始化信息(即TxRxBufferSize),再通过这个初始化信息来分配一段内容空间(由TxRxBuffer指定),在SNP中调用PxeInit()函数时,会将TxRxBuffer放到Cpb中传递给UNDI。至于这段内存空间到底是干什么的,从名字上看应该是UNDI收发数据的缓存区;

11. ReceiveBuffferReceiveBufferUnmapFillHeaderBufferFillHeaderBufferUnmap:这4个参数并没有用到;

12. PciIoIoBarIndexMemoryBarIndex:前面已经说过一个SNP_DRIVER对应一个网卡,所以这里的PciIo就是用来访问该设备的接口,通过它也可以确定IoBarIndex和MemoryBarIndex,这两个参数指定了网卡在系统中映射的资源空间;

13. CdbCpbCpbUnmapDb: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. RecycledTxBufMaxRecycledTxBufRecycledTxBufCount:这三个值共同管理一段内存空间,内存空间的大小是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的网络收发并没有被打开。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值