BIOS/UEFI基础——UEFI网络框架之UNDI
来源:互联网 发布:免费英语口语软件 编辑:程序博客网 时间:2024/05/18 00:40
UNDI
UNDI全称Universal Network Driver Interface。
它并不是UEFI网络框架的一部分,甚至也可以不是UEFI的一部分。
不过目前UEFI下的网络驱动都会实现UNDI,这样UEFI就可以通过SNP来调用网卡的底层驱动。
在《UEFI Spec 2_6.pdf》中有对UNDI的详细介绍,这里简单说明下UNDI。
UNDI说到底是定义了一系列的接口,然后SNP来访问这些接口。
SNP如何获取到这些接口呢?
这需要实现了UNDI的网络设备驱动中安装一个NetworkInterfaceIdentifier(NII)协议,目前它的版本是3_10,SNP就可以通过对应的GUID来访问到它:
// // Get the NII interface. // Status = gBS->OpenProtocol ( Controller, &gEfiNetworkInterfaceIdentifierProtocolGuid_31, (VOID **) &Nii, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); return Status; } DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n")); Pxe = (PXE_UNDI *) (UINTN) (Nii->Id);如上面代码所示,NII中最重要的是PXE_UNDI指针。
它的结构体如下:
typedef union u_pxe_undi { PXE_HW_UNDI hw; PXE_SW_UNDI sw;} PXE_UNDI;可以看到它存在两种类型,从字面意思上看一种是硬件的,一种是软件的,对应的结构体如下:
这种结构体有一个奇怪的名字叫!PXE,不知道这里的叹号表示什么意思,难道是表示“非”。
上面的结构体成员不一一介绍了,可以参考《UEFI Spec 2_6.pdf》或者其它版本也可以。
从这里我们可以看出硬件UNDI和软件UNDI的一个重大区别,即硬件UNDI通过往MMIO或者IO寄存器写命令来调用底层接口,而软件UNDI通过网络设备驱动提供出来的Entry Point来调用底层接口。
从目前SNP的实现来看,硬件UNDI并不支持。
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) { Snp->IsSwUndi = FALSE; Snp->IssueUndi32Command = &IssueHwUndiCommand; } else { Snp->IsSwUndi = TRUE; if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) { Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) Pxe->sw.EntryPoint; } else { Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) ((UINT8) (UINTN) Pxe + Pxe->sw.EntryPoint); } }上面的代码是用来获取访问网络驱动底层实现的接口,可以看到对于硬件UNDI直接使用了IssueHwUndiCommand()这个函数,但是它直接返回了Unsupported。
而软件UNDI的接口是从!PXE这个结构体中获取的。
对于底层接口的访问如下图所示:
从软件来看,实际上就是下面的几个步骤:
1. 填充CDB;
2. 调用Snp->IssueUndi32Command,参数就是CDB;
3. 判断返回值;
已SNP中的PxeStart()函数为例:
/** Call UNDI to start the interface and changes the snp state. @param Snp pointer to snp driver structure. @retval EFI_SUCCESS UNDI is started successfully. @retval EFI_DEVICE_ERROR UNDI could not be started. **/EFI_STATUSPxeStart ( IN SNP_DRIVER *Snp ){ PXE_CPB_START_31 *Cpb31; Cpb31 = Snp->Cpb; // // Initialize UNDI Start CDB for H/W UNDI // Snp->Cdb.OpCode = PXE_OPCODE_START; Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED; Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED; Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED; Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED; Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED; 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; // // Make changes to H/W UNDI Start CDB if this is // a S/W UNDI. // if (Snp->IsSwUndi) { Snp->Cdb.CPBsize = (UINT16) sizeof (PXE_CPB_START_31); Snp->Cdb.CPBaddr = (UINT64)(UINTN) Cpb31; Cpb31->Delay = (UINT64)(UINTN) &SnpUndi32CallbackDelay; Cpb31->Block = (UINT64)(UINTN) &SnpUndi32CallbackBlock; // // Virtual == Physical. This can be set to zero. // Cpb31->Virt2Phys = (UINT64)(UINTN) 0; Cpb31->Mem_IO = (UINT64)(UINTN) &SnpUndi32CallbackMemio; Cpb31->Map_Mem = (UINT64)(UINTN) &SnpUndi32CallbackMap; Cpb31->UnMap_Mem = (UINT64)(UINTN) &SnpUndi32CallbackUnmap; Cpb31->Sync_Mem = (UINT64)(UINTN) &SnpUndi32CallbackSync; Cpb31->Unique_ID = (UINT64)(UINTN) Snp; } // // Issue UNDI command and check result. // DEBUG ((EFI_D_NET, "\nsnp->undi.start() ")); (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb); if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) { // // UNDI could not be started. Return UNDI error. // DEBUG ( (EFI_D_ERROR, "\nsnp->undi.start() %xh:%xh\n", Snp->Cdb.StatCode, Snp->Cdb.StatFlags) ); return EFI_DEVICE_ERROR; } // // Set simple network state to Started and return success. // Snp->Mode.State = EfiSimpleNetworkStarted; return EFI_SUCCESS;}CBD结构体如下:
OpCode是操作码,不同的操作对OpFlags、CPB结构体、DB结构体(就是CPBxxx,DBxxx那几个成员,它们对应到结构体中)都会有影响;
StatCode和StatFlags是返回的参数,也受到OpCode的影响;
IFnum用来处理一个NII对应多个物理网络设备的情况,值从0开始,算是一个Index;
Control可以指示使用了一个CDB还是多个,还可以指示当操作忙时是等待命令执行还是直接返回失败;
OpCode的值可以在UefiPxe.h中找到具体的值。
Snp中的所有操作,实际上都到最后都是使用上述的方式来完成的。
- BIOS/UEFI基础——UEFI网络框架之UNDI
- BIOS/UEFI基础——UEFI网络框架之概述
- BIOS/UEFI基础——UEFI网络框架之SNP
- 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基础——第一条指令
- C语言实验——圆周率
- 支持向量机实现编码
- Atmeg128a
- Agri-Net
- 盒子与球问题的探讨
- BIOS/UEFI基础——UEFI网络框架之UNDI
- 解压deb包时遇到 “dpkg status database is locked by another process”问题
- 3130 排序
- C 堆栈的链式表示
- JS高级---ajax
- 模式匹配、字符串匹配(蛮力法)
- 上课笔记set_new_handler的实现
- python 中的算数运算符
- POJ 3087Shuffle'm Up(模拟)