////// Can be used on any image handle to obtain information about the loaded image.///typedefstruct { UINT32 Revision; ///< Defines the revision of the EFI_LOADED_IMAGE_PROTOCOL structure. ///< All future revisions will be backward compatible to the current revision. EFI_HANDLE ParentHandle; ///< Parent image's image handle. NULL if the image is loaded directly from ///< the firmware's boot manager. EFI_SYSTEM_TABLE *SystemTable; ///< the image's EFI system table pointer.//// Source location of image// EFI_HANDLE DeviceHandle; ///< The device handle that the EFI Image was loaded from. EFI_DEVICE_PATH_PROTOCOL *FilePath; ///< A pointer to the file path portion specific to DeviceHandle ///< that the EFI Image was loaded from. VOID *Reserved; ///< Reserved. DO NOT USE.//// Images load options// UINT32 LoadOptionsSize;///< The size in bytes of LoadOptions. VOID *LoadOptions; ///< A pointer to the image's binary load options.//// Location of where image was loaded// VOID *ImageBase; ///< The base address at which the image was loaded. UINT64 ImageSize; ///< The size in bytes of the loaded image. EFI_MEMORY_TYPE ImageCodeType; ///< The memory type that the code sections were loaded as. EFI_MEMORY_TYPE ImageDataType; ///< The memory type that the data sections were loaded as. EFI_IMAGE_UNLOAD Unload;} EFI_LOADED_IMAGE_PROTOCOL;
UEFI 스펙(specification)에 따르면 아래와 같이 설명이 되어 있는 것을 볼 수 있다.
로드된 각 이미지에는 EFI_LOADED_IMAGE_PROTOCOL을 지원하는 이미지 핸들이 있습니다. 이미지가 시작되면 자체 이미지 핸들이 전달됩니다. 이미지는 로드 옵션과 같은 EFI_LOADED_IMAGE_PROTOCOL 구조에 저장된 관련 이미지 데이터를 얻기 위해 핸들을 사용할 수 있습니다.
나머지 하나의 GUID는 EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL을 나타낸다. -
설치된 경우 로드된 Loaded Image Device Path Protocol은 PE/COFF 이미지가 EFI 부팅 서비스 LoadImage()를 통해 로드될 때 사용된 장치 경로를 지정한다.
Loaded Image Device Path Protocol은 Device Path Protocol과 동일한 프로토콜 인터페이스를 사용한다. 두가지의 유일한 차이점은 GUID 값이 다르다는 것이다.
Loaded Image Device Path Protocol은 EFI 부팅 서비스 LoadImage()를 통해 로드된 PE/COFF 이미지의 이미지 핸들에 설치해야만하며 이미지 핸들이 설치되기 전에 EFI 부팅 서비스 LoadImage()에 대한 DevicePath의 매개변수로 지정된 장치 경로의 복사본이 만들어진다.
NULL DevicePath 파라미터를 사용하여 메모리의 버퍼에 대해 LoadImage()를 호출하는 것이 가능하며 이와 같은 경우에는 Loaded Image Device Path Protocol은 NULL 인터페이스 포인터와 함께 설치가 된다.
/** This protocol can be used on any device handle to obtain generic path/location information concerning the physical device or logical device. If the handle does not logically map to a physical device, the handle may not necessarily support the device path protocol. The device path describes the location of the device the handle is for. The size of the Device Path can be determined from the structures that make up the Device Path.**/typedefstruct { UINT8 Type; ///< 0x01 Hardware Device Path. ///< 0x02 ACPI Device Path. ///< 0x03 Messaging Device Path. ///< 0x04 Media Device Path. ///< 0x05 BIOS Boot Specification Device Path. ///< 0x7F End of Hardware Device Path. UINT8 SubType; ///< Varies by Type ///< 0xFF End Entire Device Path, or ///< 0x01 End This Instance of a Device Path and start a new ///< Device Path. UINT8 Length[2]; ///< Specific Device Path data. Type and Sub-Type define ///< type of data. Size of data is included in Length.} EFI_DEVICE_PATH_PROTOCOL;
해당 구조는 Length 바이트 뒤에 오는 실제 경로 데이터의헤더와 같다고 생각하면 된다.
이제 모든 프로토콜의 구조에 대해서 이해를 했으니 프로토콜 구조를 직접 사용하는 방법을 알아야 할 때다. 지난 장에서 사용한 방법은 기초적인 원리를 이해하기 위해서 사용한 것이다. 실제로 UEFI에는 프로토콜 구조를 가져오는 여러가지 기능이 존재하기 때문에 이를 이용하겠다.
Prototype:typedefEFI_STATUS(EFIAPI *EFI_HANDLE_PROTOCOL) ( IN EFI_HANDLE Handle, IN EFI_GUID *Protocol, OUT VOID **Interface);Parameters:Handle The handle being queried. If Handle isNULL, then EFI_INVALID_PARAMETER is returned.Protocol The published unique identifier of the protocol. It is the caller’s responsibility to pass in a valid GUID.
Interface Supplies the address where a pointer to the corresponding Protocol Interface is returned.NULL will be returned in *Interface if a structure is not associated with Protocol.Description:The HandleProtocol() function queries Handle to determine if it supports Protocol. If it does, then on return Interface points to a pointer to the corresponding Protocol Interface. Interface can then be passed to any protocol service to identify the context of the request.
Status Codes Returned:EFI_SUCCESS The interface information for the specified protocol was returned.EFI_UNSUPPORTED The device does not support the specified protocol.EFI_INVALID_PARAMETER Handle is NULL..EFI_INVALID_PARAMETER Protocol is NULL.EFI_INVALID_PARAMETER Interface is NULL.
/**
Converts a device path to its text representation.
@param DevicePath A Pointer to the device to be converted.
@param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
of the display node is used, where applicable. If DisplayOnly
is FALSE, then the longer text representation of the display node
is used.
@param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
representation for a device node can be used, where applicable.
@return A pointer to the allocated text representation of the device path or
NULL if DeviceNode is NULL or there was insufficient memory.
**/
CHAR16 *
EFIAPI
ConvertDevicePathToText (
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN BOOLEAN DisplayOnly,
IN BOOLEAN AllowShortcuts
);
해당 코드의 빌드를 진행하면 아래와 같은 오류가 뜰 것이다.
/root/workspace/edk2/UefiLessonsPkg/ImageInfo/ImageInfo.c:23: undefined reference to `gEfiLoadedImageProtocolGuid'
/usr/bin/ld: /tmp/ImageInfo.dll.vzPH6S.ltrans0.ltrans.o:/root/workspace/edk2/UefiLessonsPkg/ImageInfo/ImageInfo.c:32: undefined reference to `gEfiLoadedImageDevicePathProtocolGuid
프로토콜 섹션을 추가한 뒤 실행을 하면 정상적으로 빌드가 되는 것을 볼 수 있다.
(GUID 변수는 빌드 시스템에서자동으로 생성되는 Build/UefiLessonsPkg/RELEASE_GCC5/X64/UefiLessonsPkg/ImageInfo/ImageInfo/DEBUG/AutoGen.c 파일로 이동한다.)