#include <libfdt.h>\r
#include <Library/AndroidBootImgLib.h>\r
#include <Library/PrintLib.h>\r
+#include <Library/DevicePathLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/UefiLib.h>\r
\r
#include <Protocol/AndroidBootImg.h>\r
+#include <Protocol/LoadFile2.h>\r
#include <Protocol/LoadedImage.h>\r
\r
+#include <Guid/LinuxEfiInitrdMedia.h>\r
+\r
#define FDT_ADDITIONAL_ENTRIES_SIZE 0x400\r
\r
typedef struct {\r
EFI_DEVICE_PATH_PROTOCOL End;\r
} MEMORY_DEVICE_PATH;\r
\r
+typedef struct {\r
+ VENDOR_DEVICE_PATH VendorMediaNode;\r
+ EFI_DEVICE_PATH_PROTOCOL EndNode;\r
+} RAMDISK_DEVICE_PATH;\r
+\r
STATIC ANDROID_BOOTIMG_PROTOCOL *mAndroidBootImg;\r
+STATIC VOID *mRamdiskData = NULL;\r
+STATIC UINTN mRamdiskSize = 0;\r
+STATIC EFI_HANDLE mRamDiskLoadFileHandle = NULL;\r
\r
STATIC CONST MEMORY_DEVICE_PATH mMemoryDevicePathTemplate =\r
{\r
} // End\r
};\r
\r
+STATIC CONST RAMDISK_DEVICE_PATH mRamdiskDevicePath =\r
+{\r
+ {\r
+ {\r
+ MEDIA_DEVICE_PATH,\r
+ MEDIA_VENDOR_DP,\r
+ { sizeof (VENDOR_DEVICE_PATH), 0 }\r
+ },\r
+ LINUX_EFI_INITRD_MEDIA_GUID\r
+ },\r
+ {\r
+ END_DEVICE_PATH_TYPE,\r
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+ { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }\r
+ }\r
+};\r
+\r
+/**\r
+ Causes the driver to load a specified file.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param FilePath The device specific path of the file to load.\r
+ @param BootPolicy Should always be FALSE.\r
+ @param BufferSize On input the size of Buffer in bytes. On output with a return\r
+ code of EFI_SUCCESS, the amount of data transferred to\r
+ Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,\r
+ the size of Buffer required to retrieve the requested file.\r
+ @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL,\r
+ then no the size of the requested file is returned in\r
+ BufferSize.\r
+\r
+ @retval EFI_SUCCESS The file was loaded.\r
+ @retval EFI_UNSUPPORTED BootPolicy is TRUE.\r
+ @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or\r
+ BufferSize is NULL.\r
+ @retval EFI_NO_MEDIA No medium was present to load the file.\r
+ @retval EFI_DEVICE_ERROR The file was not loaded due to a device error.\r
+ @retval EFI_NO_RESPONSE The remote system did not respond.\r
+ @retval EFI_NOT_FOUND The file was not found\r
+ @retval EFI_ABORTED The file load process was manually canceled.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current\r
+ directory entry. BufferSize has been updated with\r
+ the size needed to complete the request.\r
+\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AndroidBootImgLoadFile2 (\r
+ IN EFI_LOAD_FILE2_PROTOCOL *This,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ IN BOOLEAN BootPolicy,\r
+ IN OUT UINTN *BufferSize,\r
+ IN VOID *Buffer OPTIONAL\r
+ )\r
+\r
+{\r
+ // Verify if the valid parameters\r
+ if (This == NULL ||\r
+ BufferSize == NULL ||\r
+ FilePath == NULL ||\r
+ !IsDevicePathValid (FilePath, 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BootPolicy) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ // Check if the given buffer size is big enough\r
+ // EFI_BUFFER_TOO_SMALL to allow caller to allocate a bigger buffer\r
+ if (mRamdiskSize == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ if (Buffer == NULL || *BufferSize < mRamdiskSize) {\r
+ *BufferSize = mRamdiskSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ // Copy InitRd\r
+ CopyMem (Buffer, mRamdiskData, mRamdiskSize);\r
+ *BufferSize = mRamdiskSize;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+///\r
+/// Load File Protocol instance\r
+///\r
+STATIC EFI_LOAD_FILE2_PROTOCOL mAndroidBootImgLoadFile2 = {\r
+ AndroidBootImgLoadFile2\r
+};\r
+\r
EFI_STATUS\r
AndroidBootImgGetImgSize (\r
IN VOID *BootImg,\r
return Status;\r
}\r
\r
+EFI_STATUS\r
+AndroidBootImgInstallLoadFile2 (\r
+ IN VOID *RamdiskData,\r
+ IN UINTN RamdiskSize\r
+ )\r
+{\r
+ mRamDiskLoadFileHandle = NULL;\r
+ mRamdiskData = RamdiskData;\r
+ mRamdiskSize = RamdiskSize;\r
+ return gBS->InstallMultipleProtocolInterfaces (\r
+ &mRamDiskLoadFileHandle,\r
+ &gEfiLoadFile2ProtocolGuid,\r
+ &mAndroidBootImgLoadFile2,\r
+ &gEfiDevicePathProtocolGuid,\r
+ &mRamdiskDevicePath,\r
+ NULL\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+AndroidBootImgUninstallLoadFile2 (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+ mRamdiskData = NULL;\r
+ mRamdiskSize = 0;\r
+ if (mRamDiskLoadFileHandle != NULL) {\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ mRamDiskLoadFileHandle,\r
+ &gEfiLoadFile2ProtocolGuid,\r
+ &mAndroidBootImgLoadFile2,\r
+ &gEfiDevicePathProtocolGuid,\r
+ &mRamdiskDevicePath,\r
+ NULL\r
+ );\r
+ mRamDiskLoadFileHandle = NULL;\r
+ }\r
+ return Status;\r
+}\r
+\r
+BOOLEAN AndroidBootImgAcpiSupported (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *AcpiTable;\r
+\r
+ Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, &AcpiTable);\r
+ return !EFI_ERROR (Status);\r
+}\r
+\r
EFI_STATUS\r
AndroidBootImgLocateFdt (\r
IN VOID *BootImg,\r
goto Fdt_Exit;\r
}\r
\r
- ChosenNode = AndroidBootImgGetChosenNode(UpdatedFdtBase);\r
- if (!ChosenNode) {\r
- goto Fdt_Exit;\r
- }\r
+ if (FeaturePcdGet (PcdAndroidBootLoadFile2)) {\r
+ Status = AndroidBootImgInstallLoadFile2 (RamdiskData, RamdiskSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Fdt_Exit;\r
+ }\r
+ } else {\r
+ ChosenNode = AndroidBootImgGetChosenNode(UpdatedFdtBase);\r
+ if (!ChosenNode) {\r
+ goto Fdt_Exit;\r
+ }\r
\r
- Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode,\r
- "linux,initrd-start",\r
- (UINTN)RamdiskData);\r
- if (EFI_ERROR (Status)) {\r
- goto Fdt_Exit;\r
- }\r
+ Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode,\r
+ "linux,initrd-start",\r
+ (UINTN)RamdiskData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Fdt_Exit;\r
+ }\r
\r
- Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode,\r
- "linux,initrd-end",\r
- (UINTN)RamdiskData + RamdiskSize);\r
- if (EFI_ERROR (Status)) {\r
- goto Fdt_Exit;\r
+ Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode,\r
+ "linux,initrd-end",\r
+ (UINTN)RamdiskData + RamdiskSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Fdt_Exit;\r
+ }\r
}\r
\r
if (mAndroidBootImg->UpdateDtb) {\r
if (EFI_ERROR (Status)) {\r
goto Fdt_Exit;\r
}\r
-\r
- Status = gBS->InstallConfigurationTable (\r
- &gFdtTableGuid,\r
- (VOID *)(UINTN)NewFdtBase\r
- );\r
+ } else {\r
+ NewFdtBase = UpdatedFdtBase;\r
}\r
+ Status = gBS->InstallConfigurationTable (\r
+ &gFdtTableGuid,\r
+ (VOID *)(UINTN)NewFdtBase\r
+ );\r
\r
if (!EFI_ERROR (Status)) {\r
return EFI_SUCCESS;\r
UINTN RamdiskSize;\r
IN VOID *FdtBase;\r
\r
+ NewKernelArg = NULL;\r
+ ImageHandle = NULL;\r
+\r
Status = gBS->LocateProtocol (&gAndroidBootImgProtocolGuid, NULL,\r
(VOID **) &mAndroidBootImg);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto Exit;\r
}\r
\r
Status = AndroidBootImgGetKernelInfo (\r
&KernelSize\r
);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto Exit;\r
}\r
\r
NewKernelArg = AllocateZeroPool (ANDROID_BOOTIMG_KERNEL_ARGS_SIZE);\r
if (NewKernelArg == NULL) {\r
DEBUG ((DEBUG_ERROR, "Fail to allocate memory\n"));\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
}\r
\r
Status = AndroidBootImgUpdateArgs (Buffer, NewKernelArg);\r
if (EFI_ERROR (Status)) {\r
- FreePool (NewKernelArg);\r
- return Status;\r
+ goto Exit;\r
}\r
\r
Status = AndroidBootImgGetRamdiskInfo (\r
&RamdiskSize\r
);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto Exit;\r
}\r
\r
- Status = AndroidBootImgLocateFdt (Buffer, &FdtBase);\r
- if (EFI_ERROR (Status)) {\r
- FreePool (NewKernelArg);\r
- return Status;\r
- }\r
+ if (AndroidBootImgAcpiSupported ()) {\r
+ Status = AndroidBootImgInstallLoadFile2 (RamdiskData, RamdiskSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+ } else {\r
+ Status = AndroidBootImgLocateFdt (Buffer, &FdtBase);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
\r
- Status = AndroidBootImgUpdateFdt (Buffer, FdtBase, RamdiskData, RamdiskSize);\r
- if (EFI_ERROR (Status)) {\r
- FreePool (NewKernelArg);\r
- return Status;\r
+ Status = AndroidBootImgUpdateFdt (Buffer, FdtBase, RamdiskData, RamdiskSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
}\r
\r
KernelDevicePath = mMemoryDevicePathTemplate;\r
(EFI_DEVICE_PATH *)&KernelDevicePath,\r
(VOID*)(UINTN)Kernel, KernelSize, &ImageHandle);\r
if (EFI_ERROR (Status)) {\r
- //\r
- // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created\r
- // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.\r
- // If the caller doesn't have the option to defer the execution of an image, we should\r
- // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.\r
- //\r
- if (Status == EFI_SECURITY_VIOLATION) {\r
- gBS->UnloadImage (ImageHandle);\r
- }\r
- return Status;\r
+ goto Exit;\r
}\r
\r
// Set kernel arguments\r
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid,\r
(VOID **) &ImageInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
ImageInfo->LoadOptions = NewKernelArg;\r
ImageInfo->LoadOptionsSize = StrLen (NewKernelArg) * sizeof (CHAR16);\r
\r
Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
// Clear the Watchdog Timer if the image returns\r
gBS->SetWatchdogTimer (0, 0x10000, 0, NULL);\r
- return EFI_SUCCESS;\r
+\r
+Exit:\r
+ //Unload image as it will not be used anymore\r
+ if (ImageHandle != NULL) {\r
+ gBS->UnloadImage (ImageHandle);\r
+ ImageHandle = NULL;\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ if (NewKernelArg != NULL) {\r
+ FreePool (NewKernelArg);\r
+ NewKernelArg = NULL;\r
+ }\r
+ }\r
+ AndroidBootImgUninstallLoadFile2 ();\r
+ return Status;\r
}\r