2 Produce FMP instance for Microcode.
4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "MicrocodeUpdate.h"
12 // MicrocodeFmp driver private data
14 MICROCODE_FMP_PRIVATE_DATA
*mMicrocodeFmpPrivate
= NULL
;
16 EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol
= {
26 Initialize Microcode Descriptor.
28 @param[in] MicrocodeFmpPrivate private data structure to be initialized.
30 @return EFI_SUCCESS Microcode Descriptor is initialized.
33 InitializeMicrocodeDescriptor (
34 IN MICROCODE_FMP_PRIVATE_DATA
*MicrocodeFmpPrivate
38 Returns information about the current firmware image(s) of the device.
40 This function allows a copy of the current firmware image to be created and saved.
41 The saved copy could later been used, for example, in firmware image recovery or rollback.
43 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
44 @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.
45 On input, this is the size of the buffer allocated by the caller.
46 On output, it is the size of the buffer returned by the firmware
47 if the buffer was large enough, or the size of the buffer needed
48 to contain the image(s) information if the buffer was too small.
49 @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)
50 information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
51 @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number
52 associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
53 @param[out] DescriptorCount A pointer to the location in which firmware returns the number of
54 descriptors or firmware images within this device.
55 @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,
56 of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
57 @param[out] PackageVersion A version number that represents all the firmware images in the device.
58 The format is vendor specific and new version must have a greater value
59 than the old version. If PackageVersion is not supported, the value is
60 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
61 is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
62 that package version update is in progress.
63 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the
64 package version name. The buffer is allocated by this function with
65 AllocatePool(), and it is the caller's responsibility to free it with a call
68 @retval EFI_SUCCESS The device was successfully updated with the new image.
69 @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size
70 needed to hold the image(s) information is returned in ImageInfoSize.
71 @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.
72 @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.
78 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
79 IN OUT UINTN
*ImageInfoSize
,
80 IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageInfo
,
81 OUT UINT32
*DescriptorVersion
,
82 OUT UINT8
*DescriptorCount
,
83 OUT UINTN
*DescriptorSize
,
84 OUT UINT32
*PackageVersion
,
85 OUT CHAR16
**PackageVersionName
88 MICROCODE_FMP_PRIVATE_DATA
*MicrocodeFmpPrivate
;
91 MicrocodeFmpPrivate
= MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This
);
93 if(ImageInfoSize
== NULL
) {
94 return EFI_INVALID_PARAMETER
;
97 if (*ImageInfoSize
< sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR
) * MicrocodeFmpPrivate
->DescriptorCount
) {
98 *ImageInfoSize
= sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR
) * MicrocodeFmpPrivate
->DescriptorCount
;
99 return EFI_BUFFER_TOO_SMALL
;
102 if (ImageInfo
== NULL
||
103 DescriptorVersion
== NULL
||
104 DescriptorCount
== NULL
||
105 DescriptorSize
== NULL
||
106 PackageVersion
== NULL
||
107 PackageVersionName
== NULL
) {
108 return EFI_INVALID_PARAMETER
;
111 *ImageInfoSize
= sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR
) * MicrocodeFmpPrivate
->DescriptorCount
;
112 *DescriptorSize
= sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR
);
113 *DescriptorCount
= MicrocodeFmpPrivate
->DescriptorCount
;
114 *DescriptorVersion
= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION
;
117 // supports 1 ImageInfo descriptor
119 CopyMem(&ImageInfo
[0], MicrocodeFmpPrivate
->ImageDescriptor
, sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR
) * MicrocodeFmpPrivate
->DescriptorCount
);
120 for (Index
= 0; Index
< MicrocodeFmpPrivate
->DescriptorCount
; Index
++) {
121 if ((ImageInfo
[Index
].AttributesSetting
& IMAGE_ATTRIBUTE_IN_USE
) != 0) {
122 ImageInfo
[Index
].LastAttemptVersion
= MicrocodeFmpPrivate
->LastAttempt
.LastAttemptVersion
;
123 ImageInfo
[Index
].LastAttemptStatus
= MicrocodeFmpPrivate
->LastAttempt
.LastAttemptStatus
;
130 *PackageVersion
= MicrocodeFmpPrivate
->PackageVersion
;
131 if (MicrocodeFmpPrivate
->PackageVersionName
!= NULL
) {
132 *PackageVersionName
= AllocateCopyPool(StrSize(MicrocodeFmpPrivate
->PackageVersionName
), MicrocodeFmpPrivate
->PackageVersionName
);
139 Retrieves a copy of the current firmware image of the device.
141 This function allows a copy of the current firmware image to be created and saved.
142 The saved copy could later been used, for example, in firmware image recovery or rollback.
144 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
145 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
146 The number is between 1 and DescriptorCount.
147 @param[in,out] Image Points to the buffer where the current image is copied to.
148 @param[in,out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.
149 On return, points to the length of the image, in bytes.
151 @retval EFI_SUCCESS The device was successfully updated with the new image.
152 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
153 image. The current buffer size needed to hold the image is returned
155 @retval EFI_INVALID_PARAMETER The Image was NULL.
156 @retval EFI_NOT_FOUND The current image is not copied to the buffer.
157 @retval EFI_UNSUPPORTED The operation is not supported.
158 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
164 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
167 IN OUT UINTN
*ImageSize
170 MICROCODE_FMP_PRIVATE_DATA
*MicrocodeFmpPrivate
;
171 MICROCODE_INFO
*MicrocodeInfo
;
173 if (Image
== NULL
|| ImageSize
== NULL
) {
174 return EFI_INVALID_PARAMETER
;
177 MicrocodeFmpPrivate
= MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This
);
179 if (ImageIndex
== 0 || ImageIndex
> MicrocodeFmpPrivate
->DescriptorCount
|| ImageSize
== NULL
|| Image
== NULL
) {
180 return EFI_INVALID_PARAMETER
;
183 MicrocodeInfo
= &MicrocodeFmpPrivate
->MicrocodeInfo
[ImageIndex
- 1];
185 if (*ImageSize
< MicrocodeInfo
->TotalSize
) {
186 *ImageSize
= MicrocodeInfo
->TotalSize
;
187 return EFI_BUFFER_TOO_SMALL
;
190 *ImageSize
= MicrocodeInfo
->TotalSize
;
191 CopyMem (Image
, MicrocodeInfo
->MicrocodeEntryPoint
, MicrocodeInfo
->TotalSize
);
196 Updates the firmware image of the device.
198 This function updates the hardware with the new firmware image.
199 This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
200 If the firmware image is updatable, the function should perform the following minimal validations
201 before proceeding to do the firmware image update.
202 - Validate the image authentication if image has attribute
203 IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
204 EFI_SECURITY_VIOLATION if the validation fails.
205 - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
206 the image is unsupported. The function can optionally provide more detailed information on
207 why the image is not a supported image.
208 - Validate the data from VendorCode if not null. Image validation must be performed before
209 VendorCode data validation. VendorCode data is ignored or considered invalid if image
210 validation failed. The function returns EFI_ABORTED if the data is invalid.
212 VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
213 the caller did not specify the policy or use the default policy. As an example, vendor can implement
214 a policy to allow an option to force a firmware image update when the abort reason is due to the new
215 firmware image version is older than the current firmware image version or bad image checksum.
216 Sensitive operations such as those wiping the entire firmware image and render the device to be
217 non-functional should be encoded in the image itself rather than passed with the VendorCode.
218 AbortReason enables vendor to have the option to provide a more detailed description of the abort
219 reason to the caller.
221 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
222 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
223 The number is between 1 and DescriptorCount.
224 @param[in] Image Points to the new image.
225 @param[in] ImageSize Size of the new image in bytes.
226 @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
227 Null indicates the caller did not specify the policy or use the default policy.
228 @param[in] Progress A function used by the driver to report the progress of the firmware update.
229 @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
230 details for the aborted operation. The buffer is allocated by this function
231 with AllocatePool(), and it is the caller's responsibility to free it with a
234 @retval EFI_SUCCESS The device was successfully updated with the new image.
235 @retval EFI_ABORTED The operation is aborted.
236 @retval EFI_INVALID_PARAMETER The Image was NULL.
237 @retval EFI_UNSUPPORTED The operation is not supported.
238 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
244 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
246 IN CONST VOID
*Image
,
248 IN CONST VOID
*VendorCode
,
249 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress
,
250 OUT CHAR16
**AbortReason
254 EFI_STATUS VarStatus
;
255 MICROCODE_FMP_PRIVATE_DATA
*MicrocodeFmpPrivate
;
257 if (Image
== NULL
|| AbortReason
== NULL
) {
258 return EFI_INVALID_PARAMETER
;
261 MicrocodeFmpPrivate
= MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This
);
264 if (ImageIndex
== 0 || ImageIndex
> MicrocodeFmpPrivate
->DescriptorCount
|| Image
== NULL
) {
265 return EFI_INVALID_PARAMETER
;
268 Status
= MicrocodeWrite(MicrocodeFmpPrivate
, (VOID
*)Image
, ImageSize
, &MicrocodeFmpPrivate
->LastAttempt
.LastAttemptVersion
, &MicrocodeFmpPrivate
->LastAttempt
.LastAttemptStatus
, AbortReason
);
269 DEBUG((DEBUG_INFO
, "SetImage - LastAttempt Version - 0x%x, Status - 0x%x\n", MicrocodeFmpPrivate
->LastAttempt
.LastAttemptVersion
, MicrocodeFmpPrivate
->LastAttempt
.LastAttemptStatus
));
270 VarStatus
= gRT
->SetVariable(
271 MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME
,
273 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
274 sizeof(MicrocodeFmpPrivate
->LastAttempt
),
275 &MicrocodeFmpPrivate
->LastAttempt
277 DEBUG((DEBUG_INFO
, "SetLastAttempt - %r\n", VarStatus
));
279 if (!EFI_ERROR(Status
)) {
280 InitializeMicrocodeDescriptor(MicrocodeFmpPrivate
);
281 DumpPrivateInfo (MicrocodeFmpPrivate
);
288 Checks if the firmware image is valid for the device.
290 This function allows firmware update application to validate the firmware image without
291 invoking the SetImage() first.
293 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
294 @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
295 The number is between 1 and DescriptorCount.
296 @param[in] Image Points to the new image.
297 @param[in] ImageSize Size of the new image in bytes.
298 @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
299 if available, additional information if the image is invalid.
301 @retval EFI_SUCCESS The image was successfully checked.
302 @retval EFI_INVALID_PARAMETER The Image was NULL.
303 @retval EFI_UNSUPPORTED The operation is not supported.
304 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
310 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
312 IN CONST VOID
*Image
,
314 OUT UINT32
*ImageUpdatable
317 return EFI_UNSUPPORTED
;
321 Returns information about the firmware package.
323 This function returns package information.
325 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
326 @param[out] PackageVersion A version number that represents all the firmware images in the device.
327 The format is vendor specific and new version must have a greater value
328 than the old version. If PackageVersion is not supported, the value is
329 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
330 comparison is to be performed using PackageVersionName. A value of
331 0xFFFFFFFD indicates that package version update is in progress.
332 @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
333 the package version name. The buffer is allocated by this function with
334 AllocatePool(), and it is the caller's responsibility to free it with a
336 @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
337 package version name. A value of 0 indicates the device does not support
338 update of package version name. Length is the number of Unicode characters,
339 including the terminating null character.
340 @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
341 Definitions' for possible returned values of this parameter. A value of 1
342 indicates the attribute is supported and the current setting value is
343 indicated in AttributesSetting. A value of 0 indicates the attribute is not
344 supported and the current setting value in AttributesSetting is meaningless.
345 @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
346 values of this parameter
348 @retval EFI_SUCCESS The package information was successfully returned.
349 @retval EFI_UNSUPPORTED The operation is not supported.
355 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
356 OUT UINT32
*PackageVersion
,
357 OUT CHAR16
**PackageVersionName
,
358 OUT UINT32
*PackageVersionNameMaxLen
,
359 OUT UINT64
*AttributesSupported
,
360 OUT UINT64
*AttributesSetting
363 return EFI_UNSUPPORTED
;
367 Updates information about the firmware package.
369 This function updates package information.
370 This function returns EFI_UNSUPPORTED if the package information is not updatable.
371 VendorCode enables vendor to implement vendor-specific package information update policy.
372 Null if the caller did not specify this policy or use the default policy.
374 @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
375 @param[in] Image Points to the authentication image.
376 Null if authentication is not required.
377 @param[in] ImageSize Size of the authentication image in bytes.
378 0 if authentication is not required.
379 @param[in] VendorCode This enables vendor to implement vendor-specific firmware
381 Null indicates the caller did not specify this policy or use
383 @param[in] PackageVersion The new package version.
384 @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
385 the package version name.
386 The string length is equal to or less than the value returned in
387 PackageVersionNameMaxLen.
389 @retval EFI_SUCCESS The device was successfully updated with the new package
391 @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
392 returned in PackageVersionNameMaxLen.
393 @retval EFI_UNSUPPORTED The operation is not supported.
394 @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
400 IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*This
,
401 IN CONST VOID
*Image
,
403 IN CONST VOID
*VendorCode
,
404 IN UINT32 PackageVersion
,
405 IN CONST CHAR16
*PackageVersionName
408 return EFI_UNSUPPORTED
;
412 Sort FIT microcode entries based upon MicrocodeEntryPoint, from low to high.
414 @param[in] MicrocodeFmpPrivate private data structure to be initialized.
418 SortFitMicrocodeInfo (
419 IN MICROCODE_FMP_PRIVATE_DATA
*MicrocodeFmpPrivate
422 FIT_MICROCODE_INFO
*FitMicrocodeEntry
;
423 FIT_MICROCODE_INFO
*NextFitMicrocodeEntry
;
424 FIT_MICROCODE_INFO TempFitMicrocodeEntry
;
425 FIT_MICROCODE_INFO
*FitMicrocodeEntryEnd
;
427 FitMicrocodeEntry
= MicrocodeFmpPrivate
->FitMicrocodeInfo
;
428 NextFitMicrocodeEntry
= FitMicrocodeEntry
+ 1;
429 FitMicrocodeEntryEnd
= MicrocodeFmpPrivate
->FitMicrocodeInfo
+ MicrocodeFmpPrivate
->FitMicrocodeEntryCount
;
430 while (FitMicrocodeEntry
< FitMicrocodeEntryEnd
) {
431 while (NextFitMicrocodeEntry
< FitMicrocodeEntryEnd
) {
432 if (FitMicrocodeEntry
->MicrocodeEntryPoint
> NextFitMicrocodeEntry
->MicrocodeEntryPoint
) {
433 CopyMem (&TempFitMicrocodeEntry
, FitMicrocodeEntry
, sizeof (FIT_MICROCODE_INFO
));
434 CopyMem (FitMicrocodeEntry
, NextFitMicrocodeEntry
, sizeof (FIT_MICROCODE_INFO
));
435 CopyMem (NextFitMicrocodeEntry
, &TempFitMicrocodeEntry
, sizeof (FIT_MICROCODE_INFO
));
438 NextFitMicrocodeEntry
= NextFitMicrocodeEntry
+ 1;
441 FitMicrocodeEntry
= FitMicrocodeEntry
+ 1;
442 NextFitMicrocodeEntry
= FitMicrocodeEntry
+ 1;
447 Initialize FIT microcode information.
449 @param[in] MicrocodeFmpPrivate private data structure to be initialized.
451 @return EFI_SUCCESS FIT microcode information is initialized.
452 @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
453 @return EFI_DEVICE_ERROR There is something wrong in FIT microcode entry.
456 InitializeFitMicrocodeInfo (
457 IN MICROCODE_FMP_PRIVATE_DATA
*MicrocodeFmpPrivate
461 FIRMWARE_INTERFACE_TABLE_ENTRY
*FitEntry
;
463 UINT32 MicrocodeEntryNum
;
466 VOID
*MicrocodePatchAddress
;
467 UINTN MicrocodePatchRegionSize
;
468 FIT_MICROCODE_INFO
*FitMicrocodeInfo
;
469 FIT_MICROCODE_INFO
*FitMicrocodeInfoNext
;
470 CPU_MICROCODE_HEADER
*MicrocodeEntryPoint
;
471 CPU_MICROCODE_HEADER
*MicrocodeEntryPointNext
;
472 UINTN FitMicrocodeIndex
;
473 MICROCODE_INFO
*MicrocodeInfo
;
474 UINTN MicrocodeIndex
;
476 if (MicrocodeFmpPrivate
->FitMicrocodeInfo
!= NULL
) {
477 FreePool (MicrocodeFmpPrivate
->FitMicrocodeInfo
);
478 MicrocodeFmpPrivate
->FitMicrocodeInfo
= NULL
;
479 MicrocodeFmpPrivate
->FitMicrocodeEntryCount
= 0;
482 FitPointer
= *(UINT64
*) (UINTN
) FIT_POINTER_ADDRESS
;
483 if ((FitPointer
== 0) ||
484 (FitPointer
== 0xFFFFFFFFFFFFFFFF) ||
485 (FitPointer
== 0xEEEEEEEEEEEEEEEE)) {
491 FitEntry
= (FIRMWARE_INTERFACE_TABLE_ENTRY
*) (UINTN
) FitPointer
;
492 if ((FitEntry
[0].Type
!= FIT_TYPE_00_HEADER
) ||
493 (FitEntry
[0].Address
!= FIT_TYPE_00_SIGNATURE
)) {
495 // Invalid FIT table, treat it as no FIT table.
500 EntryNum
= *(UINT32
*)(&FitEntry
[0].Size
[0]) & 0xFFFFFF;
503 // Calculate microcode entry number.
505 MicrocodeEntryNum
= 0;
506 for (Index
= 0; Index
< EntryNum
; Index
++) {
507 if (FitEntry
[Index
].Type
== FIT_TYPE_01_MICROCODE
) {
511 if (MicrocodeEntryNum
== 0) {
513 // No FIT microcode entry.
521 MicrocodeFmpPrivate
->FitMicrocodeInfo
= AllocateZeroPool (MicrocodeEntryNum
* sizeof (FIT_MICROCODE_INFO
));
522 if (MicrocodeFmpPrivate
->FitMicrocodeInfo
== NULL
) {
523 return EFI_OUT_OF_RESOURCES
;
526 MicrocodeFmpPrivate
->FitMicrocodeEntryCount
= MicrocodeEntryNum
;
528 MicrocodePatchAddress
= MicrocodeFmpPrivate
->MicrocodePatchAddress
;
529 MicrocodePatchRegionSize
= MicrocodeFmpPrivate
->MicrocodePatchRegionSize
;
532 // Collect microcode entry info.
534 MicrocodeEntryNum
= 0;
535 for (Index
= 0; Index
< EntryNum
; Index
++) {
536 if (FitEntry
[Index
].Type
== FIT_TYPE_01_MICROCODE
) {
537 Address
= (UINTN
) FitEntry
[Index
].Address
;
538 if ((Address
< (UINTN
) MicrocodePatchAddress
) ||
539 (Address
>= ((UINTN
) MicrocodePatchAddress
+ MicrocodePatchRegionSize
))) {
542 "InitializeFitMicrocodeInfo - Address (0x%x) is not in Microcode Region\n",
547 FitMicrocodeInfo
= &MicrocodeFmpPrivate
->FitMicrocodeInfo
[MicrocodeEntryNum
];
548 FitMicrocodeInfo
->MicrocodeEntryPoint
= (CPU_MICROCODE_HEADER
*) Address
;
549 if ((*(UINT32
*) Address
) == 0xFFFFFFFF) {
551 // It is the empty slot as long as the first dword is 0xFFFF_FFFF.
553 FitMicrocodeInfo
->Empty
= TRUE
;
555 FitMicrocodeInfo
->Empty
= FALSE
;
562 // Every microcode should have a FIT microcode entry.
564 for (MicrocodeIndex
= 0; MicrocodeIndex
< MicrocodeFmpPrivate
->DescriptorCount
; MicrocodeIndex
++) {
565 MicrocodeInfo
= &MicrocodeFmpPrivate
->MicrocodeInfo
[MicrocodeIndex
];
566 for (FitMicrocodeIndex
= 0; FitMicrocodeIndex
< MicrocodeFmpPrivate
->FitMicrocodeEntryCount
; FitMicrocodeIndex
++) {
567 FitMicrocodeInfo
= &MicrocodeFmpPrivate
->FitMicrocodeInfo
[FitMicrocodeIndex
];
568 if (MicrocodeInfo
->MicrocodeEntryPoint
== FitMicrocodeInfo
->MicrocodeEntryPoint
) {
569 FitMicrocodeInfo
->TotalSize
= MicrocodeInfo
->TotalSize
;
570 FitMicrocodeInfo
->InUse
= MicrocodeInfo
->InUse
;
574 if (FitMicrocodeIndex
>= MicrocodeFmpPrivate
->FitMicrocodeEntryCount
) {
577 "InitializeFitMicrocodeInfo - There is no FIT microcode entry for Microcode (0x%x)\n",
578 MicrocodeInfo
->MicrocodeEntryPoint
584 SortFitMicrocodeInfo (MicrocodeFmpPrivate
);
589 for (FitMicrocodeIndex
= 0; FitMicrocodeIndex
< MicrocodeFmpPrivate
->FitMicrocodeEntryCount
- 1; FitMicrocodeIndex
++) {
590 FitMicrocodeInfo
= &MicrocodeFmpPrivate
->FitMicrocodeInfo
[FitMicrocodeIndex
];
591 MicrocodeEntryPoint
= FitMicrocodeInfo
->MicrocodeEntryPoint
;
592 FitMicrocodeInfoNext
= &MicrocodeFmpPrivate
->FitMicrocodeInfo
[FitMicrocodeIndex
+ 1];
593 MicrocodeEntryPointNext
= FitMicrocodeInfoNext
->MicrocodeEntryPoint
;
594 if ((MicrocodeEntryPoint
>= MicrocodeEntryPointNext
) ||
595 ((FitMicrocodeInfo
->TotalSize
!= 0) &&
596 ((UINTN
) MicrocodeEntryPoint
+ FitMicrocodeInfo
->TotalSize
) >
597 (UINTN
) MicrocodeEntryPointNext
)) {
600 "InitializeFitMicrocodeInfo - There is overlap between FIT microcode entries (0x%x 0x%x)\n",
602 MicrocodeEntryPointNext
611 FreePool (MicrocodeFmpPrivate
->FitMicrocodeInfo
);
612 MicrocodeFmpPrivate
->FitMicrocodeInfo
= NULL
;
613 MicrocodeFmpPrivate
->FitMicrocodeEntryCount
= 0;
614 return EFI_DEVICE_ERROR
;
618 Initialize Processor Microcode Index.
620 @param[in] MicrocodeFmpPrivate private data structure to be initialized.
623 InitializedProcessorMicrocodeIndex (
624 IN MICROCODE_FMP_PRIVATE_DATA
*MicrocodeFmpPrivate
628 UINTN MicrocodeIndex
;
629 UINTN TargetCpuIndex
;
630 UINT32 AttemptStatus
;
633 for (CpuIndex
= 0; CpuIndex
< MicrocodeFmpPrivate
->ProcessorCount
; CpuIndex
++) {
634 if (MicrocodeFmpPrivate
->ProcessorInfo
[CpuIndex
].MicrocodeIndex
!= (UINTN
)-1) {
637 for (MicrocodeIndex
= 0; MicrocodeIndex
< MicrocodeFmpPrivate
->DescriptorCount
; MicrocodeIndex
++) {
638 if (!MicrocodeFmpPrivate
->MicrocodeInfo
[MicrocodeIndex
].InUse
) {
641 TargetCpuIndex
= CpuIndex
;
642 Status
= VerifyMicrocode(
644 MicrocodeFmpPrivate
->MicrocodeInfo
[MicrocodeIndex
].MicrocodeEntryPoint
,
645 MicrocodeFmpPrivate
->MicrocodeInfo
[MicrocodeIndex
].TotalSize
,
651 if (!EFI_ERROR(Status
)) {
652 MicrocodeFmpPrivate
->ProcessorInfo
[CpuIndex
].MicrocodeIndex
= MicrocodeIndex
;
659 Initialize Microcode Descriptor.
661 @param[in] MicrocodeFmpPrivate private data structure to be initialized.
663 @return EFI_SUCCESS Microcode Descriptor is initialized.
664 @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
667 InitializeMicrocodeDescriptor (
668 IN MICROCODE_FMP_PRIVATE_DATA
*MicrocodeFmpPrivate
672 UINT8 CurrentMicrocodeCount
;
674 CurrentMicrocodeCount
= (UINT8
)GetMicrocodeInfo (MicrocodeFmpPrivate
, 0, NULL
, NULL
);
676 if (CurrentMicrocodeCount
> MicrocodeFmpPrivate
->DescriptorCount
) {
677 if (MicrocodeFmpPrivate
->ImageDescriptor
!= NULL
) {
678 FreePool(MicrocodeFmpPrivate
->ImageDescriptor
);
679 MicrocodeFmpPrivate
->ImageDescriptor
= NULL
;
681 if (MicrocodeFmpPrivate
->MicrocodeInfo
!= NULL
) {
682 FreePool(MicrocodeFmpPrivate
->MicrocodeInfo
);
683 MicrocodeFmpPrivate
->MicrocodeInfo
= NULL
;
686 ZeroMem(MicrocodeFmpPrivate
->ImageDescriptor
, MicrocodeFmpPrivate
->DescriptorCount
* sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR
));
687 ZeroMem(MicrocodeFmpPrivate
->MicrocodeInfo
, MicrocodeFmpPrivate
->DescriptorCount
* sizeof(MICROCODE_INFO
));
690 MicrocodeFmpPrivate
->DescriptorCount
= CurrentMicrocodeCount
;
692 if (MicrocodeFmpPrivate
->ImageDescriptor
== NULL
) {
693 MicrocodeFmpPrivate
->ImageDescriptor
= AllocateZeroPool(MicrocodeFmpPrivate
->DescriptorCount
* sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR
));
694 if (MicrocodeFmpPrivate
->ImageDescriptor
== NULL
) {
695 return EFI_OUT_OF_RESOURCES
;
698 if (MicrocodeFmpPrivate
->MicrocodeInfo
== NULL
) {
699 MicrocodeFmpPrivate
->MicrocodeInfo
= AllocateZeroPool(MicrocodeFmpPrivate
->DescriptorCount
* sizeof(MICROCODE_INFO
));
700 if (MicrocodeFmpPrivate
->MicrocodeInfo
== NULL
) {
701 FreePool (MicrocodeFmpPrivate
->ImageDescriptor
);
702 return EFI_OUT_OF_RESOURCES
;
706 CurrentMicrocodeCount
= (UINT8
)GetMicrocodeInfo (MicrocodeFmpPrivate
, MicrocodeFmpPrivate
->DescriptorCount
, MicrocodeFmpPrivate
->ImageDescriptor
, MicrocodeFmpPrivate
->MicrocodeInfo
);
707 ASSERT(CurrentMicrocodeCount
== MicrocodeFmpPrivate
->DescriptorCount
);
709 InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate
);
711 Status
= InitializeFitMicrocodeInfo (MicrocodeFmpPrivate
);
712 if (EFI_ERROR(Status
)) {
713 FreePool (MicrocodeFmpPrivate
->ImageDescriptor
);
714 FreePool (MicrocodeFmpPrivate
->MicrocodeInfo
);
715 DEBUG((DEBUG_ERROR
, "InitializeFitMicrocodeInfo - %r\n", Status
));
723 Initialize MicrocodeFmpDriver multiprocessor information.
725 @param[in] MicrocodeFmpPrivate private data structure to be initialized.
727 @return EFI_SUCCESS Processor information is initialized.
728 @return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
731 InitializeProcessorInfo (
732 IN MICROCODE_FMP_PRIVATE_DATA
*MicrocodeFmpPrivate
736 EFI_MP_SERVICES_PROTOCOL
*MpService
;
737 UINTN NumberOfProcessors
;
738 UINTN NumberOfEnabledProcessors
;
742 Status
= gBS
->LocateProtocol (&gEfiMpServiceProtocolGuid
, NULL
, (VOID
**)&MpService
);
743 ASSERT_EFI_ERROR(Status
);
745 MicrocodeFmpPrivate
->MpService
= MpService
;
746 MicrocodeFmpPrivate
->ProcessorCount
= 0;
747 MicrocodeFmpPrivate
->ProcessorInfo
= NULL
;
749 Status
= MpService
->GetNumberOfProcessors (MpService
, &NumberOfProcessors
, &NumberOfEnabledProcessors
);
750 ASSERT_EFI_ERROR(Status
);
751 MicrocodeFmpPrivate
->ProcessorCount
= NumberOfProcessors
;
753 Status
= MpService
->WhoAmI (MpService
, &BspIndex
);
754 ASSERT_EFI_ERROR(Status
);
755 MicrocodeFmpPrivate
->BspIndex
= BspIndex
;
757 MicrocodeFmpPrivate
->ProcessorInfo
= AllocateZeroPool (sizeof(PROCESSOR_INFO
) * MicrocodeFmpPrivate
->ProcessorCount
);
758 if (MicrocodeFmpPrivate
->ProcessorInfo
== NULL
) {
759 return EFI_OUT_OF_RESOURCES
;
762 for (Index
= 0; Index
< NumberOfProcessors
; Index
++) {
763 MicrocodeFmpPrivate
->ProcessorInfo
[Index
].CpuIndex
= Index
;
764 MicrocodeFmpPrivate
->ProcessorInfo
[Index
].MicrocodeIndex
= (UINTN
)-1;
765 if (Index
== BspIndex
) {
766 CollectProcessorInfo (&MicrocodeFmpPrivate
->ProcessorInfo
[Index
]);
768 Status
= MpService
->StartupThisAP (
770 CollectProcessorInfo
,
774 &MicrocodeFmpPrivate
->ProcessorInfo
[Index
],
777 ASSERT_EFI_ERROR(Status
);
785 Dump private information.
787 @param[in] MicrocodeFmpPrivate private data structure.
791 IN MICROCODE_FMP_PRIVATE_DATA
*MicrocodeFmpPrivate
795 PROCESSOR_INFO
*ProcessorInfo
;
796 MICROCODE_INFO
*MicrocodeInfo
;
797 EFI_FIRMWARE_IMAGE_DESCRIPTOR
*ImageDescriptor
;
798 FIT_MICROCODE_INFO
*FitMicrocodeInfo
;
800 DEBUG ((DEBUG_INFO
, "ProcessorInfo:\n"));
801 DEBUG ((DEBUG_INFO
, " ProcessorCount - 0x%x\n", MicrocodeFmpPrivate
->ProcessorCount
));
802 DEBUG ((DEBUG_INFO
, " BspIndex - 0x%x\n", MicrocodeFmpPrivate
->BspIndex
));
804 ProcessorInfo
= MicrocodeFmpPrivate
->ProcessorInfo
;
805 for (Index
= 0; Index
< MicrocodeFmpPrivate
->ProcessorCount
; Index
++) {
808 " ProcessorInfo[0x%x] - 0x%08x, 0x%02x, 0x%08x, (0x%x)\n",
809 ProcessorInfo
[Index
].CpuIndex
,
810 ProcessorInfo
[Index
].ProcessorSignature
,
811 ProcessorInfo
[Index
].PlatformId
,
812 ProcessorInfo
[Index
].MicrocodeRevision
,
813 ProcessorInfo
[Index
].MicrocodeIndex
817 DEBUG ((DEBUG_INFO
, "MicrocodeInfo:\n"));
818 MicrocodeInfo
= MicrocodeFmpPrivate
->MicrocodeInfo
;
819 DEBUG ((DEBUG_INFO
, " MicrocodeRegion - 0x%x - 0x%x\n", MicrocodeFmpPrivate
->MicrocodePatchAddress
, MicrocodeFmpPrivate
->MicrocodePatchRegionSize
));
820 DEBUG ((DEBUG_INFO
, " MicrocodeCount - 0x%x\n", MicrocodeFmpPrivate
->DescriptorCount
));
821 for (Index
= 0; Index
< MicrocodeFmpPrivate
->DescriptorCount
; Index
++) {
824 " MicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x)\n",
826 MicrocodeInfo
[Index
].MicrocodeEntryPoint
,
827 MicrocodeInfo
[Index
].TotalSize
,
828 MicrocodeInfo
[Index
].InUse
832 ImageDescriptor
= MicrocodeFmpPrivate
->ImageDescriptor
;
833 DEBUG ((DEBUG_VERBOSE
, "ImageDescriptor:\n"));
834 for (Index
= 0; Index
< MicrocodeFmpPrivate
->DescriptorCount
; Index
++) {
835 DEBUG((DEBUG_VERBOSE
, " ImageDescriptor (%d)\n", Index
));
836 DEBUG((DEBUG_VERBOSE
, " ImageIndex - 0x%x\n", ImageDescriptor
[Index
].ImageIndex
));
837 DEBUG((DEBUG_VERBOSE
, " ImageTypeId - %g\n", &ImageDescriptor
[Index
].ImageTypeId
));
838 DEBUG((DEBUG_VERBOSE
, " ImageId - 0x%lx\n", ImageDescriptor
[Index
].ImageId
));
839 DEBUG((DEBUG_VERBOSE
, " ImageIdName - %s\n", ImageDescriptor
[Index
].ImageIdName
));
840 DEBUG((DEBUG_VERBOSE
, " Version - 0x%x\n", ImageDescriptor
[Index
].Version
));
841 DEBUG((DEBUG_VERBOSE
, " VersionName - %s\n", ImageDescriptor
[Index
].VersionName
));
842 DEBUG((DEBUG_VERBOSE
, " Size - 0x%x\n", ImageDescriptor
[Index
].Size
));
843 DEBUG((DEBUG_VERBOSE
, " AttributesSupported - 0x%lx\n", ImageDescriptor
[Index
].AttributesSupported
));
844 DEBUG((DEBUG_VERBOSE
, " AttributesSetting - 0x%lx\n", ImageDescriptor
[Index
].AttributesSetting
));
845 DEBUG((DEBUG_VERBOSE
, " Compatibilities - 0x%lx\n", ImageDescriptor
[Index
].Compatibilities
));
846 DEBUG((DEBUG_VERBOSE
, " LowestSupportedImageVersion - 0x%x\n", ImageDescriptor
[Index
].LowestSupportedImageVersion
));
847 DEBUG((DEBUG_VERBOSE
, " LastAttemptVersion - 0x%x\n", ImageDescriptor
[Index
].LastAttemptVersion
));
848 DEBUG((DEBUG_VERBOSE
, " LastAttemptStatus - 0x%x\n", ImageDescriptor
[Index
].LastAttemptStatus
));
849 DEBUG((DEBUG_VERBOSE
, " HardwareInstance - 0x%lx\n", ImageDescriptor
[Index
].HardwareInstance
));
852 if (MicrocodeFmpPrivate
->FitMicrocodeInfo
!= NULL
) {
853 DEBUG ((DEBUG_INFO
, "FitMicrocodeInfo:\n"));
854 FitMicrocodeInfo
= MicrocodeFmpPrivate
->FitMicrocodeInfo
;
855 DEBUG ((DEBUG_INFO
, " FitMicrocodeEntryCount - 0x%x\n", MicrocodeFmpPrivate
->FitMicrocodeEntryCount
));
856 for (Index
= 0; Index
< MicrocodeFmpPrivate
->FitMicrocodeEntryCount
; Index
++) {
859 " FitMicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x, 0x%x)\n",
861 FitMicrocodeInfo
[Index
].MicrocodeEntryPoint
,
862 FitMicrocodeInfo
[Index
].TotalSize
,
863 FitMicrocodeInfo
[Index
].InUse
,
864 FitMicrocodeInfo
[Index
].Empty
871 Initialize MicrocodeFmpDriver private data structure.
873 @param[in] MicrocodeFmpPrivate private data structure to be initialized.
875 @return EFI_SUCCESS private data is initialized.
878 InitializePrivateData (
879 IN MICROCODE_FMP_PRIVATE_DATA
*MicrocodeFmpPrivate
883 EFI_STATUS VarStatus
;
887 MicrocodeFmpPrivate
->Signature
= MICROCODE_FMP_PRIVATE_DATA_SIGNATURE
;
888 MicrocodeFmpPrivate
->Handle
= NULL
;
889 CopyMem(&MicrocodeFmpPrivate
->Fmp
, &mFirmwareManagementProtocol
, sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL
));
891 MicrocodeFmpPrivate
->PackageVersion
= 0x1;
892 MicrocodeFmpPrivate
->PackageVersionName
= L
"Microcode";
894 MicrocodeFmpPrivate
->LastAttempt
.LastAttemptVersion
= 0x0;
895 MicrocodeFmpPrivate
->LastAttempt
.LastAttemptStatus
= 0x0;
896 VarSize
= sizeof(MicrocodeFmpPrivate
->LastAttempt
);
897 VarStatus
= gRT
->GetVariable(
898 MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME
,
902 &MicrocodeFmpPrivate
->LastAttempt
904 DEBUG((DEBUG_INFO
, "GetLastAttempt - %r\n", VarStatus
));
905 DEBUG((DEBUG_INFO
, "GetLastAttempt Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate
->LastAttempt
.LastAttemptVersion
, MicrocodeFmpPrivate
->LastAttempt
.LastAttemptStatus
));
907 Result
= GetMicrocodeRegion(&MicrocodeFmpPrivate
->MicrocodePatchAddress
, &MicrocodeFmpPrivate
->MicrocodePatchRegionSize
);
909 DEBUG((DEBUG_ERROR
, "Fail to get Microcode Region\n"));
910 return EFI_NOT_FOUND
;
913 Status
= InitializeProcessorInfo (MicrocodeFmpPrivate
);
914 if (EFI_ERROR(Status
)) {
915 DEBUG((DEBUG_ERROR
, "InitializeProcessorInfo - %r\n", Status
));
919 Status
= InitializeMicrocodeDescriptor(MicrocodeFmpPrivate
);
920 if (EFI_ERROR(Status
)) {
921 FreePool (MicrocodeFmpPrivate
->ProcessorInfo
);
922 DEBUG((DEBUG_ERROR
, "InitializeMicrocodeDescriptor - %r\n", Status
));
926 DumpPrivateInfo (MicrocodeFmpPrivate
);
932 Microcode FMP module entrypoint
934 @param[in] ImageHandle The firmware allocated handle for the EFI image.
935 @param[in] SystemTable A pointer to the EFI System Table.
937 @return EFI_SUCCESS Microcode FMP module is initialized.
942 IN EFI_HANDLE ImageHandle
,
943 IN EFI_SYSTEM_TABLE
*SystemTable
949 // Initialize MicrocodeFmpPrivateData
951 mMicrocodeFmpPrivate
= AllocateZeroPool (sizeof(MICROCODE_FMP_PRIVATE_DATA
));
952 if (mMicrocodeFmpPrivate
== NULL
) {
953 return EFI_OUT_OF_RESOURCES
;
956 Status
= InitializePrivateData(mMicrocodeFmpPrivate
);
957 if (EFI_ERROR(Status
)) {
958 FreePool(mMicrocodeFmpPrivate
);
959 mMicrocodeFmpPrivate
= NULL
;
964 // Install FMP protocol.
966 Status
= gBS
->InstallProtocolInterface (
967 &mMicrocodeFmpPrivate
->Handle
,
968 &gEfiFirmwareManagementProtocolGuid
,
969 EFI_NATIVE_INTERFACE
,
970 &mMicrocodeFmpPrivate
->Fmp
972 if (EFI_ERROR (Status
)) {
973 FreePool(mMicrocodeFmpPrivate
);
974 mMicrocodeFmpPrivate
= NULL
;