]> git.proxmox.com Git - mirror_edk2.git/blame - IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeFmp.c
IntelSiliconPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelSiliconPkg / Feature / Capsule / MicrocodeUpdateDxe / MicrocodeFmp.c
CommitLineData
88266859
JY
1/** @file\r
2 Produce FMP instance for Microcode.\r
3\r
1779cf40 4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
8f7a05e1 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
88266859
JY
6\r
7**/\r
8\r
9#include "MicrocodeUpdate.h"\r
10\r
11//\r
12// MicrocodeFmp driver private data\r
13//\r
14MICROCODE_FMP_PRIVATE_DATA *mMicrocodeFmpPrivate = NULL;\r
15\r
16EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol = {\r
17 FmpGetImageInfo,\r
18 FmpGetImage,\r
19 FmpSetImage,\r
20 FmpCheckImage,\r
21 FmpGetPackageInfo,\r
22 FmpSetPackageInfo\r
23};\r
24\r
25/**\r
26 Initialize Microcode Descriptor.\r
27\r
28 @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
29\r
30 @return EFI_SUCCESS Microcode Descriptor is initialized.\r
31**/\r
32EFI_STATUS\r
33InitializeMicrocodeDescriptor (\r
34 IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
35 );\r
36\r
37/**\r
38 Returns information about the current firmware image(s) of the device.\r
39\r
40 This function allows a copy of the current firmware image to be created and saved.\r
41 The saved copy could later been used, for example, in firmware image recovery or rollback.\r
42\r
43 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
44 @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.\r
45 On input, this is the size of the buffer allocated by the caller.\r
46 On output, it is the size of the buffer returned by the firmware\r
47 if the buffer was large enough, or the size of the buffer needed\r
48 to contain the image(s) information if the buffer was too small.\r
49 @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)\r
50 information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.\r
51 @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number\r
52 associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
53 @param[out] DescriptorCount A pointer to the location in which firmware returns the number of\r
54 descriptors or firmware images within this device.\r
55 @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,\r
56 of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
57 @param[out] PackageVersion A version number that represents all the firmware images in the device.\r
58 The format is vendor specific and new version must have a greater value\r
59 than the old version. If PackageVersion is not supported, the value is\r
60 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison\r
61 is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates\r
62 that package version update is in progress.\r
63 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the\r
64 package version name. The buffer is allocated by this function with\r
65 AllocatePool(), and it is the caller's responsibility to free it with a call\r
66 to FreePool().\r
67\r
68 @retval EFI_SUCCESS The device was successfully updated with the new image.\r
69 @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size\r
70 needed to hold the image(s) information is returned in ImageInfoSize.\r
71 @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.\r
72 @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.\r
73\r
74**/\r
75EFI_STATUS\r
76EFIAPI\r
77FmpGetImageInfo (\r
78 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
79 IN OUT UINTN *ImageInfoSize,\r
80 IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,\r
81 OUT UINT32 *DescriptorVersion,\r
82 OUT UINT8 *DescriptorCount,\r
83 OUT UINTN *DescriptorSize,\r
84 OUT UINT32 *PackageVersion,\r
85 OUT CHAR16 **PackageVersionName\r
86 )\r
87{\r
88 MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;\r
89 UINTN Index;\r
90\r
91 MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);\r
92\r
93 if(ImageInfoSize == NULL) {\r
94 return EFI_INVALID_PARAMETER;\r
95 }\r
96\r
97 if (*ImageInfoSize < sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount) {\r
98 *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount;\r
99 return EFI_BUFFER_TOO_SMALL;\r
100 }\r
101\r
102 if (ImageInfo == NULL ||\r
103 DescriptorVersion == NULL ||\r
104 DescriptorCount == NULL ||\r
105 DescriptorSize == NULL ||\r
106 PackageVersion == NULL ||\r
107 PackageVersionName == NULL) {\r
108 return EFI_INVALID_PARAMETER;\r
109 }\r
110\r
111 *ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount;\r
112 *DescriptorSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
113 *DescriptorCount = MicrocodeFmpPrivate->DescriptorCount;\r
114 *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;\r
115\r
116 //\r
117 // supports 1 ImageInfo descriptor\r
118 //\r
119 CopyMem(&ImageInfo[0], MicrocodeFmpPrivate->ImageDescriptor, sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount);\r
120 for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {\r
121 if ((ImageInfo[Index].AttributesSetting & IMAGE_ATTRIBUTE_IN_USE) != 0) {\r
122 ImageInfo[Index].LastAttemptVersion = MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion;\r
123 ImageInfo[Index].LastAttemptStatus = MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus;\r
124 }\r
125 }\r
126\r
127 //\r
128 // package version\r
129 //\r
130 *PackageVersion = MicrocodeFmpPrivate->PackageVersion;\r
131 if (MicrocodeFmpPrivate->PackageVersionName != NULL) {\r
132 *PackageVersionName = AllocateCopyPool(StrSize(MicrocodeFmpPrivate->PackageVersionName), MicrocodeFmpPrivate->PackageVersionName);\r
133 }\r
134\r
135 return EFI_SUCCESS;\r
136}\r
137\r
138/**\r
139 Retrieves a copy of the current firmware image of the device.\r
140\r
141 This function allows a copy of the current firmware image to be created and saved.\r
142 The saved copy could later been used, for example, in firmware image recovery or rollback.\r
143\r
144 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
145 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
146 The number is between 1 and DescriptorCount.\r
147 @param[in,out] Image Points to the buffer where the current image is copied to.\r
148 @param[in,out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.\r
149 On return, points to the length of the image, in bytes.\r
150\r
151 @retval EFI_SUCCESS The device was successfully updated with the new image.\r
152 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the\r
153 image. The current buffer size needed to hold the image is returned\r
154 in ImageSize.\r
155 @retval EFI_INVALID_PARAMETER The Image was NULL.\r
156 @retval EFI_NOT_FOUND The current image is not copied to the buffer.\r
157 @retval EFI_UNSUPPORTED The operation is not supported.\r
1779cf40 158 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
88266859
JY
159\r
160**/\r
161EFI_STATUS\r
162EFIAPI\r
163FmpGetImage (\r
164 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
165 IN UINT8 ImageIndex,\r
166 IN OUT VOID *Image,\r
167 IN OUT UINTN *ImageSize\r
168 )\r
169{\r
170 MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;\r
2ed65824 171 MICROCODE_INFO *MicrocodeInfo;\r
88266859
JY
172\r
173 if (Image == NULL || ImageSize == NULL) {\r
174 return EFI_INVALID_PARAMETER;\r
175 }\r
176\r
177 MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);\r
178\r
179 if (ImageIndex == 0 || ImageIndex > MicrocodeFmpPrivate->DescriptorCount || ImageSize == NULL || Image == NULL) {\r
180 return EFI_INVALID_PARAMETER;\r
181 }\r
182\r
2ed65824
JY
183 MicrocodeInfo = &MicrocodeFmpPrivate->MicrocodeInfo[ImageIndex - 1];\r
184\r
185 if (*ImageSize < MicrocodeInfo->TotalSize) {\r
186 *ImageSize = MicrocodeInfo->TotalSize;\r
187 return EFI_BUFFER_TOO_SMALL;\r
188 }\r
189\r
190 *ImageSize = MicrocodeInfo->TotalSize;\r
191 CopyMem (Image, MicrocodeInfo->MicrocodeEntryPoint, MicrocodeInfo->TotalSize);\r
192 return EFI_SUCCESS;\r
88266859
JY
193}\r
194\r
195/**\r
196 Updates the firmware image of the device.\r
197\r
198 This function updates the hardware with the new firmware image.\r
199 This function returns EFI_UNSUPPORTED if the firmware image is not updatable.\r
200 If the firmware image is updatable, the function should perform the following minimal validations\r
201 before proceeding to do the firmware image update.\r
202 - Validate the image authentication if image has attribute\r
203 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns\r
204 EFI_SECURITY_VIOLATION if the validation fails.\r
205 - Validate the image is a supported image for this device. The function returns EFI_ABORTED if\r
206 the image is unsupported. The function can optionally provide more detailed information on\r
207 why the image is not a supported image.\r
208 - Validate the data from VendorCode if not null. Image validation must be performed before\r
209 VendorCode data validation. VendorCode data is ignored or considered invalid if image\r
210 validation failed. The function returns EFI_ABORTED if the data is invalid.\r
211\r
212 VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if\r
213 the caller did not specify the policy or use the default policy. As an example, vendor can implement\r
214 a policy to allow an option to force a firmware image update when the abort reason is due to the new\r
215 firmware image version is older than the current firmware image version or bad image checksum.\r
216 Sensitive operations such as those wiping the entire firmware image and render the device to be\r
217 non-functional should be encoded in the image itself rather than passed with the VendorCode.\r
218 AbortReason enables vendor to have the option to provide a more detailed description of the abort\r
219 reason to the caller.\r
220\r
221 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
222 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
223 The number is between 1 and DescriptorCount.\r
224 @param[in] Image Points to the new image.\r
225 @param[in] ImageSize Size of the new image in bytes.\r
226 @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.\r
227 Null indicates the caller did not specify the policy or use the default policy.\r
228 @param[in] Progress A function used by the driver to report the progress of the firmware update.\r
229 @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more\r
230 details for the aborted operation. The buffer is allocated by this function\r
231 with AllocatePool(), and it is the caller's responsibility to free it with a\r
232 call to FreePool().\r
233\r
234 @retval EFI_SUCCESS The device was successfully updated with the new image.\r
235 @retval EFI_ABORTED The operation is aborted.\r
236 @retval EFI_INVALID_PARAMETER The Image was NULL.\r
237 @retval EFI_UNSUPPORTED The operation is not supported.\r
1779cf40 238 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
88266859
JY
239\r
240**/\r
241EFI_STATUS\r
242EFIAPI\r
243FmpSetImage (\r
244 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
245 IN UINT8 ImageIndex,\r
246 IN CONST VOID *Image,\r
247 IN UINTN ImageSize,\r
248 IN CONST VOID *VendorCode,\r
249 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,\r
250 OUT CHAR16 **AbortReason\r
251 )\r
252{\r
253 EFI_STATUS Status;\r
254 EFI_STATUS VarStatus;\r
255 MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;\r
256\r
257 if (Image == NULL || AbortReason == NULL) {\r
258 return EFI_INVALID_PARAMETER;\r
259 }\r
260\r
261 MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);\r
262 *AbortReason = NULL;\r
263\r
264 if (ImageIndex == 0 || ImageIndex > MicrocodeFmpPrivate->DescriptorCount || Image == NULL) {\r
265 return EFI_INVALID_PARAMETER;\r
266 }\r
267\r
2ed65824 268 Status = MicrocodeWrite(MicrocodeFmpPrivate, (VOID *)Image, ImageSize, &MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, &MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus, AbortReason);\r
e9179788 269 DEBUG((DEBUG_INFO, "SetImage - LastAttempt Version - 0x%x, Status - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));\r
88266859
JY
270 VarStatus = gRT->SetVariable(\r
271 MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,\r
272 &gEfiCallerIdGuid,\r
273 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
274 sizeof(MicrocodeFmpPrivate->LastAttempt),\r
275 &MicrocodeFmpPrivate->LastAttempt\r
276 );\r
e9179788 277 DEBUG((DEBUG_INFO, "SetLastAttempt - %r\n", VarStatus));\r
88266859
JY
278\r
279 if (!EFI_ERROR(Status)) {\r
280 InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);\r
31d060d9 281 DumpPrivateInfo (MicrocodeFmpPrivate);\r
88266859
JY
282 }\r
283\r
284 return Status;\r
285}\r
286\r
287/**\r
288 Checks if the firmware image is valid for the device.\r
289\r
290 This function allows firmware update application to validate the firmware image without\r
291 invoking the SetImage() first.\r
292\r
293 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
294 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.\r
295 The number is between 1 and DescriptorCount.\r
296 @param[in] Image Points to the new image.\r
297 @param[in] ImageSize Size of the new image in bytes.\r
298 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,\r
299 if available, additional information if the image is invalid.\r
300\r
301 @retval EFI_SUCCESS The image was successfully checked.\r
302 @retval EFI_INVALID_PARAMETER The Image was NULL.\r
303 @retval EFI_UNSUPPORTED The operation is not supported.\r
1779cf40 304 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
88266859
JY
305\r
306**/\r
307EFI_STATUS\r
308EFIAPI\r
309FmpCheckImage (\r
310 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
311 IN UINT8 ImageIndex,\r
312 IN CONST VOID *Image,\r
313 IN UINTN ImageSize,\r
314 OUT UINT32 *ImageUpdatable\r
315 )\r
316{\r
317 return EFI_UNSUPPORTED;\r
318}\r
319\r
320/**\r
321 Returns information about the firmware package.\r
322\r
323 This function returns package information.\r
324\r
325 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
326 @param[out] PackageVersion A version number that represents all the firmware images in the device.\r
327 The format is vendor specific and new version must have a greater value\r
328 than the old version. If PackageVersion is not supported, the value is\r
329 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version\r
330 comparison is to be performed using PackageVersionName. A value of\r
331 0xFFFFFFFD indicates that package version update is in progress.\r
332 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing\r
333 the package version name. The buffer is allocated by this function with\r
334 AllocatePool(), and it is the caller's responsibility to free it with a\r
335 call to FreePool().\r
336 @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of\r
337 package version name. A value of 0 indicates the device does not support\r
338 update of package version name. Length is the number of Unicode characters,\r
339 including the terminating null character.\r
340 @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute\r
341 Definitions' for possible returned values of this parameter. A value of 1\r
342 indicates the attribute is supported and the current setting value is\r
343 indicated in AttributesSetting. A value of 0 indicates the attribute is not\r
344 supported and the current setting value in AttributesSetting is meaningless.\r
345 @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned\r
346 values of this parameter\r
347\r
348 @retval EFI_SUCCESS The package information was successfully returned.\r
349 @retval EFI_UNSUPPORTED The operation is not supported.\r
350\r
351**/\r
352EFI_STATUS\r
353EFIAPI\r
354FmpGetPackageInfo (\r
355 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
356 OUT UINT32 *PackageVersion,\r
357 OUT CHAR16 **PackageVersionName,\r
358 OUT UINT32 *PackageVersionNameMaxLen,\r
359 OUT UINT64 *AttributesSupported,\r
360 OUT UINT64 *AttributesSetting\r
361 )\r
362{\r
363 return EFI_UNSUPPORTED;\r
364}\r
365\r
366/**\r
367 Updates information about the firmware package.\r
368\r
369 This function updates package information.\r
370 This function returns EFI_UNSUPPORTED if the package information is not updatable.\r
371 VendorCode enables vendor to implement vendor-specific package information update policy.\r
372 Null if the caller did not specify this policy or use the default policy.\r
373\r
374 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.\r
375 @param[in] Image Points to the authentication image.\r
376 Null if authentication is not required.\r
377 @param[in] ImageSize Size of the authentication image in bytes.\r
378 0 if authentication is not required.\r
379 @param[in] VendorCode This enables vendor to implement vendor-specific firmware\r
380 image update policy.\r
381 Null indicates the caller did not specify this policy or use\r
382 the default policy.\r
383 @param[in] PackageVersion The new package version.\r
384 @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing\r
385 the package version name.\r
386 The string length is equal to or less than the value returned in\r
387 PackageVersionNameMaxLen.\r
388\r
389 @retval EFI_SUCCESS The device was successfully updated with the new package\r
390 information.\r
391 @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value\r
392 returned in PackageVersionNameMaxLen.\r
393 @retval EFI_UNSUPPORTED The operation is not supported.\r
1779cf40 394 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
88266859
JY
395\r
396**/\r
397EFI_STATUS\r
398EFIAPI\r
399FmpSetPackageInfo (\r
400 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,\r
401 IN CONST VOID *Image,\r
402 IN UINTN ImageSize,\r
403 IN CONST VOID *VendorCode,\r
404 IN UINT32 PackageVersion,\r
405 IN CONST CHAR16 *PackageVersionName\r
406 )\r
407{\r
408 return EFI_UNSUPPORTED;\r
409}\r
410\r
e9179788
SZ
411/**\r
412 Sort FIT microcode entries based upon MicrocodeEntryPoint, from low to high.\r
413\r
414 @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
415\r
416**/\r
417VOID\r
418SortFitMicrocodeInfo (\r
419 IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
420 )\r
421{\r
422 FIT_MICROCODE_INFO *FitMicrocodeEntry;\r
423 FIT_MICROCODE_INFO *NextFitMicrocodeEntry;\r
424 FIT_MICROCODE_INFO TempFitMicrocodeEntry;\r
425 FIT_MICROCODE_INFO *FitMicrocodeEntryEnd;\r
426\r
427 FitMicrocodeEntry = MicrocodeFmpPrivate->FitMicrocodeInfo;\r
428 NextFitMicrocodeEntry = FitMicrocodeEntry + 1;\r
429 FitMicrocodeEntryEnd = MicrocodeFmpPrivate->FitMicrocodeInfo + MicrocodeFmpPrivate->FitMicrocodeEntryCount;\r
430 while (FitMicrocodeEntry < FitMicrocodeEntryEnd) {\r
431 while (NextFitMicrocodeEntry < FitMicrocodeEntryEnd) {\r
432 if (FitMicrocodeEntry->MicrocodeEntryPoint > NextFitMicrocodeEntry->MicrocodeEntryPoint) {\r
433 CopyMem (&TempFitMicrocodeEntry, FitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));\r
434 CopyMem (FitMicrocodeEntry, NextFitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));\r
435 CopyMem (NextFitMicrocodeEntry, &TempFitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));\r
436 }\r
437\r
438 NextFitMicrocodeEntry = NextFitMicrocodeEntry + 1;\r
439 }\r
440\r
441 FitMicrocodeEntry = FitMicrocodeEntry + 1;\r
442 NextFitMicrocodeEntry = FitMicrocodeEntry + 1;\r
443 }\r
444}\r
445\r
446/**\r
447 Initialize FIT microcode information.\r
448\r
449 @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
450\r
451 @return EFI_SUCCESS FIT microcode information is initialized.\r
452 @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.\r
453 @return EFI_DEVICE_ERROR There is something wrong in FIT microcode entry.\r
454**/\r
455EFI_STATUS\r
456InitializeFitMicrocodeInfo (\r
457 IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
458 )\r
459{\r
460 UINT64 FitPointer;\r
461 FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;\r
462 UINT32 EntryNum;\r
463 UINT32 MicrocodeEntryNum;\r
464 UINT32 Index;\r
465 UINTN Address;\r
466 VOID *MicrocodePatchAddress;\r
467 UINTN MicrocodePatchRegionSize;\r
468 FIT_MICROCODE_INFO *FitMicrocodeInfo;\r
469 FIT_MICROCODE_INFO *FitMicrocodeInfoNext;\r
470 CPU_MICROCODE_HEADER *MicrocodeEntryPoint;\r
471 CPU_MICROCODE_HEADER *MicrocodeEntryPointNext;\r
472 UINTN FitMicrocodeIndex;\r
473 MICROCODE_INFO *MicrocodeInfo;\r
474 UINTN MicrocodeIndex;\r
475\r
476 if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {\r
477 FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);\r
478 MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;\r
479 MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;\r
480 }\r
481\r
482 FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;\r
483 if ((FitPointer == 0) ||\r
484 (FitPointer == 0xFFFFFFFFFFFFFFFF) ||\r
485 (FitPointer == 0xEEEEEEEEEEEEEEEE)) {\r
486 //\r
487 // No FIT table.\r
488 //\r
489 return EFI_SUCCESS;\r
490 }\r
491 FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;\r
492 if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||\r
493 (FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {\r
494 //\r
495 // Invalid FIT table, treat it as no FIT table.\r
496 //\r
497 return EFI_SUCCESS;\r
498 }\r
499\r
500 EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;\r
501\r
502 //\r
503 // Calculate microcode entry number.\r
504 //\r
505 MicrocodeEntryNum = 0;\r
506 for (Index = 0; Index < EntryNum; Index++) {\r
507 if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {\r
508 MicrocodeEntryNum++;\r
509 }\r
510 }\r
511 if (MicrocodeEntryNum == 0) {\r
512 //\r
513 // No FIT microcode entry.\r
514 //\r
515 return EFI_SUCCESS;\r
516 }\r
517\r
518 //\r
519 // Allocate buffer.\r
520 //\r
521 MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));\r
522 if (MicrocodeFmpPrivate->FitMicrocodeInfo == NULL) {\r
523 return EFI_OUT_OF_RESOURCES;\r
524 }\r
525\r
526 MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;\r
527\r
528 MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;\r
529 MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;\r
530\r
531 //\r
532 // Collect microcode entry info.\r
533 //\r
534 MicrocodeEntryNum = 0;\r
535 for (Index = 0; Index < EntryNum; Index++) {\r
536 if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {\r
537 Address = (UINTN) FitEntry[Index].Address;\r
538 if ((Address < (UINTN) MicrocodePatchAddress) ||\r
539 (Address >= ((UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize))) {\r
540 DEBUG ((\r
541 DEBUG_ERROR,\r
542 "InitializeFitMicrocodeInfo - Address (0x%x) is not in Microcode Region\n",\r
543 Address\r
544 ));\r
545 goto ErrorExit;\r
546 }\r
547 FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[MicrocodeEntryNum];\r
548 FitMicrocodeInfo->MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) Address;\r
549 if ((*(UINT32 *) Address) == 0xFFFFFFFF) {\r
550 //\r
551 // It is the empty slot as long as the first dword is 0xFFFF_FFFF.\r
552 //\r
553 FitMicrocodeInfo->Empty = TRUE;\r
554 } else {\r
555 FitMicrocodeInfo->Empty = FALSE;\r
556 }\r
557 MicrocodeEntryNum++;\r
558 }\r
559 }\r
560\r
561 //\r
562 // Every microcode should have a FIT microcode entry.\r
563 //\r
564 for (MicrocodeIndex = 0; MicrocodeIndex < MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {\r
565 MicrocodeInfo = &MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex];\r
566 for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount; FitMicrocodeIndex++) {\r
567 FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];\r
568 if (MicrocodeInfo->MicrocodeEntryPoint == FitMicrocodeInfo->MicrocodeEntryPoint) {\r
569 FitMicrocodeInfo->TotalSize = MicrocodeInfo->TotalSize;\r
570 FitMicrocodeInfo->InUse = MicrocodeInfo->InUse;\r
571 break;\r
572 }\r
573 }\r
574 if (FitMicrocodeIndex >= MicrocodeFmpPrivate->FitMicrocodeEntryCount) {\r
575 DEBUG ((\r
576 DEBUG_ERROR,\r
577 "InitializeFitMicrocodeInfo - There is no FIT microcode entry for Microcode (0x%x)\n",\r
578 MicrocodeInfo->MicrocodeEntryPoint\r
579 ));\r
580 goto ErrorExit;\r
581 }\r
582 }\r
583\r
584 SortFitMicrocodeInfo (MicrocodeFmpPrivate);\r
585\r
586 //\r
587 // Check overlap.\r
588 //\r
589 for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount - 1; FitMicrocodeIndex++) {\r
590 FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];\r
591 MicrocodeEntryPoint = FitMicrocodeInfo->MicrocodeEntryPoint;\r
592 FitMicrocodeInfoNext = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex + 1];\r
593 MicrocodeEntryPointNext = FitMicrocodeInfoNext->MicrocodeEntryPoint;\r
594 if ((MicrocodeEntryPoint >= MicrocodeEntryPointNext) ||\r
595 ((FitMicrocodeInfo->TotalSize != 0) &&\r
596 ((UINTN) MicrocodeEntryPoint + FitMicrocodeInfo->TotalSize) >\r
597 (UINTN) MicrocodeEntryPointNext)) {\r
598 DEBUG ((\r
599 DEBUG_ERROR,\r
600 "InitializeFitMicrocodeInfo - There is overlap between FIT microcode entries (0x%x 0x%x)\n",\r
601 MicrocodeEntryPoint,\r
602 MicrocodeEntryPointNext\r
603 ));\r
604 goto ErrorExit;\r
605 }\r
606 }\r
607\r
608 return EFI_SUCCESS;\r
609\r
610ErrorExit:\r
611 FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);\r
612 MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;\r
613 MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;\r
614 return EFI_DEVICE_ERROR;\r
615}\r
616\r
31d060d9
JY
617/**\r
618 Initialize Processor Microcode Index.\r
619\r
620 @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
621**/\r
622VOID\r
623InitializedProcessorMicrocodeIndex (\r
624 IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
625 )\r
626{\r
627 UINTN CpuIndex;\r
628 UINTN MicrocodeIndex;\r
629 UINTN TargetCpuIndex;\r
630 UINT32 AttemptStatus;\r
631 EFI_STATUS Status;\r
632\r
633 for (CpuIndex = 0; CpuIndex < MicrocodeFmpPrivate->ProcessorCount; CpuIndex++) {\r
634 if (MicrocodeFmpPrivate->ProcessorInfo[CpuIndex].MicrocodeIndex != (UINTN)-1) {\r
635 continue;\r
636 }\r
637 for (MicrocodeIndex = 0; MicrocodeIndex < MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {\r
638 if (!MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].InUse) {\r
639 continue;\r
640 }\r
641 TargetCpuIndex = CpuIndex;\r
642 Status = VerifyMicrocode(\r
643 MicrocodeFmpPrivate,\r
644 MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].MicrocodeEntryPoint,\r
645 MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].TotalSize,\r
646 FALSE,\r
647 &AttemptStatus,\r
648 NULL,\r
649 &TargetCpuIndex\r
650 );\r
651 if (!EFI_ERROR(Status)) {\r
652 MicrocodeFmpPrivate->ProcessorInfo[CpuIndex].MicrocodeIndex = MicrocodeIndex;\r
653 }\r
654 }\r
655 }\r
656}\r
657\r
88266859
JY
658/**\r
659 Initialize Microcode Descriptor.\r
660\r
661 @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
662\r
e9179788
SZ
663 @return EFI_SUCCESS Microcode Descriptor is initialized.\r
664 @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.\r
88266859
JY
665**/\r
666EFI_STATUS\r
667InitializeMicrocodeDescriptor (\r
668 IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
669 )\r
670{\r
e9179788
SZ
671 EFI_STATUS Status;\r
672 UINT8 CurrentMicrocodeCount;\r
88266859 673\r
2ed65824 674 CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, 0, NULL, NULL);\r
88266859
JY
675\r
676 if (CurrentMicrocodeCount > MicrocodeFmpPrivate->DescriptorCount) {\r
677 if (MicrocodeFmpPrivate->ImageDescriptor != NULL) {\r
678 FreePool(MicrocodeFmpPrivate->ImageDescriptor);\r
679 MicrocodeFmpPrivate->ImageDescriptor = NULL;\r
680 }\r
2ed65824
JY
681 if (MicrocodeFmpPrivate->MicrocodeInfo != NULL) {\r
682 FreePool(MicrocodeFmpPrivate->MicrocodeInfo);\r
683 MicrocodeFmpPrivate->MicrocodeInfo = NULL;\r
684 }\r
88266859
JY
685 } else {\r
686 ZeroMem(MicrocodeFmpPrivate->ImageDescriptor, MicrocodeFmpPrivate->DescriptorCount * sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR));\r
2ed65824 687 ZeroMem(MicrocodeFmpPrivate->MicrocodeInfo, MicrocodeFmpPrivate->DescriptorCount * sizeof(MICROCODE_INFO));\r
88266859
JY
688 }\r
689\r
690 MicrocodeFmpPrivate->DescriptorCount = CurrentMicrocodeCount;\r
691\r
692 if (MicrocodeFmpPrivate->ImageDescriptor == NULL) {\r
693 MicrocodeFmpPrivate->ImageDescriptor = AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR));\r
694 if (MicrocodeFmpPrivate->ImageDescriptor == NULL) {\r
695 return EFI_OUT_OF_RESOURCES;\r
696 }\r
697 }\r
2ed65824
JY
698 if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {\r
699 MicrocodeFmpPrivate->MicrocodeInfo = AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * sizeof(MICROCODE_INFO));\r
700 if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {\r
e9179788 701 FreePool (MicrocodeFmpPrivate->ImageDescriptor);\r
2ed65824
JY
702 return EFI_OUT_OF_RESOURCES;\r
703 }\r
704 }\r
88266859 705\r
2ed65824 706 CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, MicrocodeFmpPrivate->DescriptorCount, MicrocodeFmpPrivate->ImageDescriptor, MicrocodeFmpPrivate->MicrocodeInfo);\r
88266859
JY
707 ASSERT(CurrentMicrocodeCount == MicrocodeFmpPrivate->DescriptorCount);\r
708\r
31d060d9
JY
709 InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);\r
710\r
e9179788
SZ
711 Status = InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);\r
712 if (EFI_ERROR(Status)) {\r
713 FreePool (MicrocodeFmpPrivate->ImageDescriptor);\r
714 FreePool (MicrocodeFmpPrivate->MicrocodeInfo);\r
715 DEBUG((DEBUG_ERROR, "InitializeFitMicrocodeInfo - %r\n", Status));\r
716 return Status;\r
717 }\r
718\r
31d060d9
JY
719 return EFI_SUCCESS;\r
720}\r
721\r
722/**\r
723 Initialize MicrocodeFmpDriver multiprocessor information.\r
724\r
725 @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
726\r
e9179788
SZ
727 @return EFI_SUCCESS Processor information is initialized.\r
728 @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.\r
31d060d9
JY
729**/\r
730EFI_STATUS\r
731InitializeProcessorInfo (\r
732 IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
733 )\r
734{\r
735 EFI_STATUS Status;\r
736 EFI_MP_SERVICES_PROTOCOL *MpService;\r
737 UINTN NumberOfProcessors;\r
738 UINTN NumberOfEnabledProcessors;\r
739 UINTN Index;\r
740 UINTN BspIndex;\r
741\r
742 Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpService);\r
743 ASSERT_EFI_ERROR(Status);\r
744\r
745 MicrocodeFmpPrivate->MpService = MpService;\r
746 MicrocodeFmpPrivate->ProcessorCount = 0;\r
747 MicrocodeFmpPrivate->ProcessorInfo = NULL;\r
748\r
749 Status = MpService->GetNumberOfProcessors (MpService, &NumberOfProcessors, &NumberOfEnabledProcessors);\r
750 ASSERT_EFI_ERROR(Status);\r
751 MicrocodeFmpPrivate->ProcessorCount = NumberOfProcessors;\r
752\r
753 Status = MpService->WhoAmI (MpService, &BspIndex);\r
754 ASSERT_EFI_ERROR(Status);\r
755 MicrocodeFmpPrivate->BspIndex = BspIndex;\r
756\r
757 MicrocodeFmpPrivate->ProcessorInfo = AllocateZeroPool (sizeof(PROCESSOR_INFO) * MicrocodeFmpPrivate->ProcessorCount);\r
758 if (MicrocodeFmpPrivate->ProcessorInfo == NULL) {\r
759 return EFI_OUT_OF_RESOURCES;\r
760 }\r
761\r
762 for (Index = 0; Index < NumberOfProcessors; Index++) {\r
763 MicrocodeFmpPrivate->ProcessorInfo[Index].CpuIndex = Index;\r
764 MicrocodeFmpPrivate->ProcessorInfo[Index].MicrocodeIndex = (UINTN)-1;\r
765 if (Index == BspIndex) {\r
766 CollectProcessorInfo (&MicrocodeFmpPrivate->ProcessorInfo[Index]);\r
767 } else {\r
768 Status = MpService->StartupThisAP (\r
769 MpService,\r
770 CollectProcessorInfo,\r
771 Index,\r
772 NULL,\r
773 0,\r
774 &MicrocodeFmpPrivate->ProcessorInfo[Index],\r
775 NULL\r
776 );\r
777 ASSERT_EFI_ERROR(Status);\r
778 }\r
779 }\r
780\r
88266859
JY
781 return EFI_SUCCESS;\r
782}\r
783\r
31d060d9
JY
784/**\r
785 Dump private information.\r
786\r
787 @param[in] MicrocodeFmpPrivate private data structure.\r
788**/\r
789VOID\r
790DumpPrivateInfo (\r
791 IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
792 )\r
793{\r
794 UINTN Index;\r
795 PROCESSOR_INFO *ProcessorInfo;\r
796 MICROCODE_INFO *MicrocodeInfo;\r
797 EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;\r
e9179788 798 FIT_MICROCODE_INFO *FitMicrocodeInfo;\r
31d060d9
JY
799\r
800 DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));\r
801 DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->ProcessorCount));\r
802 DEBUG ((DEBUG_INFO, " BspIndex - 0x%x\n", MicrocodeFmpPrivate->BspIndex));\r
803\r
804 ProcessorInfo = MicrocodeFmpPrivate->ProcessorInfo;\r
805 for (Index = 0; Index < MicrocodeFmpPrivate->ProcessorCount; Index++) {\r
806 DEBUG ((\r
807 DEBUG_INFO,\r
808 " ProcessorInfo[0x%x] - 0x%08x, 0x%02x, 0x%08x, (0x%x)\n",\r
809 ProcessorInfo[Index].CpuIndex,\r
810 ProcessorInfo[Index].ProcessorSignature,\r
811 ProcessorInfo[Index].PlatformId,\r
812 ProcessorInfo[Index].MicrocodeRevision,\r
813 ProcessorInfo[Index].MicrocodeIndex\r
814 ));\r
815 }\r
816\r
817 DEBUG ((DEBUG_INFO, "MicrocodeInfo:\n"));\r
818 MicrocodeInfo = MicrocodeFmpPrivate->MicrocodeInfo;\r
819 DEBUG ((DEBUG_INFO, " MicrocodeRegion - 0x%x - 0x%x\n", MicrocodeFmpPrivate->MicrocodePatchAddress, MicrocodeFmpPrivate->MicrocodePatchRegionSize));\r
820 DEBUG ((DEBUG_INFO, " MicrocodeCount - 0x%x\n", MicrocodeFmpPrivate->DescriptorCount));\r
821 for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {\r
822 DEBUG ((\r
823 DEBUG_INFO,\r
824 " MicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x)\n",\r
825 Index,\r
826 MicrocodeInfo[Index].MicrocodeEntryPoint,\r
827 MicrocodeInfo[Index].TotalSize,\r
828 MicrocodeInfo[Index].InUse\r
829 ));\r
830 }\r
831\r
832 ImageDescriptor = MicrocodeFmpPrivate->ImageDescriptor;\r
833 DEBUG ((DEBUG_VERBOSE, "ImageDescriptor:\n"));\r
834 for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {\r
835 DEBUG((DEBUG_VERBOSE, " ImageDescriptor (%d)\n", Index));\r
836 DEBUG((DEBUG_VERBOSE, " ImageIndex - 0x%x\n", ImageDescriptor[Index].ImageIndex));\r
837 DEBUG((DEBUG_VERBOSE, " ImageTypeId - %g\n", &ImageDescriptor[Index].ImageTypeId));\r
838 DEBUG((DEBUG_VERBOSE, " ImageId - 0x%lx\n", ImageDescriptor[Index].ImageId));\r
839 DEBUG((DEBUG_VERBOSE, " ImageIdName - %s\n", ImageDescriptor[Index].ImageIdName));\r
840 DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", ImageDescriptor[Index].Version));\r
841 DEBUG((DEBUG_VERBOSE, " VersionName - %s\n", ImageDescriptor[Index].VersionName));\r
842 DEBUG((DEBUG_VERBOSE, " Size - 0x%x\n", ImageDescriptor[Index].Size));\r
843 DEBUG((DEBUG_VERBOSE, " AttributesSupported - 0x%lx\n", ImageDescriptor[Index].AttributesSupported));\r
844 DEBUG((DEBUG_VERBOSE, " AttributesSetting - 0x%lx\n", ImageDescriptor[Index].AttributesSetting));\r
845 DEBUG((DEBUG_VERBOSE, " Compatibilities - 0x%lx\n", ImageDescriptor[Index].Compatibilities));\r
846 DEBUG((DEBUG_VERBOSE, " LowestSupportedImageVersion - 0x%x\n", ImageDescriptor[Index].LowestSupportedImageVersion));\r
847 DEBUG((DEBUG_VERBOSE, " LastAttemptVersion - 0x%x\n", ImageDescriptor[Index].LastAttemptVersion));\r
848 DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", ImageDescriptor[Index].LastAttemptStatus));\r
849 DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", ImageDescriptor[Index].HardwareInstance));\r
850 }\r
e9179788
SZ
851\r
852 if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {\r
853 DEBUG ((DEBUG_INFO, "FitMicrocodeInfo:\n"));\r
854 FitMicrocodeInfo = MicrocodeFmpPrivate->FitMicrocodeInfo;\r
855 DEBUG ((DEBUG_INFO, " FitMicrocodeEntryCount - 0x%x\n", MicrocodeFmpPrivate->FitMicrocodeEntryCount));\r
856 for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {\r
857 DEBUG ((\r
858 DEBUG_INFO,\r
859 " FitMicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x, 0x%x)\n",\r
860 Index,\r
861 FitMicrocodeInfo[Index].MicrocodeEntryPoint,\r
862 FitMicrocodeInfo[Index].TotalSize,\r
863 FitMicrocodeInfo[Index].InUse,\r
864 FitMicrocodeInfo[Index].Empty\r
865 ));\r
866 }\r
867 }\r
31d060d9
JY
868}\r
869\r
88266859
JY
870/**\r
871 Initialize MicrocodeFmpDriver private data structure.\r
872\r
873 @param[in] MicrocodeFmpPrivate private data structure to be initialized.\r
874\r
875 @return EFI_SUCCESS private data is initialized.\r
876**/\r
877EFI_STATUS\r
878InitializePrivateData (\r
879 IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate\r
880 )\r
881{\r
882 EFI_STATUS Status;\r
883 EFI_STATUS VarStatus;\r
884 UINTN VarSize;\r
2ed65824 885 BOOLEAN Result;\r
88266859
JY
886\r
887 MicrocodeFmpPrivate->Signature = MICROCODE_FMP_PRIVATE_DATA_SIGNATURE;\r
888 MicrocodeFmpPrivate->Handle = NULL;\r
889 CopyMem(&MicrocodeFmpPrivate->Fmp, &mFirmwareManagementProtocol, sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL));\r
890\r
891 MicrocodeFmpPrivate->PackageVersion = 0x1;\r
892 MicrocodeFmpPrivate->PackageVersionName = L"Microcode";\r
893\r
894 MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion = 0x0;\r
895 MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus = 0x0;\r
896 VarSize = sizeof(MicrocodeFmpPrivate->LastAttempt);\r
897 VarStatus = gRT->GetVariable(\r
898 MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,\r
899 &gEfiCallerIdGuid,\r
900 NULL,\r
901 &VarSize,\r
902 &MicrocodeFmpPrivate->LastAttempt\r
903 );\r
e9179788
SZ
904 DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus));\r
905 DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));\r
88266859 906\r
2ed65824
JY
907 Result = GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, &MicrocodeFmpPrivate->MicrocodePatchRegionSize);\r
908 if (!Result) {\r
909 DEBUG((DEBUG_ERROR, "Fail to get Microcode Region\n"));\r
910 return EFI_NOT_FOUND;\r
911 }\r
912\r
31d060d9
JY
913 Status = InitializeProcessorInfo (MicrocodeFmpPrivate);\r
914 if (EFI_ERROR(Status)) {\r
915 DEBUG((DEBUG_ERROR, "InitializeProcessorInfo - %r\n", Status));\r
916 return Status;\r
917 }\r
918\r
88266859 919 Status = InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);\r
31d060d9 920 if (EFI_ERROR(Status)) {\r
e9179788 921 FreePool (MicrocodeFmpPrivate->ProcessorInfo);\r
31d060d9
JY
922 DEBUG((DEBUG_ERROR, "InitializeMicrocodeDescriptor - %r\n", Status));\r
923 return Status;\r
924 }\r
925\r
926 DumpPrivateInfo (MicrocodeFmpPrivate);\r
88266859
JY
927\r
928 return Status;\r
929}\r
930\r
931/**\r
932 Microcode FMP module entrypoint\r
933\r
934 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
935 @param[in] SystemTable A pointer to the EFI System Table.\r
936\r
937 @return EFI_SUCCESS Microcode FMP module is initialized.\r
938**/\r
939EFI_STATUS\r
940EFIAPI\r
941MicrocodeFmpMain (\r
942 IN EFI_HANDLE ImageHandle,\r
943 IN EFI_SYSTEM_TABLE *SystemTable\r
944 )\r
945{\r
946 EFI_STATUS Status;\r
947\r
948 //\r
949 // Initialize MicrocodeFmpPrivateData\r
950 //\r
951 mMicrocodeFmpPrivate = AllocateZeroPool (sizeof(MICROCODE_FMP_PRIVATE_DATA));\r
952 if (mMicrocodeFmpPrivate == NULL) {\r
953 return EFI_OUT_OF_RESOURCES;\r
954 }\r
955\r
956 Status = InitializePrivateData(mMicrocodeFmpPrivate);\r
957 if (EFI_ERROR(Status)) {\r
958 FreePool(mMicrocodeFmpPrivate);\r
959 mMicrocodeFmpPrivate = NULL;\r
960 return Status;\r
961 }\r
962\r
963 //\r
964 // Install FMP protocol.\r
965 //\r
966 Status = gBS->InstallProtocolInterface (\r
967 &mMicrocodeFmpPrivate->Handle,\r
968 &gEfiFirmwareManagementProtocolGuid,\r
969 EFI_NATIVE_INTERFACE,\r
970 &mMicrocodeFmpPrivate->Fmp\r
971 );\r
972 if (EFI_ERROR (Status)) {\r
973 FreePool(mMicrocodeFmpPrivate);\r
974 mMicrocodeFmpPrivate = NULL;\r
975 return Status;\r
976 }\r
977\r
978 return Status;\r
979}\r