1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975 |
- /** @file
- Produces a Firmware Management Protocol that supports updates to a firmware
- image stored in a firmware device with platform and firmware device specific
- information provided through PCDs and libraries.
- Copyright (c) Microsoft Corporation.<BR>
- Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "FmpDxe.h"
- #include "VariableSupport.h"
- ///
- /// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the
- /// FILE_GUID must always be overridden in the <Defines> section to provide
- /// the ESRT GUID value associated with the updatable firmware image. A
- /// check is made in this module's driver entry point to verify that a
- /// new FILE_GUID value has been defined.
- ///
- const EFI_GUID mDefaultModuleFileGuid = {
- 0x78ef0a56, 0x1cf0, 0x4535, { 0xb5, 0xda, 0xf6, 0xfd, 0x2f, 0x40, 0x5a, 0x11 }
- };
- ///
- /// TRUE if FmpDeviceLib manages a single firmware storage device.
- ///
- BOOLEAN mFmpSingleInstance = FALSE;
- ///
- /// Firmware Management Protocol instance that is initialized in the entry
- /// point from PCD settings.
- ///
- EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL mFmpProgress;
- //
- // Template of the private context structure for the Firmware Management
- // Protocol instance
- //
- const FIRMWARE_MANAGEMENT_PRIVATE_DATA mFirmwareManagementPrivateDataTemplate = {
- FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE, // Signature
- NULL, // Handle
- { // Fmp
- GetTheImageInfo,
- GetTheImage,
- SetTheImage,
- CheckTheImage,
- GetPackageInfo,
- SetPackageInfo
- },
- FALSE, // DescriptorPopulated
- { // Desc
- 1, // ImageIndex
- //
- // ImageTypeId
- //
- { 0x00000000, 0x0000,0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
- },
- 1, // ImageId
- NULL, // ImageIdName
- 0, // Version
- NULL, // VersionName
- 0, // Size
- 0, // AttributesSupported
- 0, // AttributesSetting
- 0, // Compatibilities
- 0, // LowestSupportedImageVersion
- 0, // LastAttemptVersion
- 0, // LastAttemptStatus
- 0 // HardwareInstance
- },
- NULL, // ImageIdName
- NULL, // VersionName
- TRUE, // RuntimeVersionSupported
- NULL, // FmpDeviceLockEvent
- FALSE, // FmpDeviceLocked
- NULL, // FmpDeviceContext
- NULL, // VersionVariableName
- NULL, // LsvVariableName
- NULL, // LastAttemptStatusVariableName
- NULL, // LastAttemptVersionVariableName
- NULL, // FmpStateVariableName
- TRUE // DependenciesSatisfied
- };
- ///
- /// GUID that is used to create event used to lock the firmware storage device.
- ///
- EFI_GUID *mLockGuid = NULL;
- ///
- /// Progress() function pointer passed into SetTheImage()
- ///
- EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS mProgressFunc = NULL;
- ///
- /// Null-terminated Unicode string retrieved from PcdFmpDeviceImageIdName.
- ///
- CHAR16 *mImageIdName = NULL;
- /**
- Callback function to report the process of the firmware updating.
- Wrap the caller's version in this so that progress from the device lib is
- within the expected range. Convert device lib 0% - 100% to 6% - 98%.
- FmpDxe 1% - 5% for validation
- FmpDeviceLib 6% - 98% for flashing/update
- FmpDxe 99% - 100% finish
- @param[in] Completion A value between 1 and 100 indicating the current
- completion progress of the firmware update. Completion
- progress is reported as from 1 to 100 percent. A value
- of 0 is used by the driver to indicate that progress
- reporting is not supported.
- @retval EFI_SUCCESS The progress was updated.
- @retval EFI_UNSUPPORTED Updating progress is not supported.
- **/
- EFI_STATUS
- EFIAPI
- FmpDxeProgress (
- IN UINTN Completion
- )
- {
- EFI_STATUS Status;
- Status = EFI_UNSUPPORTED;
- if (mProgressFunc == NULL) {
- return Status;
- }
- //
- // Reserve 6% - 98% for the FmpDeviceLib. Call the real progress function.
- //
- Status = mProgressFunc (((Completion * 92) / 100) + 6);
- if (Status == EFI_UNSUPPORTED) {
- mProgressFunc = NULL;
- }
- return Status;
- }
- /**
- Returns a pointer to the ImageTypeId GUID value. An attempt is made to get
- the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide
- a GUID value, then PcdFmpDeviceImageTypeIdGuid is used. If the size of
- PcdFmpDeviceImageTypeIdGuid is not the size of EFI_GUID, then gEfiCallerIdGuid
- is returned.
- @retval The ImageTypeId GUID
- **/
- EFI_GUID *
- GetImageTypeIdGuid (
- VOID
- )
- {
- EFI_STATUS Status;
- EFI_GUID *FmpDeviceLibGuid;
- UINTN ImageTypeIdGuidSize;
- FmpDeviceLibGuid = NULL;
- Status = FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid);
- if (EFI_ERROR (Status)) {
- if (Status != EFI_UNSUPPORTED) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", mImageIdName, Status));
- }
- } else if (FmpDeviceLibGuid == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n", mImageIdName));
- Status = EFI_NOT_FOUND;
- }
- if (EFI_ERROR (Status)) {
- ImageTypeIdGuidSize = PcdGetSize (PcdFmpDeviceImageTypeIdGuid);
- if (ImageTypeIdGuidSize == sizeof (EFI_GUID)) {
- FmpDeviceLibGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceImageTypeIdGuid);
- } else {
- DEBUG ((DEBUG_WARN, "FmpDxe(%s): Fall back to ImageTypeIdGuid of gEfiCallerIdGuid\n", mImageIdName));
- FmpDeviceLibGuid = &gEfiCallerIdGuid;
- }
- }
- return FmpDeviceLibGuid;
- }
- /**
- Returns a pointer to the Null-terminated Unicode ImageIdName string.
- @retval Null-terminated Unicode ImageIdName string.
- **/
- CHAR16 *
- GetImageTypeNameString (
- VOID
- )
- {
- return mImageIdName;
- }
- /**
- Lowest supported version is a combo of three parts.
- 1. Check if the device lib has a lowest supported version
- 2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied)
- 3. Check Fixed at build PCD
- @param[in] Private Pointer to the private context structure for the
- Firmware Management Protocol instance.
- @retval The largest value
- **/
- UINT32
- GetLowestSupportedVersion (
- FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
- )
- {
- EFI_STATUS Status;
- UINT32 DeviceLibLowestSupportedVersion;
- UINT32 VariableLowestSupportedVersion;
- UINT32 ReturnLsv;
- //
- // Get the LowestSupportedVersion.
- //
- if (!IsLowestSupportedVersionCheckRequired ()) {
- //
- // Any Version can pass the 0 LowestSupportedVersion check.
- //
- return 0;
- }
- ReturnLsv = PcdGet32 (PcdFmpDeviceBuildTimeLowestSupportedVersion);
- //
- // Check the FmpDeviceLib
- //
- DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
- Status = FmpDeviceGetLowestSupportedVersion (&DeviceLibLowestSupportedVersion);
- if (EFI_ERROR (Status)) {
- DeviceLibLowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
- }
- if (DeviceLibLowestSupportedVersion > ReturnLsv) {
- ReturnLsv = DeviceLibLowestSupportedVersion;
- }
- //
- // Check the lowest supported version UEFI variable for this device
- //
- VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable (Private);
- if (VariableLowestSupportedVersion > ReturnLsv) {
- ReturnLsv = VariableLowestSupportedVersion;
- }
- //
- // Return the largest value
- //
- return ReturnLsv;
- }
- /**
- Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the private
- context structure.
- @param[in] Private Pointer to the private context structure for the
- Firmware Management Protocol instance.
- **/
- VOID
- PopulateDescriptor (
- FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
- )
- {
- EFI_STATUS Status;
- UINT32 DependenciesSize;
- if (Private == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): PopulateDescriptor() - Private is NULL.\n", mImageIdName));
- return;
- }
- if (Private->DescriptorPopulated) {
- return;
- }
- Private->Descriptor.ImageIndex = 1;
- CopyGuid (&Private->Descriptor.ImageTypeId, GetImageTypeIdGuid ());
- Private->Descriptor.ImageId = Private->Descriptor.ImageIndex;
- Private->Descriptor.ImageIdName = GetImageTypeNameString ();
- //
- // Get the hardware instance from FmpDeviceLib
- //
- Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);
- if (Status == EFI_UNSUPPORTED) {
- Private->Descriptor.HardwareInstance = 0;
- }
- //
- // Generate UEFI Variable names used to store status information for this
- // FMP instance.
- //
- GenerateFmpVariableNames (Private);
- //
- // Get the version. Some devices don't support getting the firmware version
- // at runtime. If FmpDeviceLib does not support returning a version, then
- // it is stored in a UEFI variable.
- //
- Status = FmpDeviceGetVersion (&Private->Descriptor.Version);
- if (Status == EFI_UNSUPPORTED) {
- Private->RuntimeVersionSupported = FALSE;
- Private->Descriptor.Version = GetVersionFromVariable (Private);
- } else if (EFI_ERROR (Status)) {
- //
- // Unexpected error. Use default version.
- //
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetVersion() from FmpDeviceLib (%s) returned %r\n", mImageIdName, GetImageTypeNameString (), Status));
- Private->Descriptor.Version = DEFAULT_VERSION;
- }
- //
- // Free the current version name. Shouldn't really happen but this populate
- // function could be called multiple times (to refresh).
- //
- if (Private->Descriptor.VersionName != NULL) {
- FreePool (Private->Descriptor.VersionName);
- Private->Descriptor.VersionName = NULL;
- }
- //
- // Attempt to get the version string from the FmpDeviceLib
- //
- Status = FmpDeviceGetVersionString (&Private->Descriptor.VersionName);
- if (Status == EFI_UNSUPPORTED) {
- DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() unsupported in FmpDeviceLib.\n", mImageIdName));
- Private->Descriptor.VersionName = AllocateCopyPool (
- sizeof (VERSION_STRING_NOT_SUPPORTED),
- VERSION_STRING_NOT_SUPPORTED
- );
- } else if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() not available in FmpDeviceLib.\n", mImageIdName));
- Private->Descriptor.VersionName = AllocateCopyPool (
- sizeof (VERSION_STRING_NOT_AVAILABLE),
- VERSION_STRING_NOT_AVAILABLE
- );
- }
- Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion (Private);
- //
- // Get attributes from the FmpDeviceLib
- //
- FmpDeviceGetAttributes (
- &Private->Descriptor.AttributesSupported,
- &Private->Descriptor.AttributesSetting
- );
- //
- // Force set the updatable bits in the attributes;
- //
- Private->Descriptor.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
- Private->Descriptor.AttributesSetting |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
- //
- // Force set the authentication bits in the attributes;
- //
- Private->Descriptor.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
- Private->Descriptor.AttributesSetting |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
- Private->Descriptor.Compatibilities = 0;
- //
- // Get the size of the firmware image from the FmpDeviceLib
- //
- Status = FmpDeviceGetSize (&Private->Descriptor.Size);
- if (EFI_ERROR (Status)) {
- Private->Descriptor.Size = 0;
- }
- Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable (Private);
- Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable (Private);
- //
- // Get the dependency from the FmpDependencyDeviceLib.
- //
- Private->Descriptor.Dependencies = NULL;
- //
- // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
- //
- if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
- Private->Descriptor.Dependencies = GetFmpDependency (&DependenciesSize);
- }
- Private->DescriptorPopulated = TRUE;
- }
- /**
- 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
- GetTheImageInfo (
- 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
- )
- {
- EFI_STATUS Status;
- FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
- Status = EFI_SUCCESS;
- if (This == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - This is NULL.\n", mImageIdName));
- Status = EFI_INVALID_PARAMETER;
- goto cleanup;
- }
- //
- // Retrieve the private context structure
- //
- Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
- FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
- //
- // Check for valid pointer
- //
- if (ImageInfoSize == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is NULL.\n", mImageIdName));
- Status = EFI_INVALID_PARAMETER;
- goto cleanup;
- }
- //
- // Check the buffer size
- // NOTE: Check this first so caller can get the necessary memory size it must allocate.
- //
- if (*ImageInfoSize < (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR))) {
- *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
- DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is to small.\n", mImageIdName));
- Status = EFI_BUFFER_TOO_SMALL;
- goto cleanup;
- }
- //
- // Confirm that buffer isn't null
- //
- if ( (ImageInfo == NULL) || (DescriptorVersion == NULL) || (DescriptorCount == NULL) || (DescriptorSize == NULL)
- || (PackageVersion == NULL))
- {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - Pointer Parameter is NULL.\n", mImageIdName));
- Status = EFI_INVALID_PARAMETER;
- goto cleanup;
- }
- //
- // Set the size to whatever we need
- //
- *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
- //
- // Make sure the descriptor has already been loaded or refreshed
- //
- PopulateDescriptor (Private);
- //
- // Copy the image descriptor
- //
- CopyMem (ImageInfo, &Private->Descriptor, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));
- *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
- *DescriptorCount = 1;
- *DescriptorSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
- //
- // means unsupported
- //
- *PackageVersion = 0xFFFFFFFF;
- //
- // Do not update PackageVersionName since it is not supported in this instance.
- //
- cleanup:
- return Status;
- }
- /**
- 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_VIOLATION The operation could not be performed due to an authentication failure.
- **/
- EFI_STATUS
- EFIAPI
- GetTheImage (
- IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
- IN UINT8 ImageIndex,
- IN OUT VOID *Image,
- IN OUT UINTN *ImageSize
- )
- {
- EFI_STATUS Status;
- FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
- UINTN Size;
- if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
- return EFI_UNSUPPORTED;
- }
- Status = EFI_SUCCESS;
- if (This == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - This is NULL.\n", mImageIdName));
- Status = EFI_INVALID_PARAMETER;
- goto cleanup;
- }
- //
- // Retrieve the private context structure
- //
- Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
- FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
- //
- // Check to make sure index is 1 (only 1 image for this device)
- //
- if (ImageIndex != 1) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Index Invalid.\n", mImageIdName));
- Status = EFI_INVALID_PARAMETER;
- goto cleanup;
- }
- if (ImageSize == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - ImageSize Pointer Parameter is NULL.\n", mImageIdName));
- Status = EFI_INVALID_PARAMETER;
- goto cleanup;
- }
- //
- // Check the buffer size
- //
- Status = FmpDeviceGetSize (&Size);
- if (EFI_ERROR (Status)) {
- Size = 0;
- }
- if (*ImageSize < Size) {
- *ImageSize = Size;
- DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName));
- Status = EFI_BUFFER_TOO_SMALL;
- goto cleanup;
- }
- if (Image == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
- Status = EFI_INVALID_PARAMETER;
- goto cleanup;
- }
- Status = FmpDeviceGetImage (Image, ImageSize);
- cleanup:
- return Status;
- }
- /**
- Helper function to safely retrieve the FMP header from
- within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
- @param[in] Image Pointer to the image.
- @param[in] ImageSize Size of the image.
- @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.
- @param[out] PayloadSize An optional pointer to a UINTN that holds the size of the payload
- (image size minus headers)
- @retval !NULL Valid pointer to the header.
- @retval NULL Structure is bad and pointer cannot be found.
- **/
- VOID *
- GetFmpHeader (
- IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
- IN CONST UINTN ImageSize,
- IN CONST UINTN AdditionalHeaderSize,
- OUT UINTN *PayloadSize OPTIONAL
- )
- {
- //
- // Check to make sure that operation can be safely performed.
- //
- if ((((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize < (UINTN)Image) || \
- (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize >= (UINTN)Image + ImageSize))
- {
- //
- // Pointer overflow. Invalid image.
- //
- return NULL;
- }
- if (PayloadSize != NULL) {
- *PayloadSize = ImageSize - (sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength + AdditionalHeaderSize);
- }
- return (VOID *)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength + AdditionalHeaderSize);
- }
- /**
- Helper function to safely calculate the size of all headers
- within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
- @param[in] Image Pointer to the image.
- @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.
- @retval UINT32>0 Valid size of all the headers.
- @retval 0 Structure is bad and size cannot be found.
- **/
- UINT32
- GetAllHeaderSize (
- IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
- IN UINT32 AdditionalHeaderSize
- )
- {
- UINT32 CalculatedSize;
- if (Image == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetAllHeaderSize() - Image is NULL.\n", mImageIdName));
- return 0;
- }
- CalculatedSize = sizeof (Image->MonotonicCount) +
- AdditionalHeaderSize +
- Image->AuthInfo.Hdr.dwLength;
- //
- // Check to make sure that operation can be safely performed.
- //
- if ((CalculatedSize < sizeof (Image->MonotonicCount)) ||
- (CalculatedSize < AdditionalHeaderSize) ||
- (CalculatedSize < Image->AuthInfo.Hdr.dwLength))
- {
- //
- // Integer overflow. Invalid image.
- //
- return 0;
- }
- return CalculatedSize;
- }
- /**
- 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.
- @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt status to report
- back to the ESRT table in case of error. If an error does not occur,
- this function will set the value to LAST_ATTEMPT_STATUS_SUCCESS.
- This function will return error codes that occur within this function
- implementation within a driver range of last attempt error codes from
- LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE_VALUE
- to LAST_ATTEMPT_STATUS_DRIVER_MAX_ERROR_CODE_VALUE.
- This function might also return error codes that occur within libraries
- linked against this module that return last attempt error codes such as:
- LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MIN_ERROR_CODE_VALUE to
- LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MAX_ERROR_CODE_VALUE
- LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MIN_ERROR_CODE_VALUE to
- LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MAX_ERROR_CODE_VALUE
- @retval EFI_SUCCESS The image was successfully checked.
- @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_VIOLATION The operation could not be performed due to an authentication failure.
- **/
- EFI_STATUS
- EFIAPI
- CheckTheImageInternal (
- IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
- IN UINT8 ImageIndex,
- IN CONST VOID *Image,
- IN UINTN ImageSize,
- OUT UINT32 *ImageUpdatable,
- OUT UINT32 *LastAttemptStatus
- )
- {
- EFI_STATUS Status;
- UINT32 LocalLastAttemptStatus;
- FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
- UINTN RawSize;
- VOID *FmpPayloadHeader;
- UINTN FmpPayloadSize;
- UINT32 Version;
- UINT32 FmpHeaderSize;
- UINTN AllHeaderSize;
- UINT32 Index;
- VOID *PublicKeyData;
- UINTN PublicKeyDataLength;
- UINT8 *PublicKeyDataXdr;
- UINT8 *PublicKeyDataXdrEnd;
- EFI_FIRMWARE_IMAGE_DEP *Dependencies;
- UINT32 DependenciesSize;
- Status = EFI_SUCCESS;
- LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
- RawSize = 0;
- FmpPayloadHeader = NULL;
- FmpPayloadSize = 0;
- Version = 0;
- FmpHeaderSize = 0;
- AllHeaderSize = 0;
- Dependencies = NULL;
- DependenciesSize = 0;
- if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
- return EFI_UNSUPPORTED;
- }
- if (LastAttemptStatus == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImageInternal() - LastAttemptStatus is NULL.\n", mImageIdName));
- Status = EFI_INVALID_PARAMETER;
- goto cleanup;
- }
- //
- // A last attempt status error code will always override the success
- // value before returning from the function
- //
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
- if (This == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - This is NULL.\n", mImageIdName));
- Status = EFI_INVALID_PARAMETER;
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;
- goto cleanup;
- }
- //
- // Retrieve the private context structure
- //
- Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
- FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
- //
- // Make sure the descriptor has already been loaded or refreshed
- //
- PopulateDescriptor (Private);
- if (ImageUpdatable == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName));
- Status = EFI_INVALID_PARAMETER;
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_UPDATABLE;
- goto cleanup;
- }
- //
- // Set to valid and then if any tests fail it will update this flag.
- //
- *ImageUpdatable = IMAGE_UPDATABLE_VALID;
- //
- // Set to satisfied and then if dependency evaluates to false it will update this flag.
- //
- Private->DependenciesSatisfied = TRUE;
- if (Image == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
- //
- // not sure if this is needed
- //
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROVIDED;
- return EFI_INVALID_PARAMETER;
- }
- PublicKeyDataXdr = PcdGetPtr (PcdFmpDevicePkcs7CertBufferXdr);
- PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);
- if ((PublicKeyDataXdr == NULL) || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName));
- Status = EFI_ABORTED;
- LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CERTIFICATE;
- } else {
- //
- // Try each key from PcdFmpDevicePkcs7CertBufferXdr
- //
- for (Index = 1; PublicKeyDataXdr < PublicKeyDataXdrEnd; Index++) {
- Index++;
- DEBUG (
- (DEBUG_INFO,
- "FmpDxe(%s): Certificate #%d [%p..%p].\n",
- mImageIdName,
- Index,
- PublicKeyDataXdr,
- PublicKeyDataXdrEnd
- )
- );
- if ((PublicKeyDataXdr + sizeof (UINT32)) > PublicKeyDataXdrEnd) {
- //
- // Key data extends beyond end of PCD
- //
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName));
- Status = EFI_ABORTED;
- LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH_VALUE;
- break;
- }
- //
- // Read key length stored in big-endian format
- //
- PublicKeyDataLength = SwapBytes32 (*(UINT32 *)(PublicKeyDataXdr));
- //
- // Point to the start of the key data
- //
- PublicKeyDataXdr += sizeof (UINT32);
- if (PublicKeyDataXdr + PublicKeyDataLength > PublicKeyDataXdrEnd) {
- //
- // Key data extends beyond end of PCD
- //
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName));
- Status = EFI_ABORTED;
- LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH;
- break;
- }
- PublicKeyData = PublicKeyDataXdr;
- Status = AuthenticateFmpImage (
- (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,
- ImageSize,
- PublicKeyData,
- PublicKeyDataLength
- );
- if (!EFI_ERROR (Status)) {
- break;
- }
- PublicKeyDataXdr += PublicKeyDataLength;
- PublicKeyDataXdr = (UINT8 *)ALIGN_POINTER (PublicKeyDataXdr, sizeof (UINT32));
- }
- }
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName, Status));
- if (LocalLastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {
- *LastAttemptStatus = LocalLastAttemptStatus;
- } else {
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_AUTH_FAILURE;
- }
- goto cleanup;
- }
- //
- // Check to make sure index is 1
- //
- if (ImageIndex != 1) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName));
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE;
- Status = EFI_INVALID_PARAMETER;
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_IMAGE_INDEX;
- goto cleanup;
- }
- //
- // Get the dependency from Image.
- //
- Dependencies = GetImageDependency (
- (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image,
- ImageSize,
- &DependenciesSize,
- LastAttemptStatus
- );
- if (*LastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {
- Status = EFI_ABORTED;
- goto cleanup;
- }
- //
- // Check the FmpPayloadHeader
- //
- FmpPayloadHeader = GetFmpHeader ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize);
- if (FmpPayloadHeader == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));
- Status = EFI_ABORTED;
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;
- goto cleanup;
- }
- Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
- Status = EFI_SUCCESS;
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_VERSION;
- goto cleanup;
- }
- //
- // Check the lowest supported version
- //
- if (Version < Private->Descriptor.LowestSupportedImageVersion) {
- DEBUG (
- (DEBUG_ERROR,
- "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",
- mImageIdName, Version, Private->Descriptor.LowestSupportedImageVersion)
- );
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;
- Status = EFI_SUCCESS;
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_VERSION_TOO_LOW;
- goto cleanup;
- }
- //
- // Evaluate dependency expression
- //
- Private->DependenciesSatisfied = CheckFmpDependency (
- Private->Descriptor.ImageTypeId,
- Version,
- Dependencies,
- DependenciesSize,
- &LocalLastAttemptStatus
- );
- if (!Private->DependenciesSatisfied) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed.\n", mImageIdName));
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
- Status = EFI_SUCCESS;
- *LastAttemptStatus = LocalLastAttemptStatus;
- goto cleanup;
- }
- //
- // Get the FmpHeaderSize so we can determine the real payload size
- //
- Status = GetFmpPayloadHeaderSize (FmpPayloadHeader, FmpPayloadSize, &FmpHeaderSize);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
- Status = EFI_SUCCESS;
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;
- goto cleanup;
- }
- //
- // Call FmpDevice Lib Check Image on the
- // Raw payload. So all headers need stripped off
- //
- AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);
- if (AllHeaderSize == 0) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName));
- Status = EFI_ABORTED;
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;
- goto cleanup;
- }
- RawSize = ImageSize - AllHeaderSize;
- //
- // FmpDeviceLib CheckImage function to do any specific checks
- //
- Status = FmpDeviceCheckImageWithStatus ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdatable, LastAttemptStatus);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName, Status));
- //
- // LastAttemptStatus returned from the device library should fall within the designated error range
- // [LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE, LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]
- //
- if ((*LastAttemptStatus < LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE) ||
- (*LastAttemptStatus > LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE))
- {
- DEBUG (
- (DEBUG_ERROR,
- "FmpDxe(%s): CheckTheImage() - LastAttemptStatus %d from FmpDeviceCheckImageWithStatus() is invalid.\n",
- mImageIdName,
- *LastAttemptStatus)
- );
- *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
- }
- }
- cleanup:
- 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_ABORTED The operation is aborted.
- @retval EFI_INVALID_PARAMETER The Image was NULL.
- @retval EFI_UNSUPPORTED The operation is not supported.
- @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
- **/
- EFI_STATUS
- EFIAPI
- CheckTheImage (
- IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
- IN UINT8 ImageIndex,
- IN CONST VOID *Image,
- IN UINTN ImageSize,
- OUT UINT32 *ImageUpdatable
- )
- {
- UINT32 LastAttemptStatus;
- return CheckTheImageInternal (This, ImageIndex, Image, ImageSize, ImageUpdatable, &LastAttemptStatus);
- }
- /**
- 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_VIOLATION The operation could not be performed due to an authentication failure.
- **/
- EFI_STATUS
- EFIAPI
- SetTheImage (
- 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;
- FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
- UINT32 Updateable;
- BOOLEAN BooleanValue;
- UINT32 FmpHeaderSize;
- VOID *FmpHeader;
- UINTN FmpPayloadSize;
- UINT32 AllHeaderSize;
- UINT32 IncomingFwVersion;
- UINT32 LastAttemptStatus;
- UINT32 Version;
- UINT32 LowestSupportedVersion;
- EFI_FIRMWARE_IMAGE_DEP *Dependencies;
- UINT32 DependenciesSize;
- Status = EFI_SUCCESS;
- Private = NULL;
- Updateable = 0;
- BooleanValue = FALSE;
- FmpHeaderSize = 0;
- FmpHeader = NULL;
- FmpPayloadSize = 0;
- AllHeaderSize = 0;
- IncomingFwVersion = 0;
- LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
- Dependencies = NULL;
- DependenciesSize = 0;
- if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
- return EFI_UNSUPPORTED;
- }
- if (This == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - This is NULL.\n", mImageIdName));
- Status = EFI_INVALID_PARAMETER;
- LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING;
- goto cleanup;
- }
- //
- // Retrieve the private context structure
- //
- Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
- FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
- //
- // Make sure the descriptor has already been loaded or refreshed
- //
- PopulateDescriptor (Private);
- //
- // Set to 0 to clear any previous results.
- //
- SetLastAttemptVersionInVariable (Private, IncomingFwVersion);
- //
- // if we have locked the device, then skip the set operation.
- // it should be blocked by hardware too but we can catch here even faster
- //
- if (Private->FmpDeviceLocked) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName));
- LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_DEVICE_LOCKED;
- Status = EFI_UNSUPPORTED;
- goto cleanup;
- }
- //
- // Call check image to verify the image
- //
- Status = CheckTheImageInternal (This, ImageIndex, Image, ImageSize, &Updateable, &LastAttemptStatus);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName, Status));
- goto cleanup;
- }
- //
- // Get the dependency from Image.
- //
- Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize, &LastAttemptStatus);
- //
- // No functional error in CheckTheImage. Attempt to get the Version to
- // support better error reporting.
- //
- FmpHeader = GetFmpHeader ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize);
- if (FmpHeader == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));
- LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER;
- Status = EFI_ABORTED;
- goto cleanup;
- }
- Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);
- if (!EFI_ERROR (Status)) {
- //
- // Set to actual value
- //
- SetLastAttemptVersionInVariable (Private, IncomingFwVersion);
- }
- if (Updateable != IMAGE_UPDATABLE_VALID) {
- DEBUG (
- (DEBUG_ERROR,
- "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",
- mImageIdName, Updateable)
- );
- if (Private->DependenciesSatisfied == FALSE) {
- LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;
- }
- Status = EFI_ABORTED;
- goto cleanup;
- }
- if (Progress == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName));
- LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROGRESS_CALLBACK_ERROR;
- Status = EFI_INVALID_PARAMETER;
- goto cleanup;
- }
- mProgressFunc = Progress;
- //
- // Checking the image is at least 1%
- //
- Status = Progress (1);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Progress Callback failed with Status %r.\n", mImageIdName, Status));
- }
- //
- // Check System Power
- //
- Status = CheckSystemPower (&BooleanValue);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName, Status));
- LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_POWER_API;
- goto cleanup;
- }
- if (!BooleanValue) {
- Status = EFI_ABORTED;
- DEBUG (
- (DEBUG_ERROR,
- "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n", mImageIdName)
- );
- LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT;
- goto cleanup;
- }
- Progress (2);
- //
- // Check System Thermal
- //
- Status = CheckSystemThermal (&BooleanValue);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName, Status));
- LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_THERMAL_API;
- goto cleanup;
- }
- if (!BooleanValue) {
- Status = EFI_ABORTED;
- LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_THERMAL;
- DEBUG (
- (DEBUG_ERROR,
- "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName)
- );
- goto cleanup;
- }
- Progress (3);
- //
- // Check System Environment
- //
- Status = CheckSystemEnvironment (&BooleanValue);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName, Status));
- LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_ENV_API;
- goto cleanup;
- }
- if (!BooleanValue) {
- Status = EFI_ABORTED;
- LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_SYSTEM_ENV;
- DEBUG (
- (DEBUG_ERROR,
- "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName)
- );
- goto cleanup;
- }
- Progress (4);
- //
- // Save LastAttemptStatus as error so that if SetImage never returns the error
- // state is recorded.
- //
- SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
- //
- // Strip off all the headers so the device can process its firmware
- //
- Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName, Status));
- LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE;
- goto cleanup;
- }
- AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);
- if (AllHeaderSize == 0) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName));
- LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE;
- Status = EFI_ABORTED;
- goto cleanup;
- }
- //
- // Indicate that control is handed off to FmpDeviceLib
- //
- Progress (5);
- //
- // Copy the requested image to the firmware using the FmpDeviceLib
- //
- Status = FmpDeviceSetImageWithStatus (
- (((UINT8 *)Image) + AllHeaderSize),
- ImageSize - AllHeaderSize,
- VendorCode,
- FmpDxeProgress,
- IncomingFwVersion,
- AbortReason,
- &LastAttemptStatus
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", mImageIdName, Status));
- //
- // LastAttemptStatus returned from the device library should fall within the designated error range
- // [LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE, LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]
- //
- if ((LastAttemptStatus < LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE) ||
- (LastAttemptStatus > LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE))
- {
- DEBUG (
- (DEBUG_ERROR,
- "FmpDxe(%s): SetTheImage() - LastAttemptStatus %d from FmpDeviceSetImageWithStatus() is invalid.\n",
- mImageIdName,
- LastAttemptStatus)
- );
- LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
- }
- goto cleanup;
- }
- //
- // Store the dependency
- //
- if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
- Status = SaveFmpDependency (Dependencies, DependenciesSize);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SaveFmpDependency from FmpDependencyCheckLib failed. (%r)\n", mImageIdName, Status));
- }
- Status = EFI_SUCCESS;
- }
- //
- // Finished the update without error
- // Indicate that control has been returned from FmpDeviceLib
- //
- Progress (99);
- //
- // Update the version stored in variable
- //
- if (!Private->RuntimeVersionSupported) {
- Version = DEFAULT_VERSION;
- GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);
- SetVersionInVariable (Private, Version);
- }
- //
- // Update lowest supported variable
- //
- LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
- GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);
- SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);
- LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
- cleanup:
- mProgressFunc = NULL;
- if (Private != NULL) {
- DEBUG ((DEBUG_INFO, "FmpDxe(%s): SetTheImage() LastAttemptStatus: %u.\n", mImageIdName, LastAttemptStatus));
- SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
- }
- if (Progress != NULL) {
- //
- // Set progress to 100 after everything is done including recording Status.
- //
- Progress (100);
- }
- //
- // Need repopulate after SetImage is called to
- // update LastAttemptVersion and LastAttemptStatus.
- //
- if (Private != NULL) {
- Private->DescriptorPopulated = FALSE;
- }
- return Status;
- }
- /**
- 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
- GetPackageInfo (
- 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_VIOLATION The operation could not be performed due to an authentication failure.
- **/
- EFI_STATUS
- EFIAPI
- SetPackageInfo (
- 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;
- }
- /**
- Event notification function that is invoked when the event GUID specified by
- PcdFmpDeviceLockEventGuid is signaled.
- @param[in] Event Event whose notification function is being invoked.
- @param[in] Context The pointer to the notification function's context,
- which is implementation-dependent.
- **/
- VOID
- EFIAPI
- FmpDxeLockEventNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- EFI_STATUS Status;
- FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
- if (Context == NULL) {
- ASSERT (Context != NULL);
- return;
- }
- Private = (FIRMWARE_MANAGEMENT_PRIVATE_DATA *)Context;
- if (!Private->FmpDeviceLocked) {
- //
- // Lock the firmware device
- //
- FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
- Status = FmpDeviceLock ();
- if (EFI_ERROR (Status)) {
- if (Status != EFI_UNSUPPORTED) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));
- } else {
- DEBUG ((DEBUG_WARN, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));
- }
- }
- Private->FmpDeviceLocked = TRUE;
- }
- }
- /**
- Function to install FMP instance.
- @param[in] Handle The device handle to install a FMP instance on.
- @retval EFI_SUCCESS FMP Installed
- @retval EFI_INVALID_PARAMETER Handle was invalid
- @retval other Error installing FMP
- **/
- EFI_STATUS
- EFIAPI
- InstallFmpInstance (
- IN EFI_HANDLE Handle
- )
- {
- EFI_STATUS Status;
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
- FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
- //
- // Only allow a single FMP Protocol instance to be installed
- //
- Status = gBS->OpenProtocol (
- Handle,
- &gEfiFirmwareManagementProtocolGuid,
- (VOID **)&Fmp,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- return EFI_ALREADY_STARTED;
- }
- //
- // Allocate FMP Protocol instance
- //
- Private = AllocateCopyPool (
- sizeof (mFirmwareManagementPrivateDataTemplate),
- &mFirmwareManagementPrivateDataTemplate
- );
- if (Private == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to allocate memory for private structure.\n", mImageIdName));
- Status = EFI_OUT_OF_RESOURCES;
- goto cleanup;
- }
- //
- // Initialize private context data structure
- //
- Private->Handle = Handle;
- Private->FmpDeviceContext = NULL;
- Status = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
- if (Status == EFI_UNSUPPORTED) {
- Private->FmpDeviceContext = NULL;
- } else if (EFI_ERROR (Status)) {
- goto cleanup;
- }
- //
- // Make sure the descriptor has already been loaded or refreshed
- //
- PopulateDescriptor (Private);
- if (IsLockFmpDeviceAtLockEventGuidRequired ()) {
- //
- // Register all UEFI Variables used by this module to be locked.
- //
- Status = LockAllFmpVariables (Private);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register variables to lock. Status = %r.\n", mImageIdName, Status));
- } else {
- DEBUG ((DEBUG_INFO, "FmpDxe(%s): All variables registered to lock\n", mImageIdName));
- }
- //
- // Create and register notify function to lock the FMP device.
- //
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- FmpDxeLockEventNotify,
- Private,
- mLockGuid,
- &Private->FmpDeviceLockEvent
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register notification. Status = %r\n", mImageIdName, Status));
- }
- ASSERT_EFI_ERROR (Status);
- } else {
- DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName));
- }
- //
- // Install FMP Protocol and FMP Progress Protocol
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &Private->Handle,
- &gEfiFirmwareManagementProtocolGuid,
- &Private->Fmp,
- &gEdkiiFirmwareManagementProgressProtocolGuid,
- &mFmpProgress,
- NULL
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName, Status));
- goto cleanup;
- }
- cleanup:
- if (EFI_ERROR (Status)) {
- if (Private != NULL) {
- if (Private->FmpDeviceLockEvent != NULL) {
- gBS->CloseEvent (Private->FmpDeviceLockEvent);
- }
- if (Private->Descriptor.VersionName != NULL) {
- FreePool (Private->Descriptor.VersionName);
- }
- if (Private->FmpDeviceContext != NULL) {
- FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
- }
- if (Private->VersionVariableName != NULL) {
- FreePool (Private->VersionVariableName);
- }
- if (Private->LsvVariableName != NULL) {
- FreePool (Private->LsvVariableName);
- }
- if (Private->LastAttemptStatusVariableName != NULL) {
- FreePool (Private->LastAttemptStatusVariableName);
- }
- if (Private->LastAttemptVersionVariableName != NULL) {
- FreePool (Private->LastAttemptVersionVariableName);
- }
- if (Private->FmpStateVariableName != NULL) {
- FreePool (Private->FmpStateVariableName);
- }
- FreePool (Private);
- }
- }
- return Status;
- }
- /**
- Function to uninstall FMP instance.
- @param[in] Handle The device handle to install a FMP instance on.
- @retval EFI_SUCCESS FMP Installed
- @retval EFI_INVALID_PARAMETER Handle was invalid
- @retval other Error installing FMP
- **/
- EFI_STATUS
- EFIAPI
- UninstallFmpInstance (
- IN EFI_HANDLE Handle
- )
- {
- EFI_STATUS Status;
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
- FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
- Status = gBS->OpenProtocol (
- Handle,
- &gEfiFirmwareManagementProtocolGuid,
- (VOID **)&Fmp,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol open error. Status = %r.\n", mImageIdName, Status));
- return Status;
- }
- Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (Fmp);
- FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
- if (Private->FmpDeviceLockEvent != NULL) {
- gBS->CloseEvent (Private->FmpDeviceLockEvent);
- }
- Status = gBS->UninstallMultipleProtocolInterfaces (
- Private->Handle,
- &gEfiFirmwareManagementProtocolGuid,
- &Private->Fmp,
- &gEdkiiFirmwareManagementProgressProtocolGuid,
- &mFmpProgress,
- NULL
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol uninstall error. Status = %r.\n", mImageIdName, Status));
- return Status;
- }
- if (Private->Descriptor.VersionName != NULL) {
- FreePool (Private->Descriptor.VersionName);
- }
- if (Private->FmpDeviceContext != NULL) {
- FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
- }
- if (Private->VersionVariableName != NULL) {
- FreePool (Private->VersionVariableName);
- }
- if (Private->LsvVariableName != NULL) {
- FreePool (Private->LsvVariableName);
- }
- if (Private->LastAttemptStatusVariableName != NULL) {
- FreePool (Private->LastAttemptStatusVariableName);
- }
- if (Private->LastAttemptVersionVariableName != NULL) {
- FreePool (Private->LastAttemptVersionVariableName);
- }
- if (Private->FmpStateVariableName != NULL) {
- FreePool (Private->FmpStateVariableName);
- }
- FreePool (Private);
- return EFI_SUCCESS;
- }
- /**
- Unloads the application and its installed protocol.
- @param ImageHandle Handle that identifies the image to be unloaded.
- @param SystemTable The system table.
- @retval EFI_SUCCESS The image has been unloaded.
- **/
- EFI_STATUS
- EFIAPI
- FmpDxeLibDestructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- if (mFmpSingleInstance) {
- return UninstallFmpInstance (ImageHandle);
- }
- return EFI_SUCCESS;
- }
- /**
- Main entry for this driver/library.
- @param[in] ImageHandle Image handle this driver.
- @param[in] SystemTable Pointer to SystemTable.
- **/
- EFI_STATUS
- EFIAPI
- FmpDxeEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- //
- // Verify that a new FILE_GUID value has been provided in the <Defines>
- // section of this module. The FILE_GUID is the ESRT GUID that must be
- // unique for each updatable firmware image.
- //
- if (CompareGuid (&mDefaultModuleFileGuid, &gEfiCallerIdGuid)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: Use of default FILE_GUID detected. FILE_GUID must be set to a unique value.\n"));
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
- }
- //
- // Get the ImageIdName value for the EFI_FIRMWARE_IMAGE_DESCRIPTOR from a PCD.
- //
- mImageIdName = (CHAR16 *)PcdGetPtr (PcdFmpDeviceImageIdName);
- if ((PcdGetSize (PcdFmpDeviceImageIdName) <= 2) || (mImageIdName[0] == 0)) {
- //
- // PcdFmpDeviceImageIdName must be set to a non-empty Unicode string
- //
- DEBUG ((DEBUG_ERROR, "FmpDxe(%g): PcdFmpDeviceImageIdName is an empty string.\n", &gEfiCallerIdGuid));
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
- }
- //
- // Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.
- //
- DetectTestKey ();
- //
- // Fill in FMP Progress Protocol fields for Version 1
- //
- mFmpProgress.Version = 1;
- mFmpProgress.ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);
- mFmpProgress.WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);
- // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.
- // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then
- // gEfiEndOfDxeEventGroupGuid is used.
- //
- mLockGuid = &gEfiEndOfDxeEventGroupGuid;
- if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {
- mLockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);
- }
- DEBUG ((DEBUG_INFO, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName, mLockGuid));
- //
- // Register with library the install function so if the library uses
- // UEFI driver model/driver binding protocol it can install FMP on its device handle
- // If library is simple lib that does not use driver binding then it should return
- // unsupported and this will install the FMP instance on the ImageHandle
- //
- Status = RegisterFmpInstaller (InstallFmpInstance);
- if (Status == EFI_UNSUPPORTED) {
- mFmpSingleInstance = TRUE;
- DEBUG ((DEBUG_INFO, "FmpDxe(%s): FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n", mImageIdName));
- Status = RegisterFmpUninstaller (UninstallFmpInstance);
- if (Status == EFI_UNSUPPORTED) {
- Status = InstallFmpInstance (ImageHandle);
- } else {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));
- Status = EFI_UNSUPPORTED;
- }
- } else if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib registration returned %r. No FMP installed.\n", mImageIdName, Status));
- } else {
- DEBUG ((
- DEBUG_INFO,
- "FmpDxe(%s): FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n",
- mImageIdName
- ));
- Status = RegisterFmpUninstaller (UninstallFmpInstance);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));
- }
- }
- return Status;
- }
|