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