123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986 |
- /** @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)) {
- // The image cannot be valid if an error occurred checking the image
- if (*ImageUpdatable == IMAGE_UPDATABLE_VALID) {
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
- }
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName, Status));
- }
- //
- // Only validate the library last attempt status code if the image is not updatable.
- // This specifically avoids converting LAST_ATTEMPT_STATUS_SUCCESS if it set for an updatable image.
- //
- if (*ImageUpdatable != IMAGE_UPDATABLE_VALID) {
- //
- // 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;
- }
|