2016-09-21 05:15:03 +02:00
/** @file
Produce FMP instance for Microcode .
Copyright ( c ) 2016 , Intel Corporation . All rights reserved . < BR >
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution . The full text of the license may be found at
http : //opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN " AS IS " BASIS ,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND , EITHER EXPRESS OR IMPLIED .
* */
# include "MicrocodeUpdate.h"
//
// MicrocodeFmp driver private data
//
MICROCODE_FMP_PRIVATE_DATA * mMicrocodeFmpPrivate = NULL ;
EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol = {
FmpGetImageInfo ,
FmpGetImage ,
FmpSetImage ,
FmpCheckImage ,
FmpGetPackageInfo ,
FmpSetPackageInfo
} ;
/**
Initialize Microcode Descriptor .
@ param [ in ] MicrocodeFmpPrivate private data structure to be initialized .
@ return EFI_SUCCESS Microcode Descriptor is initialized .
* */
EFI_STATUS
InitializeMicrocodeDescriptor (
IN MICROCODE_FMP_PRIVATE_DATA * MicrocodeFmpPrivate
) ;
/**
Returns information about the current firmware image ( s ) of the device .
This function allows a copy of the current firmware image to be created and saved .
The saved copy could later been used , for example , in firmware image recovery or rollback .
@ param [ in ] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance .
@ param [ in , out ] ImageInfoSize A pointer to the size , in bytes , of the ImageInfo buffer .
On input , this is the size of the buffer allocated by the caller .
On output , it is the size of the buffer returned by the firmware
if the buffer was large enough , or the size of the buffer needed
to contain the image ( s ) information if the buffer was too small .
@ param [ in , out ] ImageInfo A pointer to the buffer in which firmware places the current image ( s )
information . The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs .
@ param [ out ] DescriptorVersion A pointer to the location in which firmware returns the version number
associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR .
@ param [ out ] DescriptorCount A pointer to the location in which firmware returns the number of
descriptors or firmware images within this device .
@ param [ out ] DescriptorSize A pointer to the location in which firmware returns the size , in bytes ,
of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR .
@ param [ out ] PackageVersion A version number that represents all the firmware images in the device .
The format is vendor specific and new version must have a greater value
than the old version . If PackageVersion is not supported , the value is
0xFFFFFFFF . A value of 0xFFFFFFFE indicates that package version comparison
is to be performed using PackageVersionName . A value of 0xFFFFFFFD indicates
that package version update is in progress .
@ param [ out ] PackageVersionName A pointer to a pointer to a null - terminated string representing the
package version name . The buffer is allocated by this function with
AllocatePool ( ) , and it is the caller ' s responsibility to free it with a call
to FreePool ( ) .
@ retval EFI_SUCCESS The device was successfully updated with the new image .
@ retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small . The current buffer size
needed to hold the image ( s ) information is returned in ImageInfoSize .
@ retval EFI_INVALID_PARAMETER ImageInfoSize is NULL .
@ retval EFI_DEVICE_ERROR Valid information could not be returned . Possible corrupted image .
* */
EFI_STATUS
EFIAPI
FmpGetImageInfo (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This ,
IN OUT UINTN * ImageInfoSize ,
IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR * ImageInfo ,
OUT UINT32 * DescriptorVersion ,
OUT UINT8 * DescriptorCount ,
OUT UINTN * DescriptorSize ,
OUT UINT32 * PackageVersion ,
OUT CHAR16 * * PackageVersionName
)
{
MICROCODE_FMP_PRIVATE_DATA * MicrocodeFmpPrivate ;
UINTN Index ;
MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP ( This ) ;
if ( ImageInfoSize = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
if ( * ImageInfoSize < sizeof ( EFI_FIRMWARE_IMAGE_DESCRIPTOR ) * MicrocodeFmpPrivate - > DescriptorCount ) {
* ImageInfoSize = sizeof ( EFI_FIRMWARE_IMAGE_DESCRIPTOR ) * MicrocodeFmpPrivate - > DescriptorCount ;
return EFI_BUFFER_TOO_SMALL ;
}
if ( ImageInfo = = NULL | |
DescriptorVersion = = NULL | |
DescriptorCount = = NULL | |
DescriptorSize = = NULL | |
PackageVersion = = NULL | |
PackageVersionName = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
* ImageInfoSize = sizeof ( EFI_FIRMWARE_IMAGE_DESCRIPTOR ) * MicrocodeFmpPrivate - > DescriptorCount ;
* DescriptorSize = sizeof ( EFI_FIRMWARE_IMAGE_DESCRIPTOR ) ;
* DescriptorCount = MicrocodeFmpPrivate - > DescriptorCount ;
* DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION ;
//
// supports 1 ImageInfo descriptor
//
CopyMem ( & ImageInfo [ 0 ] , MicrocodeFmpPrivate - > ImageDescriptor , sizeof ( EFI_FIRMWARE_IMAGE_DESCRIPTOR ) * MicrocodeFmpPrivate - > DescriptorCount ) ;
for ( Index = 0 ; Index < MicrocodeFmpPrivate - > DescriptorCount ; Index + + ) {
if ( ( ImageInfo [ Index ] . AttributesSetting & IMAGE_ATTRIBUTE_IN_USE ) ! = 0 ) {
ImageInfo [ Index ] . LastAttemptVersion = MicrocodeFmpPrivate - > LastAttempt . LastAttemptVersion ;
ImageInfo [ Index ] . LastAttemptStatus = MicrocodeFmpPrivate - > LastAttempt . LastAttemptStatus ;
}
}
//
// package version
//
* PackageVersion = MicrocodeFmpPrivate - > PackageVersion ;
if ( MicrocodeFmpPrivate - > PackageVersionName ! = NULL ) {
* PackageVersionName = AllocateCopyPool ( StrSize ( MicrocodeFmpPrivate - > PackageVersionName ) , MicrocodeFmpPrivate - > PackageVersionName ) ;
}
return EFI_SUCCESS ;
}
/**
Retrieves a copy of the current firmware image of the device .
This function allows a copy of the current firmware image to be created and saved .
The saved copy could later been used , for example , in firmware image recovery or rollback .
@ param [ in ] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance .
@ param [ in ] ImageIndex A unique number identifying the firmware image ( s ) within the device .
The number is between 1 and DescriptorCount .
@ param [ in , out ] Image Points to the buffer where the current image is copied to .
@ param [ in , out ] ImageSize On entry , points to the size of the buffer pointed to by Image , in bytes .
On return , points to the length of the image , in bytes .
@ retval EFI_SUCCESS The device was successfully updated with the new image .
@ retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
image . The current buffer size needed to hold the image is returned
in ImageSize .
@ retval EFI_INVALID_PARAMETER The Image was NULL .
@ retval EFI_NOT_FOUND The current image is not copied to the buffer .
@ retval EFI_UNSUPPORTED The operation is not supported .
@ retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure .
* */
EFI_STATUS
EFIAPI
FmpGetImage (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This ,
IN UINT8 ImageIndex ,
IN OUT VOID * Image ,
IN OUT UINTN * ImageSize
)
{
MICROCODE_FMP_PRIVATE_DATA * MicrocodeFmpPrivate ;
2016-12-26 16:35:41 +01:00
MICROCODE_INFO * MicrocodeInfo ;
2016-09-21 05:15:03 +02:00
if ( Image = = NULL | | ImageSize = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP ( This ) ;
if ( ImageIndex = = 0 | | ImageIndex > MicrocodeFmpPrivate - > DescriptorCount | | ImageSize = = NULL | | Image = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
2016-12-26 16:35:41 +01:00
MicrocodeInfo = & MicrocodeFmpPrivate - > MicrocodeInfo [ ImageIndex - 1 ] ;
if ( * ImageSize < MicrocodeInfo - > TotalSize ) {
* ImageSize = MicrocodeInfo - > TotalSize ;
return EFI_BUFFER_TOO_SMALL ;
}
* ImageSize = MicrocodeInfo - > TotalSize ;
CopyMem ( Image , MicrocodeInfo - > MicrocodeEntryPoint , MicrocodeInfo - > TotalSize ) ;
return EFI_SUCCESS ;
2016-09-21 05:15:03 +02:00
}
/**
Updates the firmware image of the device .
This function updates the hardware with the new firmware image .
This function returns EFI_UNSUPPORTED if the firmware image is not updatable .
If the firmware image is updatable , the function should perform the following minimal validations
before proceeding to do the firmware image update .
- Validate the image authentication if image has attribute
IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED . The function returns
EFI_SECURITY_VIOLATION if the validation fails .
- Validate the image is a supported image for this device . The function returns EFI_ABORTED if
the image is unsupported . The function can optionally provide more detailed information on
why the image is not a supported image .
- Validate the data from VendorCode if not null . Image validation must be performed before
VendorCode data validation . VendorCode data is ignored or considered invalid if image
validation failed . The function returns EFI_ABORTED if the data is invalid .
VendorCode enables vendor to implement vendor - specific firmware image update policy . Null if
the caller did not specify the policy or use the default policy . As an example , vendor can implement
a policy to allow an option to force a firmware image update when the abort reason is due to the new
firmware image version is older than the current firmware image version or bad image checksum .
Sensitive operations such as those wiping the entire firmware image and render the device to be
non - functional should be encoded in the image itself rather than passed with the VendorCode .
AbortReason enables vendor to have the option to provide a more detailed description of the abort
reason to the caller .
@ param [ in ] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance .
@ param [ in ] ImageIndex A unique number identifying the firmware image ( s ) within the device .
The number is between 1 and DescriptorCount .
@ param [ in ] Image Points to the new image .
@ param [ in ] ImageSize Size of the new image in bytes .
@ param [ in ] VendorCode This enables vendor to implement vendor - specific firmware image update policy .
Null indicates the caller did not specify the policy or use the default policy .
@ param [ in ] Progress A function used by the driver to report the progress of the firmware update .
@ param [ out ] AbortReason A pointer to a pointer to a null - terminated string providing more
details for the aborted operation . The buffer is allocated by this function
with AllocatePool ( ) , and it is the caller ' s responsibility to free it with a
call to FreePool ( ) .
@ retval EFI_SUCCESS The device was successfully updated with the new image .
@ retval EFI_ABORTED The operation is aborted .
@ retval EFI_INVALID_PARAMETER The Image was NULL .
@ retval EFI_UNSUPPORTED The operation is not supported .
@ retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure .
* */
EFI_STATUS
EFIAPI
FmpSetImage (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This ,
IN UINT8 ImageIndex ,
IN CONST VOID * Image ,
IN UINTN ImageSize ,
IN CONST VOID * VendorCode ,
IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress ,
OUT CHAR16 * * AbortReason
)
{
EFI_STATUS Status ;
EFI_STATUS VarStatus ;
MICROCODE_FMP_PRIVATE_DATA * MicrocodeFmpPrivate ;
if ( Image = = NULL | | AbortReason = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP ( This ) ;
* AbortReason = NULL ;
if ( ImageIndex = = 0 | | ImageIndex > MicrocodeFmpPrivate - > DescriptorCount | | Image = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
2016-12-26 16:35:41 +01:00
Status = MicrocodeWrite ( MicrocodeFmpPrivate , ( VOID * ) Image , ImageSize , & MicrocodeFmpPrivate - > LastAttempt . LastAttemptVersion , & MicrocodeFmpPrivate - > LastAttempt . LastAttemptStatus , AbortReason ) ;
2016-09-21 05:15:03 +02:00
DEBUG ( ( DEBUG_INFO , " SetImage - LastAttemp Version - 0x%x, State - 0x%x \n " , MicrocodeFmpPrivate - > LastAttempt . LastAttemptVersion , MicrocodeFmpPrivate - > LastAttempt . LastAttemptStatus ) ) ;
VarStatus = gRT - > SetVariable (
MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME ,
& gEfiCallerIdGuid ,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS ,
sizeof ( MicrocodeFmpPrivate - > LastAttempt ) ,
& MicrocodeFmpPrivate - > LastAttempt
) ;
DEBUG ( ( DEBUG_INFO , " SetLastAttemp - %r \n " , VarStatus ) ) ;
if ( ! EFI_ERROR ( Status ) ) {
InitializeMicrocodeDescriptor ( MicrocodeFmpPrivate ) ;
2016-12-27 07:21:16 +01:00
DumpPrivateInfo ( MicrocodeFmpPrivate ) ;
2016-09-21 05:15:03 +02:00
}
return Status ;
}
/**
Checks if the firmware image is valid for the device .
This function allows firmware update application to validate the firmware image without
invoking the SetImage ( ) first .
@ param [ in ] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance .
@ param [ in ] ImageIndex A unique number identifying the firmware image ( s ) within the device .
The number is between 1 and DescriptorCount .
@ param [ in ] Image Points to the new image .
@ param [ in ] ImageSize Size of the new image in bytes .
@ param [ out ] ImageUpdatable Indicates if the new image is valid for update . It also provides ,
if available , additional information if the image is invalid .
@ retval EFI_SUCCESS The image was successfully checked .
@ retval EFI_INVALID_PARAMETER The Image was NULL .
@ retval EFI_UNSUPPORTED The operation is not supported .
@ retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure .
* */
EFI_STATUS
EFIAPI
FmpCheckImage (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This ,
IN UINT8 ImageIndex ,
IN CONST VOID * Image ,
IN UINTN ImageSize ,
OUT UINT32 * ImageUpdatable
)
{
return EFI_UNSUPPORTED ;
}
/**
Returns information about the firmware package .
This function returns package information .
@ param [ in ] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance .
@ param [ out ] PackageVersion A version number that represents all the firmware images in the device .
The format is vendor specific and new version must have a greater value
than the old version . If PackageVersion is not supported , the value is
0xFFFFFFFF . A value of 0xFFFFFFFE indicates that package version
comparison is to be performed using PackageVersionName . A value of
0xFFFFFFFD indicates that package version update is in progress .
@ param [ out ] PackageVersionName A pointer to a pointer to a null - terminated string representing
the package version name . The buffer is allocated by this function with
AllocatePool ( ) , and it is the caller ' s responsibility to free it with a
call to FreePool ( ) .
@ param [ out ] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
package version name . A value of 0 indicates the device does not support
update of package version name . Length is the number of Unicode characters ,
including the terminating null character .
@ param [ out ] AttributesSupported Package attributes that are supported by this device . See ' Package Attribute
Definitions ' for possible returned values of this parameter . A value of 1
indicates the attribute is supported and the current setting value is
indicated in AttributesSetting . A value of 0 indicates the attribute is not
supported and the current setting value in AttributesSetting is meaningless .
@ param [ out ] AttributesSetting Package attributes . See ' Package Attribute Definitions ' for possible returned
values of this parameter
@ retval EFI_SUCCESS The package information was successfully returned .
@ retval EFI_UNSUPPORTED The operation is not supported .
* */
EFI_STATUS
EFIAPI
FmpGetPackageInfo (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This ,
OUT UINT32 * PackageVersion ,
OUT CHAR16 * * PackageVersionName ,
OUT UINT32 * PackageVersionNameMaxLen ,
OUT UINT64 * AttributesSupported ,
OUT UINT64 * AttributesSetting
)
{
return EFI_UNSUPPORTED ;
}
/**
Updates information about the firmware package .
This function updates package information .
This function returns EFI_UNSUPPORTED if the package information is not updatable .
VendorCode enables vendor to implement vendor - specific package information update policy .
Null if the caller did not specify this policy or use the default policy .
@ param [ in ] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance .
@ param [ in ] Image Points to the authentication image .
Null if authentication is not required .
@ param [ in ] ImageSize Size of the authentication image in bytes .
0 if authentication is not required .
@ param [ in ] VendorCode This enables vendor to implement vendor - specific firmware
image update policy .
Null indicates the caller did not specify this policy or use
the default policy .
@ param [ in ] PackageVersion The new package version .
@ param [ in ] PackageVersionName A pointer to the new null - terminated Unicode string representing
the package version name .
The string length is equal to or less than the value returned in
PackageVersionNameMaxLen .
@ retval EFI_SUCCESS The device was successfully updated with the new package
information .
@ retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
returned in PackageVersionNameMaxLen .
@ retval EFI_UNSUPPORTED The operation is not supported .
@ retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure .
* */
EFI_STATUS
EFIAPI
FmpSetPackageInfo (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL * This ,
IN CONST VOID * Image ,
IN UINTN ImageSize ,
IN CONST VOID * VendorCode ,
IN UINT32 PackageVersion ,
IN CONST CHAR16 * PackageVersionName
)
{
return EFI_UNSUPPORTED ;
}
2016-12-27 07:21:16 +01:00
/**
Initialize Processor Microcode Index .
@ param [ in ] MicrocodeFmpPrivate private data structure to be initialized .
* */
VOID
InitializedProcessorMicrocodeIndex (
IN MICROCODE_FMP_PRIVATE_DATA * MicrocodeFmpPrivate
)
{
UINTN CpuIndex ;
UINTN MicrocodeIndex ;
UINTN TargetCpuIndex ;
UINT32 AttemptStatus ;
EFI_STATUS Status ;
for ( CpuIndex = 0 ; CpuIndex < MicrocodeFmpPrivate - > ProcessorCount ; CpuIndex + + ) {
if ( MicrocodeFmpPrivate - > ProcessorInfo [ CpuIndex ] . MicrocodeIndex ! = ( UINTN ) - 1 ) {
continue ;
}
for ( MicrocodeIndex = 0 ; MicrocodeIndex < MicrocodeFmpPrivate - > DescriptorCount ; MicrocodeIndex + + ) {
if ( ! MicrocodeFmpPrivate - > MicrocodeInfo [ MicrocodeIndex ] . InUse ) {
continue ;
}
TargetCpuIndex = CpuIndex ;
Status = VerifyMicrocode (
MicrocodeFmpPrivate ,
MicrocodeFmpPrivate - > MicrocodeInfo [ MicrocodeIndex ] . MicrocodeEntryPoint ,
MicrocodeFmpPrivate - > MicrocodeInfo [ MicrocodeIndex ] . TotalSize ,
FALSE ,
& AttemptStatus ,
NULL ,
& TargetCpuIndex
) ;
if ( ! EFI_ERROR ( Status ) ) {
MicrocodeFmpPrivate - > ProcessorInfo [ CpuIndex ] . MicrocodeIndex = MicrocodeIndex ;
}
}
}
}
2016-09-21 05:15:03 +02:00
/**
Initialize Microcode Descriptor .
@ param [ in ] MicrocodeFmpPrivate private data structure to be initialized .
@ return EFI_SUCCESS Microcode Descriptor is initialized .
* */
EFI_STATUS
InitializeMicrocodeDescriptor (
IN MICROCODE_FMP_PRIVATE_DATA * MicrocodeFmpPrivate
)
{
2016-12-26 16:35:41 +01:00
UINT8 CurrentMicrocodeCount ;
2016-09-21 05:15:03 +02:00
2016-12-26 16:35:41 +01:00
CurrentMicrocodeCount = ( UINT8 ) GetMicrocodeInfo ( MicrocodeFmpPrivate , 0 , NULL , NULL ) ;
2016-09-21 05:15:03 +02:00
if ( CurrentMicrocodeCount > MicrocodeFmpPrivate - > DescriptorCount ) {
if ( MicrocodeFmpPrivate - > ImageDescriptor ! = NULL ) {
FreePool ( MicrocodeFmpPrivate - > ImageDescriptor ) ;
MicrocodeFmpPrivate - > ImageDescriptor = NULL ;
}
2016-12-26 16:35:41 +01:00
if ( MicrocodeFmpPrivate - > MicrocodeInfo ! = NULL ) {
FreePool ( MicrocodeFmpPrivate - > MicrocodeInfo ) ;
MicrocodeFmpPrivate - > MicrocodeInfo = NULL ;
}
2016-09-21 05:15:03 +02:00
} else {
ZeroMem ( MicrocodeFmpPrivate - > ImageDescriptor , MicrocodeFmpPrivate - > DescriptorCount * sizeof ( EFI_FIRMWARE_IMAGE_DESCRIPTOR ) ) ;
2016-12-26 16:35:41 +01:00
ZeroMem ( MicrocodeFmpPrivate - > MicrocodeInfo , MicrocodeFmpPrivate - > DescriptorCount * sizeof ( MICROCODE_INFO ) ) ;
2016-09-21 05:15:03 +02:00
}
MicrocodeFmpPrivate - > DescriptorCount = CurrentMicrocodeCount ;
if ( MicrocodeFmpPrivate - > ImageDescriptor = = NULL ) {
MicrocodeFmpPrivate - > ImageDescriptor = AllocateZeroPool ( MicrocodeFmpPrivate - > DescriptorCount * sizeof ( EFI_FIRMWARE_IMAGE_DESCRIPTOR ) ) ;
if ( MicrocodeFmpPrivate - > ImageDescriptor = = NULL ) {
return EFI_OUT_OF_RESOURCES ;
}
}
2016-12-26 16:35:41 +01:00
if ( MicrocodeFmpPrivate - > MicrocodeInfo = = NULL ) {
MicrocodeFmpPrivate - > MicrocodeInfo = AllocateZeroPool ( MicrocodeFmpPrivate - > DescriptorCount * sizeof ( MICROCODE_INFO ) ) ;
if ( MicrocodeFmpPrivate - > MicrocodeInfo = = NULL ) {
return EFI_OUT_OF_RESOURCES ;
}
}
2016-09-21 05:15:03 +02:00
2016-12-26 16:35:41 +01:00
CurrentMicrocodeCount = ( UINT8 ) GetMicrocodeInfo ( MicrocodeFmpPrivate , MicrocodeFmpPrivate - > DescriptorCount , MicrocodeFmpPrivate - > ImageDescriptor , MicrocodeFmpPrivate - > MicrocodeInfo ) ;
2016-09-21 05:15:03 +02:00
ASSERT ( CurrentMicrocodeCount = = MicrocodeFmpPrivate - > DescriptorCount ) ;
2016-12-27 07:21:16 +01:00
InitializedProcessorMicrocodeIndex ( MicrocodeFmpPrivate ) ;
return EFI_SUCCESS ;
}
/**
Initialize MicrocodeFmpDriver multiprocessor information .
@ param [ in ] MicrocodeFmpPrivate private data structure to be initialized .
@ return EFI_SUCCESS private data is initialized .
* */
EFI_STATUS
InitializeProcessorInfo (
IN MICROCODE_FMP_PRIVATE_DATA * MicrocodeFmpPrivate
)
{
EFI_STATUS Status ;
EFI_MP_SERVICES_PROTOCOL * MpService ;
UINTN NumberOfProcessors ;
UINTN NumberOfEnabledProcessors ;
UINTN Index ;
UINTN BspIndex ;
Status = gBS - > LocateProtocol ( & gEfiMpServiceProtocolGuid , NULL , ( VOID * * ) & MpService ) ;
ASSERT_EFI_ERROR ( Status ) ;
MicrocodeFmpPrivate - > MpService = MpService ;
MicrocodeFmpPrivate - > ProcessorCount = 0 ;
MicrocodeFmpPrivate - > ProcessorInfo = NULL ;
Status = MpService - > GetNumberOfProcessors ( MpService , & NumberOfProcessors , & NumberOfEnabledProcessors ) ;
ASSERT_EFI_ERROR ( Status ) ;
MicrocodeFmpPrivate - > ProcessorCount = NumberOfProcessors ;
Status = MpService - > WhoAmI ( MpService , & BspIndex ) ;
ASSERT_EFI_ERROR ( Status ) ;
MicrocodeFmpPrivate - > BspIndex = BspIndex ;
MicrocodeFmpPrivate - > ProcessorInfo = AllocateZeroPool ( sizeof ( PROCESSOR_INFO ) * MicrocodeFmpPrivate - > ProcessorCount ) ;
if ( MicrocodeFmpPrivate - > ProcessorInfo = = NULL ) {
return EFI_OUT_OF_RESOURCES ;
}
for ( Index = 0 ; Index < NumberOfProcessors ; Index + + ) {
MicrocodeFmpPrivate - > ProcessorInfo [ Index ] . CpuIndex = Index ;
MicrocodeFmpPrivate - > ProcessorInfo [ Index ] . MicrocodeIndex = ( UINTN ) - 1 ;
if ( Index = = BspIndex ) {
CollectProcessorInfo ( & MicrocodeFmpPrivate - > ProcessorInfo [ Index ] ) ;
} else {
Status = MpService - > StartupThisAP (
MpService ,
CollectProcessorInfo ,
Index ,
NULL ,
0 ,
& MicrocodeFmpPrivate - > ProcessorInfo [ Index ] ,
NULL
) ;
ASSERT_EFI_ERROR ( Status ) ;
}
}
2016-09-21 05:15:03 +02:00
return EFI_SUCCESS ;
}
2016-12-27 07:21:16 +01:00
/**
Dump private information .
@ param [ in ] MicrocodeFmpPrivate private data structure .
* */
VOID
DumpPrivateInfo (
IN MICROCODE_FMP_PRIVATE_DATA * MicrocodeFmpPrivate
)
{
UINTN Index ;
PROCESSOR_INFO * ProcessorInfo ;
MICROCODE_INFO * MicrocodeInfo ;
EFI_FIRMWARE_IMAGE_DESCRIPTOR * ImageDescriptor ;
DEBUG ( ( DEBUG_INFO , " ProcessorInfo: \n " ) ) ;
DEBUG ( ( DEBUG_INFO , " ProcessorCount - 0x%x \n " , MicrocodeFmpPrivate - > ProcessorCount ) ) ;
DEBUG ( ( DEBUG_INFO , " BspIndex - 0x%x \n " , MicrocodeFmpPrivate - > BspIndex ) ) ;
ProcessorInfo = MicrocodeFmpPrivate - > ProcessorInfo ;
for ( Index = 0 ; Index < MicrocodeFmpPrivate - > ProcessorCount ; Index + + ) {
DEBUG ( (
DEBUG_INFO ,
" ProcessorInfo[0x%x] - 0x%08x, 0x%02x, 0x%08x, (0x%x) \n " ,
ProcessorInfo [ Index ] . CpuIndex ,
ProcessorInfo [ Index ] . ProcessorSignature ,
ProcessorInfo [ Index ] . PlatformId ,
ProcessorInfo [ Index ] . MicrocodeRevision ,
ProcessorInfo [ Index ] . MicrocodeIndex
) ) ;
}
DEBUG ( ( DEBUG_INFO , " MicrocodeInfo: \n " ) ) ;
MicrocodeInfo = MicrocodeFmpPrivate - > MicrocodeInfo ;
DEBUG ( ( DEBUG_INFO , " MicrocodeRegion - 0x%x - 0x%x \n " , MicrocodeFmpPrivate - > MicrocodePatchAddress , MicrocodeFmpPrivate - > MicrocodePatchRegionSize ) ) ;
DEBUG ( ( DEBUG_INFO , " MicrocodeCount - 0x%x \n " , MicrocodeFmpPrivate - > DescriptorCount ) ) ;
for ( Index = 0 ; Index < MicrocodeFmpPrivate - > DescriptorCount ; Index + + ) {
DEBUG ( (
DEBUG_INFO ,
" MicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x) \n " ,
Index ,
MicrocodeInfo [ Index ] . MicrocodeEntryPoint ,
MicrocodeInfo [ Index ] . TotalSize ,
MicrocodeInfo [ Index ] . InUse
) ) ;
}
ImageDescriptor = MicrocodeFmpPrivate - > ImageDescriptor ;
DEBUG ( ( DEBUG_VERBOSE , " ImageDescriptor: \n " ) ) ;
for ( Index = 0 ; Index < MicrocodeFmpPrivate - > DescriptorCount ; Index + + ) {
DEBUG ( ( DEBUG_VERBOSE , " ImageDescriptor (%d) \n " , Index ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " ImageIndex - 0x%x \n " , ImageDescriptor [ Index ] . ImageIndex ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " ImageTypeId - %g \n " , & ImageDescriptor [ Index ] . ImageTypeId ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " ImageId - 0x%lx \n " , ImageDescriptor [ Index ] . ImageId ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " ImageIdName - %s \n " , ImageDescriptor [ Index ] . ImageIdName ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " Version - 0x%x \n " , ImageDescriptor [ Index ] . Version ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " VersionName - %s \n " , ImageDescriptor [ Index ] . VersionName ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " Size - 0x%x \n " , ImageDescriptor [ Index ] . Size ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " AttributesSupported - 0x%lx \n " , ImageDescriptor [ Index ] . AttributesSupported ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " AttributesSetting - 0x%lx \n " , ImageDescriptor [ Index ] . AttributesSetting ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " Compatibilities - 0x%lx \n " , ImageDescriptor [ Index ] . Compatibilities ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " LowestSupportedImageVersion - 0x%x \n " , ImageDescriptor [ Index ] . LowestSupportedImageVersion ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " LastAttemptVersion - 0x%x \n " , ImageDescriptor [ Index ] . LastAttemptVersion ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " LastAttemptStatus - 0x%x \n " , ImageDescriptor [ Index ] . LastAttemptStatus ) ) ;
DEBUG ( ( DEBUG_VERBOSE , " HardwareInstance - 0x%lx \n " , ImageDescriptor [ Index ] . HardwareInstance ) ) ;
}
}
2016-09-21 05:15:03 +02:00
/**
Initialize MicrocodeFmpDriver private data structure .
@ param [ in ] MicrocodeFmpPrivate private data structure to be initialized .
@ return EFI_SUCCESS private data is initialized .
* */
EFI_STATUS
InitializePrivateData (
IN MICROCODE_FMP_PRIVATE_DATA * MicrocodeFmpPrivate
)
{
EFI_STATUS Status ;
EFI_STATUS VarStatus ;
UINTN VarSize ;
2016-12-26 16:35:41 +01:00
BOOLEAN Result ;
2016-09-21 05:15:03 +02:00
MicrocodeFmpPrivate - > Signature = MICROCODE_FMP_PRIVATE_DATA_SIGNATURE ;
MicrocodeFmpPrivate - > Handle = NULL ;
CopyMem ( & MicrocodeFmpPrivate - > Fmp , & mFirmwareManagementProtocol , sizeof ( EFI_FIRMWARE_MANAGEMENT_PROTOCOL ) ) ;
MicrocodeFmpPrivate - > PackageVersion = 0x1 ;
MicrocodeFmpPrivate - > PackageVersionName = L " Microcode " ;
MicrocodeFmpPrivate - > LastAttempt . LastAttemptVersion = 0x0 ;
MicrocodeFmpPrivate - > LastAttempt . LastAttemptStatus = 0x0 ;
VarSize = sizeof ( MicrocodeFmpPrivate - > LastAttempt ) ;
VarStatus = gRT - > GetVariable (
MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME ,
& gEfiCallerIdGuid ,
NULL ,
& VarSize ,
& MicrocodeFmpPrivate - > LastAttempt
) ;
DEBUG ( ( DEBUG_INFO , " GetLastAttemp - %r \n " , VarStatus ) ) ;
DEBUG ( ( DEBUG_INFO , " GetLastAttemp Version - 0x%x, State - 0x%x \n " , MicrocodeFmpPrivate - > LastAttempt . LastAttemptVersion , MicrocodeFmpPrivate - > LastAttempt . LastAttemptStatus ) ) ;
2016-12-26 16:35:41 +01:00
Result = GetMicrocodeRegion ( & MicrocodeFmpPrivate - > MicrocodePatchAddress , & MicrocodeFmpPrivate - > MicrocodePatchRegionSize ) ;
if ( ! Result ) {
DEBUG ( ( DEBUG_ERROR , " Fail to get Microcode Region \n " ) ) ;
return EFI_NOT_FOUND ;
}
2016-12-27 07:21:16 +01:00
Status = InitializeProcessorInfo ( MicrocodeFmpPrivate ) ;
if ( EFI_ERROR ( Status ) ) {
DEBUG ( ( DEBUG_ERROR , " InitializeProcessorInfo - %r \n " , Status ) ) ;
return Status ;
}
2016-09-21 05:15:03 +02:00
Status = InitializeMicrocodeDescriptor ( MicrocodeFmpPrivate ) ;
2016-12-27 07:21:16 +01:00
if ( EFI_ERROR ( Status ) ) {
DEBUG ( ( DEBUG_ERROR , " InitializeMicrocodeDescriptor - %r \n " , Status ) ) ;
return Status ;
}
DumpPrivateInfo ( MicrocodeFmpPrivate ) ;
2016-09-21 05:15:03 +02:00
return Status ;
}
/**
Microcode FMP module entrypoint
@ param [ in ] ImageHandle The firmware allocated handle for the EFI image .
@ param [ in ] SystemTable A pointer to the EFI System Table .
@ return EFI_SUCCESS Microcode FMP module is initialized .
* */
EFI_STATUS
EFIAPI
MicrocodeFmpMain (
IN EFI_HANDLE ImageHandle ,
IN EFI_SYSTEM_TABLE * SystemTable
)
{
EFI_STATUS Status ;
//
// Initialize MicrocodeFmpPrivateData
//
mMicrocodeFmpPrivate = AllocateZeroPool ( sizeof ( MICROCODE_FMP_PRIVATE_DATA ) ) ;
if ( mMicrocodeFmpPrivate = = NULL ) {
return EFI_OUT_OF_RESOURCES ;
}
Status = InitializePrivateData ( mMicrocodeFmpPrivate ) ;
if ( EFI_ERROR ( Status ) ) {
FreePool ( mMicrocodeFmpPrivate ) ;
mMicrocodeFmpPrivate = NULL ;
return Status ;
}
//
// Install FMP protocol.
//
Status = gBS - > InstallProtocolInterface (
& mMicrocodeFmpPrivate - > Handle ,
& gEfiFirmwareManagementProtocolGuid ,
EFI_NATIVE_INTERFACE ,
& mMicrocodeFmpPrivate - > Fmp
) ;
if ( EFI_ERROR ( Status ) ) {
FreePool ( mMicrocodeFmpPrivate ) ;
mMicrocodeFmpPrivate = NULL ;
return Status ;
}
return Status ;
}