UEFI解决完整路径

编程入门 行业动态 更新时间:2024-10-24 04:44:08
本文介绍了UEFI解决完整路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在使用GNU-EFI进行各种引导加载程序.到目前为止,我已经能够读取Boot#### NVRAM变量,所以我有一个半填充的FilePathList[],它看起来像这样(用DevicePathToStr打印):

I'm working on a bootloader of sorts using GNU-EFI. So far I've been able to read the Boot#### NVRAM variable, so I have a semi-populated FilePathList[], which looks like this (printed with DevicePathToStr):

HD(Part2, SigCD0400E6-54F3-49F4-81F2-65B21E8278A8)/\EFI\Microsoft\Boot\bootmgfw.efi

当传递给LoadImage时,它会失败,并显示EFI_NOT_FOUND.据我了解,(UEFI文档第3.1.2节) ,我需要在已有路径之前添加完整路径.我发现正确的路径是PciRoot(0x0)/Pci(0x1, 0x1)/Ata(0x0),但是我不确定如何根据自己的方式以编程方式找到该路径,因此可以将其作为前缀.

When passed to LoadImage it fails with EFI_NOT_FOUND. As I understand it (UEFI Doc Section 3.1.2), I need to add the full path before what I already have. I've found out that the correct path is PciRoot(0x0)/Pci(0x1, 0x1)/Ata(0x0), but I am unsure how I programmatically find this path based on what I have so it can be prepended.

到目前为止,我的代码如下,请原谅我的代码质量低下,到目前为止,我一直在尝试使某些代码正常工作.

The code I have so far is as follows, please excuse the low quality, I've just been trying to get something working so far.

EFI_STATUS status; EFI_GUID vendor = EFI_GLOBAL_VARIABLE; UINT32 Attr; UINTN size = 256; UINT16 *buf = AllocateZeroPool(size); if (buf == NULL) Print(L"Failed to allocate buffer\n"); status = uefi_call_wrapper(RT->GetVariable, 5, L"BootOrder", /*VariableName*/ &vendor, /*VendorGuid*/ &Attr, /*Attributes*/ &size, /*DataSize*/ buf /*Data*/ ); if (status != EFI_SUCCESS) Print(L"Failed to read BootOrder (%d)\n", status); // should contain an int for the correct boot option UINT16 bootopt = buf[0]; FreePool(buf); CHAR16 *name = AllocateZeroPool(18); // Bootxxxx\0 unicode SPrint(name, 18, L"Boot%04x", bootopt); Print(L"Next boot: %s\n", name); size = 0; do { buf = AllocateZeroPool(size); if (buf == NULL) Print(L"Failed to allocate buffer\n"); status = uefi_call_wrapper(RT->GetVariable, 5, name, &vendor, &Attr, &size, buf ); if (status == EFI_SUCCESS) break; FreePool(buf); // if it fails, size is set to what it needs to be // handy that } while(status == EFI_BUFFER_TOO_SMALL); if (!(buf[0]&LOAD_OPTION_ACTIVE)) Print(L"BootOption not active\n"); Print(L"%s: 0x%r\n\n", name, buf); UINT8 *OrigFilePathList = ((UINT8*)buf) + (sizeof(UINT32) + sizeof(UINT16) + StrSize(buf+3)); UINT16 *FilePathListLength = ((UINT16*)OrigFilePathList)+2; Print(L"&OrigFilePathList = 0x%r\n", OrigFilePathList); Print(L"sizeof(_EFI_LOAD_OPTION) = %d\n", size); Print(L"struct _EFI_LOAD_OPTION {\n"); Print(L" Attributes = %d\n", *(UINT32 *)(buf)); Print(L" FilePathListLength = %d,\n", *FilePathListLength); Print(L" Description = %s,\n", buf+3); Print(L" FilePathList[] = {\n"); UINT16 totallength = 0; UINT8 *FilePathList = OrigFilePathList; for (UINT8 i = 0; i < *FilePathListLength+1; i++) { Print(L" &FilePathList[%d] = 0x%r\n", i, OrigFilePathList); Print(L" FilePathList[%d].Type = %d ", i, *OrigFilePathList); switch (*OrigFilePathList) { case 0x01: Print(L"(Hardware Device Path)\n"); break; case 0x02: Print(L"(ACPI Device Path)\n"); break; case 0x03: Print(L"(Messaging Device Path)\n"); break; case 0x04: Print(L"(Media Device Path)\n"); break; case 0x05: Print(L"(BIOS Boot Specification Device Path)\n"); break; case 0x7f: Print(L"(End Of Hardware Device Path)\n"); break; default: Print(L"(Unknown Device Path)\n"); break; } Print(L" FilePathList[%d].SubType = %d\n", i, *(OrigFilePathList+1)); Print(L" FilePathList[%d].Length = %d\n", i, *(UINT16*)(OrigFilePathList+2)); totallength += *(UINT16*)(OrigFilePathList+2); OrigFilePathList += *(UINT16*)(OrigFilePathList+2); } Print(L" }\n"); Print(L" &OptionalData = 0x%r\n", OrigFilePathList); Print(L" OptionalDataLength = %d\n", size-totallength); Print(L"}\n"); // The hard drive device path can be appended to the matching hardware // device path and normal boot behavior can then be used. // We need to locate the Type 1 FilePathList and prepend it to what we've already got // Need to prefix PciRoot(0x0)/Pci(0x1, 0x1)/Ata(0x0) // but automatically find it // in theory we should be able to use the list of handles to devices that support SIMPLE_FILE_SYSTEM_PROTOCOL // to find the right device Print(L"%s\n", DevicePathToStr((EFI_DEVICE_PATH *)FilePathList)); /* EFI_STATUS (EFIAPI *EFI_IMAGE_LOAD) ( IN BOOLEAN BootPolicy, IN EFI_HANDLE ParentImageHandle, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN VOID *SourceBuffer OPTIONAL, IN UINTN SourceSize, OUT EFI_HANDLE *ImageHandle ); */ EFI_HANDLE *NextHandle = AllocateZeroPool(sizeof(EFI_HANDLE)); status = uefi_call_wrapper(BS->LoadImage, 6, /* status = BS->LoadImage( */ TRUE, /* BootPolicy */ ImageHandle, /* ParentImageHandle */ (EFI_DEVICE_PATH *)FilePathList, /* DevicePath */ NULL, /* SourceBuffer */ 0, /* SourceSize */ NextHandle /* ImageHandle */ ); if (status != EFI_SUCCESS) Print(L"Failed to LoadImage (%d)\n", status); else Print(L"LoadImage OK\n");

我需要什么功能和流程才能完全合格FilePathList,以便可以与LoadImage一起使用?

What functions and flows are required for me to fully qualify the FilePathList so it can be used with LoadImage?

推荐答案

当我寻求帮助时,请相信我会解决的.

Trust that when I've asked for help I work it out.

通常的想法是使用LocateHandleBuffer查找SIMPLE_FILE_SYSTEM_PROTOCOL的所有句柄.使用这些句柄,将路径(使用DevicePathFromHandle)与我们已经找到合适设备所需的路径进行比较. LoadImage现在对我有用.

The general idea is to use LocateHandleBuffer to find all handles for SIMPLE_FILE_SYSTEM_PROTOCOL. With these handles, compare the path (using DevicePathFromHandle) to what we already have to find the appropriate device. LoadImage now works for me.

下面的示例代码(buf是GetVariable中Boot####变量的值):

Sample code below (buf is the value of the Boot#### variable from GetVariable):

Print(L"Description = %s\n", (CHAR16*)buf + 3); EFI_DEVICE_PATH *BootX = (EFI_DEVICE_PATH*) (((UINT8*)buf) + (sizeof(UINT32) + sizeof(UINT16) + StrSize(buf+3))); UINTN NoHandles = 0; EFI_HANDLE *handles = NULL; EFI_GUID SimpleFileSystemGUID = SIMPLE_FILE_SYSTEM_PROTOCOL; status = uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, &SimpleFileSystemGUID, NULL, &NoHandles, &handles ); if (status != EFI_SUCCESS) Print(L"Failed to LocateHandleBuffer (%d)\n", status); else Print(L"LocateHandleBuffer OK (%d handles)\n", NoHandles); EFI_DEVICE_PATH *prefix; UINTN index; for (index = 0; index < NoHandles; index++) { prefix = DevicePathFromHandle(handles[index]); while(!IsDevicePathEnd(NextDevicePathNode(prefix))) prefix = NextDevicePathNode(prefix); if(LibMatchDevicePaths(prefix, BootX)) { break; } else { FreePool(prefix); } } prefix = DevicePathFromHandle(handles[index]); // prefix ends with the same node that BootX starts with // so skip forward BootX so we can prepend prefix BootX = NextDevicePathNode(BootX); EFI_DEVICE_PATH *fullpath = AppendDevicePath(prefix, BootX); Print(L"Booting: %s\n", DevicePathToStr(fullpath)); /* EFI_STATUS (EFIAPI *EFI_IMAGE_LOAD) ( IN BOOLEAN BootPolicy, IN EFI_HANDLE ParentImageHandle, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN VOID *SourceBuffer OPTIONAL, IN UINTN SourceSize, OUT EFI_HANDLE *ImageHandle ); */ EFI_HANDLE *NextHandle = AllocateZeroPool(sizeof(EFI_HANDLE)); status = uefi_call_wrapper(BS->LoadImage, 6, /* status = BS->LoadImage( */ TRUE, /* BootPolicy */ ImageHandle, /* ParentImageHandle */ fullpath, /* DevicePath */ NULL, /* SourceBuffer */ 0, /* SourceSize */ NextHandle /* ImageHandle */ ); if (status != EFI_SUCCESS) Print(L"Failed to LoadImage (%d)\n", status); else Print(L"LoadImage OK\n");

更多推荐

UEFI解决完整路径

本文发布于:2023-11-30 05:33:47,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1648893.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:路径   完整   UEFI

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!