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