PayloadLoaderPeim.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /** @file
  2. ELF Load Image Support
  3. Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <PiPei.h>
  7. #include <UniversalPayload/UniversalPayload.h>
  8. #include <UniversalPayload/ExtraData.h>
  9. #include <Ppi/LoadFile.h>
  10. #include <Library/DebugLib.h>
  11. #include <Library/HobLib.h>
  12. #include <Library/PeiServicesLib.h>
  13. #include <Library/MemoryAllocationLib.h>
  14. #include <Library/BaseMemoryLib.h>
  15. #include "ElfLib.h"
  16. /**
  17. The wrapper function of PeiLoadImageLoadImage().
  18. @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
  19. @param FileHandle - Pointer to the FFS file header of the image.
  20. @param ImageAddressArg - Pointer to PE/TE image.
  21. @param ImageSizeArg - Size of PE/TE image.
  22. @param EntryPoint - Pointer to entry point of specified image file for output.
  23. @param AuthenticationState - Pointer to attestation authentication state of image.
  24. @return Status of PeiLoadImageLoadImage().
  25. **/
  26. EFI_STATUS
  27. EFIAPI
  28. PeiLoadFileLoadPayload (
  29. IN CONST EFI_PEI_LOAD_FILE_PPI *This,
  30. IN EFI_PEI_FILE_HANDLE FileHandle,
  31. OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,
  32. OUT UINT64 *ImageSizeArg OPTIONAL,
  33. OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
  34. OUT UINT32 *AuthenticationState
  35. )
  36. {
  37. EFI_STATUS Status;
  38. VOID *Elf;
  39. UNIVERSAL_PAYLOAD_EXTRA_DATA *ExtraData;
  40. ELF_IMAGE_CONTEXT Context;
  41. UINT32 Index;
  42. UINT16 ExtraDataIndex;
  43. CHAR8 *SectionName;
  44. UINTN Offset;
  45. UINTN Size;
  46. UINT32 ExtraDataCount;
  47. UINTN Instance;
  48. UINTN Length;
  49. //
  50. // ELF is added to file as RAW section for EDKII bootloader.
  51. // But RAW section might be added by build tool before the ELF RAW section when alignment is specified for ELF RAW section.
  52. // Below loop skips the RAW section that doesn't contain valid ELF image.
  53. //
  54. Instance = 0;
  55. do {
  56. Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Elf, AuthenticationState);
  57. if (EFI_ERROR (Status)) {
  58. return Status;
  59. }
  60. ZeroMem (&Context, sizeof (Context));
  61. Status = ParseElfImage (Elf, &Context);
  62. } while (EFI_ERROR (Status));
  63. DEBUG ((
  64. DEBUG_INFO,
  65. "Payload File Size: 0x%08X, Mem Size: 0x%08x, Reload: %d\n",
  66. Context.FileSize,
  67. Context.ImageSize,
  68. Context.ReloadRequired
  69. ));
  70. //
  71. // Get UNIVERSAL_PAYLOAD_INFO_HEADER and number of additional PLD sections.
  72. //
  73. ExtraDataCount = 0;
  74. for (Index = 0; Index < Context.ShNum; Index++) {
  75. Status = GetElfSectionName (&Context, Index, &SectionName);
  76. if (EFI_ERROR (Status)) {
  77. continue;
  78. }
  79. DEBUG ((DEBUG_INFO, "Payload Section[%d]: %a\n", Index, SectionName));
  80. if (AsciiStrCmp (SectionName, UNIVERSAL_PAYLOAD_INFO_SEC_NAME) == 0) {
  81. Status = GetElfSectionPos (&Context, Index, &Offset, &Size);
  82. } else if (AsciiStrnCmp (SectionName, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX_LENGTH) == 0) {
  83. Status = GetElfSectionPos (&Context, Index, &Offset, &Size);
  84. if (!EFI_ERROR (Status)) {
  85. ExtraDataCount++;
  86. }
  87. }
  88. }
  89. //
  90. // Report the additional PLD sections through HOB.
  91. //
  92. Length = sizeof (UNIVERSAL_PAYLOAD_EXTRA_DATA) + ExtraDataCount * sizeof (UNIVERSAL_PAYLOAD_EXTRA_DATA_ENTRY);
  93. ExtraData = BuildGuidHob (
  94. &gUniversalPayloadExtraDataGuid,
  95. Length
  96. );
  97. ExtraData->Count = ExtraDataCount;
  98. ExtraData->Header.Revision = UNIVERSAL_PAYLOAD_EXTRA_DATA_REVISION;
  99. ExtraData->Header.Length = (UINT16)Length;
  100. if (ExtraDataCount != 0) {
  101. for (ExtraDataIndex = 0, Index = 0; Index < Context.ShNum; Index++) {
  102. Status = GetElfSectionName (&Context, Index, &SectionName);
  103. if (EFI_ERROR (Status)) {
  104. continue;
  105. }
  106. if (AsciiStrnCmp (SectionName, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX, UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX_LENGTH) == 0) {
  107. Status = GetElfSectionPos (&Context, Index, &Offset, &Size);
  108. if (!EFI_ERROR (Status)) {
  109. ASSERT (ExtraDataIndex < ExtraDataCount);
  110. AsciiStrCpyS (
  111. ExtraData->Entry[ExtraDataIndex].Identifier,
  112. sizeof (ExtraData->Entry[ExtraDataIndex].Identifier),
  113. SectionName + UNIVERSAL_PAYLOAD_EXTRA_SEC_NAME_PREFIX_LENGTH
  114. );
  115. ExtraData->Entry[ExtraDataIndex].Base = (UINTN)(Context.FileBase + Offset);
  116. ExtraData->Entry[ExtraDataIndex].Size = Size;
  117. ExtraDataIndex++;
  118. }
  119. }
  120. }
  121. }
  122. if (Context.ReloadRequired || (Context.PreferredImageAddress != Context.FileBase)) {
  123. Context.ImageAddress = AllocatePages (EFI_SIZE_TO_PAGES (Context.ImageSize));
  124. } else {
  125. Context.ImageAddress = Context.FileBase;
  126. }
  127. //
  128. // Load ELF into the required base
  129. //
  130. Status = LoadElfImage (&Context);
  131. if (!EFI_ERROR (Status)) {
  132. *ImageAddressArg = (UINTN)Context.ImageAddress;
  133. *EntryPoint = Context.EntryPoint;
  134. *ImageSizeArg = Context.ImageSize;
  135. }
  136. return Status;
  137. }
  138. EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = {
  139. PeiLoadFileLoadPayload
  140. };
  141. EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
  142. (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  143. &gEfiPeiLoadFilePpiGuid,
  144. &mPeiLoadFilePpi
  145. };
  146. /**
  147. Install Pei Load File PPI.
  148. @param FileHandle Handle of the file being invoked.
  149. @param PeiServices Describes the list of possible PEI Services.
  150. @retval EFI_SUCESS The entry point executes successfully.
  151. @retval Others Some error occurs during the execution of this function.
  152. **/
  153. EFI_STATUS
  154. EFIAPI
  155. InitializePayloadLoaderPeim (
  156. IN EFI_PEI_FILE_HANDLE FileHandle,
  157. IN CONST EFI_PEI_SERVICES **PeiServices
  158. )
  159. {
  160. EFI_STATUS Status;
  161. Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList);
  162. return Status;
  163. }