]> git.proxmox.com Git - mirror_edk2.git/blob - FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c
5e0241b25957bbfe8731ae1b3f574a64390652f7
[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) 2020, Intel Corporation. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10 #include <PiDxe.h>
11 #include <Library/BaseLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/FmpDependencyLib.h>
15 #include <Library/FmpDependencyCheckLib.h>
16 #include <Library/MemoryAllocationLib.h>
17 #include <Library/UefiLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19
20 /**
21 Check dependency for firmware update.
22
23 @param[in] ImageTypeId Image Type Id.
24 @param[in] Version New version.
25 @param[in] Dependencies Fmp dependency.
26 @param[in] DependenciesSize Size, in bytes, of the Fmp dependency.
27
28 @retval TRUE Dependencies are satisfied.
29 @retval FALSE Dependencies are unsatisfied or dependency check fails.
30
31 **/
32 BOOLEAN
33 EFIAPI
34 CheckFmpDependency (
35 IN EFI_GUID ImageTypeId,
36 IN UINT32 Version,
37 IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL
38 IN UINT32 DependenciesSize
39 )
40 {
41 EFI_STATUS Status;
42 EFI_HANDLE *HandleBuffer;
43 UINTN Index;
44 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
45 UINTN ImageInfoSize;
46 UINT32 *DescriptorVer;
47 UINT8 FmpImageInfoCount;
48 UINTN *DescriptorSize;
49 UINT32 PackageVersion;
50 CHAR16 *PackageVersionName;
51 UINTN NumberOfFmpInstance;
52 EFI_FIRMWARE_IMAGE_DESCRIPTOR **FmpImageInfoBuf;
53 FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions;
54 UINTN FmpVersionsCount;
55 BOOLEAN IsSatisfied;
56
57 FmpImageInfoBuf = NULL;
58 DescriptorVer = NULL;
59 DescriptorSize = NULL;
60 NumberOfFmpInstance = 0;
61 FmpVersions = NULL;
62 FmpVersionsCount = 0;
63 IsSatisfied = TRUE;
64 PackageVersionName = NULL;
65
66 //
67 // Get ImageDescriptors of all FMP instances, and archive them for dependency evaluation.
68 //
69 Status = gBS->LocateHandleBuffer (
70 ByProtocol,
71 &gEfiFirmwareManagementProtocolGuid,
72 NULL,
73 &NumberOfFmpInstance,
74 &HandleBuffer
75 );
76 if (EFI_ERROR (Status)) {
77 DEBUG ((DEBUG_ERROR, "CheckFmpDependency: Get Firmware Management Protocol failed. (%r)", Status));
78 goto cleanup;
79 }
80
81 FmpImageInfoBuf = AllocateZeroPool (sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * NumberOfFmpInstance);
82 if (FmpImageInfoBuf == NULL) {
83 IsSatisfied = FALSE;
84 goto cleanup;
85 }
86
87 DescriptorVer = AllocateZeroPool (sizeof(UINT32) * NumberOfFmpInstance);
88 if (DescriptorVer == NULL ) {
89 IsSatisfied = FALSE;
90 goto cleanup;
91 }
92
93 DescriptorSize = AllocateZeroPool (sizeof(UINTN) * NumberOfFmpInstance);
94 if (DescriptorSize == NULL ) {
95 IsSatisfied = FALSE;
96 goto cleanup;
97 }
98
99 FmpVersions = AllocateZeroPool (sizeof(FMP_DEPEX_CHECK_VERSION_DATA) * NumberOfFmpInstance);
100 if (FmpVersions == NULL) {
101 IsSatisfied = FALSE;
102 goto cleanup;
103 }
104
105 for (Index = 0; Index < NumberOfFmpInstance; Index ++) {
106 Status = gBS->HandleProtocol (
107 HandleBuffer[Index],
108 &gEfiFirmwareManagementProtocolGuid,
109 (VOID **) &Fmp
110 );
111 if (EFI_ERROR(Status)) {
112 continue;
113 }
114
115 ImageInfoSize = 0;
116 Status = Fmp->GetImageInfo (
117 Fmp,
118 &ImageInfoSize,
119 NULL,
120 NULL,
121 NULL,
122 NULL,
123 NULL,
124 NULL
125 );
126 if (Status != EFI_BUFFER_TOO_SMALL) {
127 continue;
128 }
129
130 FmpImageInfoBuf[Index] = AllocateZeroPool (ImageInfoSize);
131 if (FmpImageInfoBuf[Index] == NULL) {
132 continue;
133 }
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
151 if (PackageVersionName != NULL) {
152 FreePool (PackageVersionName);
153 PackageVersionName = NULL;
154 }
155
156 CopyGuid (&FmpVersions[FmpVersionsCount].ImageTypeId, &FmpImageInfoBuf[Index]->ImageTypeId);
157 FmpVersions[FmpVersionsCount].Version = FmpImageInfoBuf[Index]->Version;
158 FmpVersionsCount ++;
159 }
160
161 //
162 // Evaluate firmware image's depex, against the version of other Fmp instances.
163 //
164 if (Dependencies != NULL) {
165 IsSatisfied = EvaluateDependency (Dependencies, DependenciesSize, FmpVersions, FmpVersionsCount);
166 }
167
168 if (!IsSatisfied) {
169 DEBUG ((DEBUG_ERROR, "CheckFmpDependency: %g\'s dependency is not satisfied!\n", ImageTypeId));
170 goto cleanup;
171 }
172
173 cleanup:
174 if (FmpImageInfoBuf != NULL) {
175 for (Index = 0; Index < NumberOfFmpInstance; Index ++) {
176 if (FmpImageInfoBuf[Index] != NULL) {
177 FreePool (FmpImageInfoBuf[Index]);
178 }
179 }
180 FreePool (FmpImageInfoBuf);
181 }
182
183 if (DescriptorVer != NULL) {
184 FreePool (DescriptorVer);
185 }
186
187 if (DescriptorSize != NULL) {
188 FreePool (DescriptorSize);
189 }
190
191 if (FmpVersions != NULL) {
192 FreePool (FmpVersions);
193 }
194
195 return IsSatisfied;
196 }