FmpDependencyCheckLib.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /** @file
  2. Provides FMP capsule dependency check services when updating the firmware
  3. image of a FMP device.
  4. Copyright (c) Microsoft Corporation.<BR>
  5. Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
  6. SPDX-License-Identifier: BSD-2-Clause-Patent
  7. **/
  8. #include <PiDxe.h>
  9. #include <Library/BaseLib.h>
  10. #include <Library/BaseMemoryLib.h>
  11. #include <Library/DebugLib.h>
  12. #include <Library/FmpDependencyLib.h>
  13. #include <Library/FmpDependencyCheckLib.h>
  14. #include <Library/MemoryAllocationLib.h>
  15. #include <Library/UefiLib.h>
  16. #include <Library/UefiBootServicesTableLib.h>
  17. #include <Guid/SystemResourceTable.h>
  18. #include <LastAttemptStatus.h>
  19. #include <FmpLastAttemptStatus.h>
  20. /**
  21. Check dependency for firmware update.
  22. @param[in] ImageTypeId Image Type Id.
  23. @param[in] Version New version.
  24. @param[in] Dependencies Fmp dependency.
  25. @param[in] DependenciesSize Size, in bytes, of the Fmp dependency.
  26. @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds the
  27. last attempt status to report back to the caller.
  28. This function will set the value to LAST_ATTEMPT_STATUS_SUCCESS
  29. if an error code is not set.
  30. @retval TRUE Dependencies are satisfied.
  31. @retval FALSE Dependencies are unsatisfied or dependency check fails.
  32. **/
  33. BOOLEAN
  34. EFIAPI
  35. CheckFmpDependency (
  36. IN EFI_GUID ImageTypeId,
  37. IN UINT32 Version,
  38. IN EFI_FIRMWARE_IMAGE_DEP *Dependencies OPTIONAL,
  39. IN UINT32 DependenciesSize,
  40. OUT UINT32 *LastAttemptStatus OPTIONAL
  41. )
  42. {
  43. EFI_STATUS Status;
  44. EFI_HANDLE *HandleBuffer;
  45. UINTN Index;
  46. EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
  47. UINTN ImageInfoSize;
  48. UINT32 LocalLastAttemptStatus;
  49. UINT32 *DescriptorVer;
  50. UINT8 FmpImageInfoCount;
  51. UINTN *DescriptorSize;
  52. UINT32 PackageVersion;
  53. CHAR16 *PackageVersionName;
  54. UINTN NumberOfFmpInstance;
  55. EFI_FIRMWARE_IMAGE_DESCRIPTOR **FmpImageInfoBuf;
  56. FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions;
  57. UINTN FmpVersionsCount;
  58. BOOLEAN IsSatisfied;
  59. LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
  60. FmpImageInfoBuf = NULL;
  61. DescriptorVer = NULL;
  62. DescriptorSize = NULL;
  63. NumberOfFmpInstance = 0;
  64. FmpVersions = NULL;
  65. FmpVersionsCount = 0;
  66. IsSatisfied = TRUE;
  67. PackageVersionName = NULL;
  68. //
  69. // Get ImageDescriptors of all FMP instances, and archive them for dependency evaluation.
  70. //
  71. Status = gBS->LocateHandleBuffer (
  72. ByProtocol,
  73. &gEfiFirmwareManagementProtocolGuid,
  74. NULL,
  75. &NumberOfFmpInstance,
  76. &HandleBuffer
  77. );
  78. if (EFI_ERROR (Status)) {
  79. DEBUG ((DEBUG_ERROR, "CheckFmpDependency: Get Firmware Management Protocol failed. (%r)", Status));
  80. IsSatisfied = FALSE;
  81. LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_FMP_PROTOCOL_NOT_FOUND;
  82. goto cleanup;
  83. }
  84. FmpImageInfoBuf = AllocateZeroPool (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * NumberOfFmpInstance);
  85. if (FmpImageInfoBuf == NULL) {
  86. IsSatisfied = FALSE;
  87. LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_FMP_INFO_BUFFER_FAILED;
  88. goto cleanup;
  89. }
  90. DescriptorVer = AllocateZeroPool (sizeof (UINT32) * NumberOfFmpInstance);
  91. if (DescriptorVer == NULL ) {
  92. IsSatisfied = FALSE;
  93. LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_DESC_VER_BUFFER_FAILED;
  94. goto cleanup;
  95. }
  96. DescriptorSize = AllocateZeroPool (sizeof (UINTN) * NumberOfFmpInstance);
  97. if (DescriptorSize == NULL ) {
  98. IsSatisfied = FALSE;
  99. LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_DESC_SIZE_BUFFER_FAILED;
  100. goto cleanup;
  101. }
  102. FmpVersions = AllocateZeroPool (sizeof (FMP_DEPEX_CHECK_VERSION_DATA) * NumberOfFmpInstance);
  103. if (FmpVersions == NULL) {
  104. IsSatisfied = FALSE;
  105. LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_FMP_VER_BUFFER_FAILED;
  106. goto cleanup;
  107. }
  108. for (Index = 0; Index < NumberOfFmpInstance; Index++) {
  109. Status = gBS->HandleProtocol (
  110. HandleBuffer[Index],
  111. &gEfiFirmwareManagementProtocolGuid,
  112. (VOID **)&Fmp
  113. );
  114. if (EFI_ERROR (Status)) {
  115. continue;
  116. }
  117. ImageInfoSize = 0;
  118. Status = Fmp->GetImageInfo (
  119. Fmp,
  120. &ImageInfoSize,
  121. NULL,
  122. NULL,
  123. NULL,
  124. NULL,
  125. NULL,
  126. NULL
  127. );
  128. if (Status != EFI_BUFFER_TOO_SMALL) {
  129. continue;
  130. }
  131. FmpImageInfoBuf[Index] = AllocateZeroPool (ImageInfoSize);
  132. if (FmpImageInfoBuf[Index] == NULL) {
  133. continue;
  134. }
  135. Status = Fmp->GetImageInfo (
  136. Fmp,
  137. &ImageInfoSize, // ImageInfoSize
  138. FmpImageInfoBuf[Index], // ImageInfo
  139. &DescriptorVer[Index], // DescriptorVersion
  140. &FmpImageInfoCount, // DescriptorCount
  141. &DescriptorSize[Index], // DescriptorSize
  142. &PackageVersion, // PackageVersion
  143. &PackageVersionName // PackageVersionName
  144. );
  145. if (EFI_ERROR (Status)) {
  146. FreePool (FmpImageInfoBuf[Index]);
  147. FmpImageInfoBuf[Index] = NULL;
  148. continue;
  149. }
  150. if (PackageVersionName != NULL) {
  151. FreePool (PackageVersionName);
  152. PackageVersionName = NULL;
  153. }
  154. CopyGuid (&FmpVersions[FmpVersionsCount].ImageTypeId, &FmpImageInfoBuf[Index]->ImageTypeId);
  155. FmpVersions[FmpVersionsCount].Version = FmpImageInfoBuf[Index]->Version;
  156. FmpVersionsCount++;
  157. }
  158. //
  159. // Evaluate firmware image's depex, against the version of other Fmp instances.
  160. //
  161. if (Dependencies != NULL) {
  162. IsSatisfied = EvaluateDependency (Dependencies, DependenciesSize, FmpVersions, FmpVersionsCount, &LocalLastAttemptStatus);
  163. }
  164. if (!IsSatisfied) {
  165. DEBUG ((DEBUG_ERROR, "CheckFmpDependency: %g\'s dependency is not satisfied!\n", ImageTypeId));
  166. goto cleanup;
  167. }
  168. cleanup:
  169. if (FmpImageInfoBuf != NULL) {
  170. for (Index = 0; Index < NumberOfFmpInstance; Index++) {
  171. if (FmpImageInfoBuf[Index] != NULL) {
  172. FreePool (FmpImageInfoBuf[Index]);
  173. }
  174. }
  175. FreePool (FmpImageInfoBuf);
  176. }
  177. if (DescriptorVer != NULL) {
  178. FreePool (DescriptorVer);
  179. }
  180. if (DescriptorSize != NULL) {
  181. FreePool (DescriptorSize);
  182. }
  183. if (FmpVersions != NULL) {
  184. FreePool (FmpVersions);
  185. }
  186. if (LastAttemptStatus != NULL) {
  187. *LastAttemptStatus = LocalLastAttemptStatus;
  188. }
  189. return IsSatisfied;
  190. }