我正在尝试使用 EFI 简单网络协议:
http://wiki.phoenix.com/wiki/index.php/EFI_SIMPLE_NETWORK_PROTOCOL
等待传入的以太网数据包。然而,使用 QEMU,WaitForPacket 事件即使有传入的数据包也不会触发,并且在真实硬件上,该事件总是会立即触发而没有任何数据包到达。我可以使用 tcpdump 看到我的示例数据包“在线”,所以我相当有信心我正在向它提供数据包。这是我的代码(归结为这个测试用例):
#include <efi.h>
#include <efilib.h>
EFI_HANDLE getNetHandle();
EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
InitializeLib(ImageHandle, SystemTable);
EFI_GUID snpguid = EFI_SIMPLE_NETWORK_PROTOCOL;
EFI_HANDLE netHandle = getNetHandle();
EFI_STATUS status;
EFI_SIMPLE_NETWORK* net_if_struct;
status = uefi_call_wrapper(BS->HandleProtocol, 3,
netHandle, &snpguid, &net_if_struct);
Print(L"Main: HandleProtocol status: %r\n", status);
Print(L"Main: WaitForPacket event: %x\n", net_if_struct->WaitForPacket);
EFI_EVENT waitEvents[1];
waitEvents[0] = net_if_struct->WaitForPacket;
UINTN eventTriggered;
status = uefi_call_wrapper(BS->WaitForEvent, 3,
1, waitEvents, &eventTriggered);
Print(L"Main: WaitForEvent status: %r, event triggered: %d\n", status, eventTriggered);
return EFI_SUCCESS;
}
EFI_HANDLE getNetHandle()
{
UINTN numHandles = 0;
EFI_HANDLE* handles = NULL;
EFI_GUID SimpleNetworkGUID = EFI_SIMPLE_NETWORK_PROTOCOL;
EFI_STATUS status = uefi_call_wrapper(BS->LocateHandleBuffer, 5,
ByProtocol, &SimpleNetworkGUID, NULL, &numHandles, &handles);
if (status != EFI_SUCCESS)
Print(L"getNetHandle: Failed to LocateHandleBuffer (%d)\n", status);
else
Print(L"getNetHandle: LocateHandleBuffer OK (%d handles)\n", numHandles);
EFI_HANDLE toReturn = NULL;
if (numHandles == 1)
{
toReturn = handles[0];
}
FreePool(handles);
return toReturn;
}
我尝试过/证明/线索的事情:
当它运行时,WaitForPacket 事件打印行打印一个非空值,所以我假设 EFI 系统已经创建了一个事件并在 EFI_SIMPLE_NETWORK 结构中将其准备好。
我尝试假设我需要创建一个事件并将其放入结构中,然后使用该事件等待,但它没有任何区别。
我有其他代码可以发送和接收数据包(差不多),所以我认为我对网络句柄和接口结构的理解是合理的,我的 EFI 硬件和 QEMU 能够进行网络通信。
关于如何使用 WaitForPacket 的文档是不存在的,以至于感觉这应该是那些可以工作的东西之一。我发现的文档位于 Phoenix wiki(上面链接)和 2899 页 UEFI 规范文档版本 2.7。
尽管我在谷歌上搜索得最好,但我找不到任何在 GNU-EFI 应用程序中使用 WaitForPacket 的例子。
我尝试过启动和初始化网络硬件,这对于 QEMU 来说似乎是必要的,但对于真正的硬件却不是。我还尝试使用 ReceiveFilters() 将硬件设置为混杂模式并对其进行广播,但这也没有什么区别。
有任何想法吗??