diff --git a/EmbeddedPkg/EmbeddedPkg.dec b/EmbeddedPkg/EmbeddedPkg.dec index c2068ce5a8..7638aaaade 100644 --- a/EmbeddedPkg/EmbeddedPkg.dec +++ b/EmbeddedPkg/EmbeddedPkg.dec @@ -86,6 +86,7 @@ [PcdsFeatureFlag.common] gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|FALSE|BOOLEAN|0x0000001b gEmbeddedTokenSpaceGuid.PcdGdbSerial|FALSE|BOOLEAN|0x00000053 + gEmbeddedTokenSpaceGuid.PcdAndroidBootLoadFile2|FALSE|BOOLEAN|0x0000005b [PcdsFixedAtBuild.common] gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0|UINT32|0x0000000b diff --git a/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c index 4f8ff5b261..cc39fef489 100644 --- a/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c +++ b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c @@ -10,12 +10,16 @@ #include #include #include +#include #include #include #include +#include #include +#include + #define FDT_ADDITIONAL_ENTRIES_SIZE 0x400 typedef struct { @@ -23,7 +27,15 @@ typedef struct { EFI_DEVICE_PATH_PROTOCOL End; } MEMORY_DEVICE_PATH; +typedef struct { + VENDOR_DEVICE_PATH VendorMediaNode; + EFI_DEVICE_PATH_PROTOCOL EndNode; +} RAMDISK_DEVICE_PATH; + STATIC ANDROID_BOOTIMG_PROTOCOL *mAndroidBootImg; +STATIC VOID *mRamdiskData = NULL; +STATIC UINTN mRamdiskSize = 0; +STATIC EFI_HANDLE mRamDiskLoadFileHandle = NULL; STATIC CONST MEMORY_DEVICE_PATH mMemoryDevicePathTemplate = { @@ -46,6 +58,99 @@ STATIC CONST MEMORY_DEVICE_PATH mMemoryDevicePathTemplate = } // End }; +STATIC CONST RAMDISK_DEVICE_PATH mRamdiskDevicePath = +{ + { + { + MEDIA_DEVICE_PATH, + MEDIA_VENDOR_DP, + { sizeof (VENDOR_DEVICE_PATH), 0 } + }, + LINUX_EFI_INITRD_MEDIA_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } + } +}; + +/** + Causes the driver to load a specified file. + + @param This Protocol instance pointer. + @param FilePath The device specific path of the file to load. + @param BootPolicy Should always be FALSE. + @param BufferSize On input the size of Buffer in bytes. On output with a return + code of EFI_SUCCESS, the amount of data transferred to + Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, + the size of Buffer required to retrieve the requested file. + @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL, + then no the size of the requested file is returned in + BufferSize. + + @retval EFI_SUCCESS The file was loaded. + @retval EFI_UNSUPPORTED BootPolicy is TRUE. + @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or + BufferSize is NULL. + @retval EFI_NO_MEDIA No medium was present to load the file. + @retval EFI_DEVICE_ERROR The file was not loaded due to a device error. + @retval EFI_NO_RESPONSE The remote system did not respond. + @retval EFI_NOT_FOUND The file was not found + @retval EFI_ABORTED The file load process was manually canceled. + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current + directory entry. BufferSize has been updated with + the size needed to complete the request. + + +**/ +EFI_STATUS +EFIAPI +AndroidBootImgLoadFile2 ( + IN EFI_LOAD_FILE2_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN BOOLEAN BootPolicy, + IN OUT UINTN *BufferSize, + IN VOID *Buffer OPTIONAL + ) + +{ + // Verify if the valid parameters + if (This == NULL || + BufferSize == NULL || + FilePath == NULL || + !IsDevicePathValid (FilePath, 0)) { + return EFI_INVALID_PARAMETER; + } + + if (BootPolicy) { + return EFI_UNSUPPORTED; + } + + // Check if the given buffer size is big enough + // EFI_BUFFER_TOO_SMALL to allow caller to allocate a bigger buffer + if (mRamdiskSize == 0) { + return EFI_NOT_FOUND; + } + if (Buffer == NULL || *BufferSize < mRamdiskSize) { + *BufferSize = mRamdiskSize; + return EFI_BUFFER_TOO_SMALL; + } + + // Copy InitRd + CopyMem (Buffer, mRamdiskData, mRamdiskSize); + *BufferSize = mRamdiskSize; + + return EFI_SUCCESS; +} + +/// +/// Load File Protocol instance +/// +STATIC EFI_LOAD_FILE2_PROTOCOL mAndroidBootImgLoadFile2 = { + AndroidBootImgLoadFile2 +}; + EFI_STATUS AndroidBootImgGetImgSize ( IN VOID *BootImg, @@ -214,6 +319,60 @@ AndroidBootImgUpdateArgs ( return Status; } +EFI_STATUS +AndroidBootImgInstallLoadFile2 ( + IN VOID *RamdiskData, + IN UINTN RamdiskSize + ) +{ + mRamDiskLoadFileHandle = NULL; + mRamdiskData = RamdiskData; + mRamdiskSize = RamdiskSize; + return gBS->InstallMultipleProtocolInterfaces ( + &mRamDiskLoadFileHandle, + &gEfiLoadFile2ProtocolGuid, + &mAndroidBootImgLoadFile2, + &gEfiDevicePathProtocolGuid, + &mRamdiskDevicePath, + NULL + ); +} + +EFI_STATUS +AndroidBootImgUninstallLoadFile2 ( + VOID + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + mRamdiskData = NULL; + mRamdiskSize = 0; + if (mRamDiskLoadFileHandle != NULL) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + mRamDiskLoadFileHandle, + &gEfiLoadFile2ProtocolGuid, + &mAndroidBootImgLoadFile2, + &gEfiDevicePathProtocolGuid, + &mRamdiskDevicePath, + NULL + ); + mRamDiskLoadFileHandle = NULL; + } + return Status; +} + +BOOLEAN AndroidBootImgAcpiSupported ( + VOID + ) +{ + EFI_STATUS Status; + VOID *AcpiTable; + + Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, &AcpiTable); + return !EFI_ERROR (Status); +} + EFI_STATUS AndroidBootImgLocateFdt ( IN VOID *BootImg, @@ -325,23 +484,30 @@ AndroidBootImgUpdateFdt ( goto Fdt_Exit; } - ChosenNode = AndroidBootImgGetChosenNode(UpdatedFdtBase); - if (!ChosenNode) { - goto Fdt_Exit; - } + if (FeaturePcdGet (PcdAndroidBootLoadFile2)) { + Status = AndroidBootImgInstallLoadFile2 (RamdiskData, RamdiskSize); + if (EFI_ERROR (Status)) { + goto Fdt_Exit; + } + } else { + ChosenNode = AndroidBootImgGetChosenNode(UpdatedFdtBase); + if (!ChosenNode) { + goto Fdt_Exit; + } - Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode, - "linux,initrd-start", - (UINTN)RamdiskData); - if (EFI_ERROR (Status)) { - goto Fdt_Exit; - } + Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode, + "linux,initrd-start", + (UINTN)RamdiskData); + if (EFI_ERROR (Status)) { + goto Fdt_Exit; + } - Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode, - "linux,initrd-end", - (UINTN)RamdiskData + RamdiskSize); - if (EFI_ERROR (Status)) { - goto Fdt_Exit; + Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode, + "linux,initrd-end", + (UINTN)RamdiskData + RamdiskSize); + if (EFI_ERROR (Status)) { + goto Fdt_Exit; + } } if (mAndroidBootImg->UpdateDtb) { @@ -422,14 +588,21 @@ AndroidBootImgBoot ( goto Exit; } - Status = AndroidBootImgLocateFdt (Buffer, &FdtBase); - if (EFI_ERROR (Status)) { - goto Exit; - } + if (AndroidBootImgAcpiSupported ()) { + Status = AndroidBootImgInstallLoadFile2 (RamdiskData, RamdiskSize); + if (EFI_ERROR (Status)) { + goto Exit; + } + } else { + Status = AndroidBootImgLocateFdt (Buffer, &FdtBase); + if (EFI_ERROR (Status)) { + goto Exit; + } - Status = AndroidBootImgUpdateFdt (Buffer, FdtBase, RamdiskData, RamdiskSize); - if (EFI_ERROR (Status)) { - goto Exit; + Status = AndroidBootImgUpdateFdt (Buffer, FdtBase, RamdiskData, RamdiskSize); + if (EFI_ERROR (Status)) { + goto Exit; + } } KernelDevicePath = mMemoryDevicePathTemplate; @@ -473,5 +646,6 @@ Exit: NewKernelArg = NULL; } } + AndroidBootImgUninstallLoadFile2 (); return Status; } diff --git a/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.inf b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.inf index bfed4ba9dc..8eefeef4f9 100644 --- a/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.inf +++ b/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.inf @@ -39,6 +39,11 @@ [Protocols] gAndroidBootImgProtocolGuid gEfiLoadedImageProtocolGuid + gEfiLoadFile2ProtocolGuid [Guids] + gEfiAcpiTableGuid gFdtTableGuid + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdAndroidBootLoadFile2