Date   

Re: Tianocore community page on who we are - please review

Yao, Jiewen
 

Some other thought is about maintainer’s role definition:

 

The role of a maintainer is to:

  1. Maintainer assignments to packages and source file name patterns are provided in the "Maintainers.txt" file.
  2. Subscribe to the "edk2-bugs" mailing list https://edk2.groups.io/g/bugs, which propagates TianoCore Bugzilla https://bugzilla.tianocore.org/ actions via email. Keep a close eye on new issues reported for their assigned packages. Participate in triaging and analyzing bugs filed for their assigned packages.
  3. Responsible for reviewing patches and answering questions from contributors, on the edk2-devel mailing list https://edk2.groups.io/g/devel/.
  4. Responsible for coordinating patch review with co-maintainers and reviewers of the same package.
  5. Has push / merge access to the merge branch.
  6. Responsible for merging approved patches into the master branch.
  7. Follow the EDK II development process.

 

IMHO, the 1~4 need technical expertise, while 5~7 need process expertise.

Logically, the can be two separated roles and be done by two different persons.

A people who has strong technical expertise might NOT be the best person to do the integration, and vice versa. I hope we can let right person do right thing in right way.

For example, to avoid mistake during check in, 5~7 can be done by a role named “integrator”.

 

My dream is that check-in process is just one click button. But it seems we are still far from it…

 

My two cents.

 

Thank you

Yao Jiewen

 

From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Yao, Jiewen
Sent: Saturday, September 26, 2020 1:09 PM
To: devel@edk2.groups.io; Guptha, Soumya K <soumya.k.guptha@...>; announce@edk2.groups.io
Subject: Re: [edk2-devel] Tianocore community page on who we are - please review

 

Thanks Soumya. I think this is a good start.

 

Recently we are discussing the maintainer’s work in EDKII mailing list, with title “more development process failure”.

 

I feel the process mentioned in https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Development-Process is not clear enough to follow, especially for the maintainer who is not full time working on EDKII.

 

I wish we can have this opportunity to revisit the “Follow the EDK II development process” and make “the process” simpler and clearer.

 

Then all maintainers can sign to follow one rule. The rule we define and the rule we agree with.

 

Thank you

Yao Jiewen

 

 

From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Soumya Guptha
Sent: Saturday, September 26, 2020 6:35 AM
To: announce@edk2.groups.io; devel@edk2.groups.io
Subject: [edk2-devel] Tianocore community page on who we are - please review

 

Dear Community members,

 

I have drafted a document “who we are”, explaining Tianocore community structure, members of the community, their role and the current development process. I have drafted this document with the help of the Tianocore Stewards.

We view this as a living document, as our development processes evolve, I will keep this document updated.

 

Please review the draft version of the document (link below) and provide your feedback. Please send it to me, no need to reply all.

I appreciate your input by Friday, Oct 2. After this, I plan on make it live on our TianoCore wiki site.

 

Link: https://github.com/tianocore/tianocore.github.io/wiki/Who-we-are

 

Thanks,

Soumya

 

Soumya Guptha
TianoCore Community Manager

 


Re: Tianocore community page on who we are - please review

Yao, Jiewen
 

Thanks Soumya. I think this is a good start.

 

Recently we are discussing the maintainer’s work in EDKII mailing list, with title “more development process failure”.

 

I feel the process mentioned in https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Development-Process is not clear enough to follow, especially for the maintainer who is not full time working on EDKII.

 

I wish we can have this opportunity to revisit the “Follow the EDK II development process” and make “the process” simpler and clearer.

 

Then all maintainers can sign to follow one rule. The rule we define and the rule we agree with.

 

Thank you

Yao Jiewen

 

 

From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Soumya Guptha
Sent: Saturday, September 26, 2020 6:35 AM
To: announce@edk2.groups.io; devel@edk2.groups.io
Subject: [edk2-devel] Tianocore community page on who we are - please review

 

Dear Community members,

 

I have drafted a document “who we are”, explaining Tianocore community structure, members of the community, their role and the current development process. I have drafted this document with the help of the Tianocore Stewards.

We view this as a living document, as our development processes evolve, I will keep this document updated.

 

Please review the draft version of the document (link below) and provide your feedback. Please send it to me, no need to reply all.

I appreciate your input by Friday, Oct 2. After this, I plan on make it live on our TianoCore wiki site.

 

Link: https://github.com/tianocore/tianocore.github.io/wiki/Who-we-are

 

Thanks,

Soumya

 

Soumya Guptha
TianoCore Community Manager


 


Re: [EXTERNAL] [edk2-devel] ECC: Won't somebody PLEASE think of the... test structures.

Andrew Fish
 

Bret,

Details aside this ECC issue got me thinking it might be useful to some how tag code that follows different, subsetted, or alternate rules, or uses different build environments. I was kind of thinking of doing something like how we tag the licenses in the header comments [1]. I would say nothing means edk2 rules. I can see vendors maybe having different internal rules, or us wanting to distinguish test code from production code. The general idea if we start this tools can be smarter and that seems like a good thing. 

 This is just a wild idea, so I’d like to see what other people think?

[1] SPDX-License-Identifier: BSD-2-Clause-Patent

Thanks,

Andrew Fish

On Sep 24, 2020, at 7:57 PM, Bret Barkelew <Bret.Barkelew@...> wrote:

Andrew,
 
That’s actually what got me here. EccCheck runs as part of our CI now (but it didn’t when I wrote these tests a year ago). I need to either figure out how to get this code to pass EccCheck in a reasonable way, or just not contribute the tests and say “go to Mu for the tests, if you want them”.
 
Skipping the contribution isn’t a desirable outcome at all for a number of reasons, not the least of which is that we (MS and others) are trying encourage all contributions to come with tests, so the process of writing them needs to be simple and painless.
 
- Bret 
 
From: Andrew Fish
Sent: Thursday, September 24, 2020 7:48 PM
To: edk2-devel-groups-io; Bret Barkelew
Cc: Ken Taylor
Subject: [EXTERNAL] Re: [edk2-devel] ECC: Won't somebody PLEASE think of the... test structures.
 
Bret,
 
I’ve had this issue with EFI code too. It will compile with for DEBUG and RELEASE as the optimizer removes the memcpy/memset. So you only see a build failure when you compiler NOOPT (and there are no intrinsic libs). I mostly see this in platform code when I try to compile a single driver/lib NOOPT and it fails to link due to the missing intrinsic. 
 
The easy to enforce this is to compile with optimizations enabled and don’t enable intrinsic libs. Not sure if that is really practical from the test point of view. 
 
Seems the tool caught the coding style violation so I guess we could try to “make running that tool easier”. Maybe hooking into patchcheck.py, making some kind of githook, or adding a git command?  
 
Thanks,
 
Andrew Fish
 


On Sep 24, 2020, at 7:25 PM, Bret Barkelew via groups.io <bret.barkelew@...> wrote:
 
So for context, this is a new host-based test that should only run within a platform OS, so intrinsics aren’t the big deal that they would be in FW code.
 
But we do need to figure out how to simultaneously adhere to the coding convention while enabling test authoring.
Or we chose to not enforce quite as many things for tests.
 
I’d prefer the first. 
 
- Bret 
 
From: Ken Taylor
Sent: Thursday, September 24, 2020 6:57 PM
To: devel@edk2.groups.io; Bret Barkelew
Subject: [EXTERNAL] RE: ECC: Won't somebody PLEASE think of the... test structures.
 
If the structure is a non-static local variable, most compilers will silently inject an intrinsic call to memcpy in function initialization.  This leads to an intermittent linker error.
 
If the compiler you use automatically supports an intrinsic memcpy in the given architecture or optimizes out the memcpy, it will build for you and you won’t know you need to link to an intrinsic support library in order to build cross platform.  This leads to code that builds for you, but not for me.
 
Regards,
-Ken.
 
From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Bret Barkelew via groups.io
Sent: Thursday, September 24, 2020 6:23 PM
To: devel@edk2.groups.io
Subject: [edk2-devel] ECC: Won't somebody PLEASE think of the... test structures.
 
ERROR - EFI coding style error
ERROR - *Error code: 5007
ERROR - *There should be no initialization of a variable as part of its declaration
ERROR - *file: //home/corthon/_uefi/edk2_qemu_ci/edk2/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c
ERROR - *Line number: 333
ERROR - *Variable Name: MatchCheckPolicy
 
EccCheck no likey:
SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
    {
      VARIABLE_POLICY_ENTRY_REVISION,
      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
      sizeof(VARIABLE_POLICY_ENTRY),
      TEST_GUID_1,
      TEST_POLICY_MIN_SIZE_NULL,
      TEST_POLICY_MAX_SIZE_NULL,
      TEST_POLICY_ATTRIBUTES_NULL,
      TEST_POLICY_ATTRIBUTES_NULL,
      VARIABLE_POLICY_TYPE_NO_LOCK
    },
    TEST_VAR_1_NAME
  };
 
But you can’t init this structure separately without addressing each field.
Can a brother get an override?
 
- Bret 
 
 
<95B370A7BEED49AAB797022E8F260C8F.png>
 
 


[PATCH v4 6/6] FmpDevicePkg/FmpDeviceLib: Add Last Attempt Status to Check/Set API

Michael Kubacki
 

From: Michael Kubacki <michael.kubacki@...>

Provides the ability for a given FMP device library instance to
return a Last Attempt Status code during check image and set image
operations with FmpDeviceCheckImageEx() and FmpDeviceSetImageEx().

Cc: Liming Gao <gaoliming@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Guomin Jiang <guomin.jiang@...>
Cc: Wei6 Xu <wei6.xu@...>
Signed-off-by: Michael Kubacki <michael.kubacki@...>
---
FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLib.c | 132 +++++++++++++++++++-
FmpDevicePkg/Include/Library/FmpDeviceLib.h | 121 +++++++++++++++++-
2 files changed, 251 insertions(+), 2 deletions(-)

diff --git a/FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLib.c b/FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLib.c
index 316de12e910c..4e1ce8bf2294 100644
--- a/FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLib.c
+++ b/FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLib.c
@@ -2,7 +2,7 @@
Provides firmware device specific services to support updates of a firmware
image stored in a firmware device.

- Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -10,6 +10,7 @@
**/

#include <PiDxe.h>
+#include <Guid/SystemResourceTable.h>
#include <Library/FmpDeviceLib.h>

/**
@@ -410,6 +411,55 @@ FmpDeviceCheckImage (
return EFI_SUCCESS;
}

+/**
+ Checks if a new firmware image is valid for the firmware device. This
+ function allows firmware update operation to validate the firmware image
+ before FmpDeviceSetImage() is called.
+
+ @param[in] Image Points to a new firmware image.
+ @param[in] ImageSize Size, in bytes, of a new firmware image.
+ @param[out] ImageUpdatable Indicates if a new firmware image is valid for
+ a firmware update to the firmware device. The
+ following values from the Firmware Management
+ Protocol are supported:
+ IMAGE_UPDATABLE_VALID
+ IMAGE_UPDATABLE_INVALID
+ IMAGE_UPDATABLE_INVALID_TYPE
+ IMAGE_UPDATABLE_INVALID_OLD
+ IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE
+ @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. This value will only be checked when this
+ function returns an error.
+
+ The return status code must fall in the range of
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
+
+ If the value falls outside this range, it will be converted
+ to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
+
+ @retval EFI_SUCCESS The image was successfully checked. Additional
+ status information is returned in
+ ImageUpdatable.
+ @retval EFI_INVALID_PARAMETER Image is NULL.
+ @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpDeviceCheckImageWithStatus (
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *ImageUpdatable,
+ OUT UINT32 *LastAttemptStatus
+ )
+{
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+
+ return EFI_SUCCESS;
+}
+
/**
Updates a firmware device with a new firmware image. This function returns
EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image
@@ -476,6 +526,86 @@ FmpDeviceSetImage (
return EFI_UNSUPPORTED;
}

+/**
+ Updates a firmware device with a 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 that the image is a supported image for this firmware device.
+ Return EFI_ABORTED if the image is not supported. Additional details
+ on why the image is not a supported image may be returned in AbortReason.
+ - Validate the data from VendorCode if is not NULL. Firmware image
+ validation must be performed before VendorCode data validation.
+ VendorCode data is ignored or considered invalid if image validation
+ fails. Return EFI_ABORTED if the VendorCode 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] Image Points to the new firmware image.
+ @param[in] ImageSize Size, in bytes, of the new firmware image.
+ @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 to report the progress of
+ updating the firmware device with the new
+ firmware image.
+ @param[in] CapsuleFwVersion The version of the new firmware image from the
+ update capsule that provided the new firmware
+ image.
+ @param[out] AbortReason A pointer to a pointer to a Null-terminated
+ Unicode string providing more details on an
+ aborted operation. The buffer is allocated by
+ this function with
+ EFI_BOOT_SERVICES.AllocatePool(). It is the
+ caller's responsibility to free this buffer with
+ EFI_BOOT_SERVICES.FreePool().
+ @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. This value will only be checked when this
+ function returns an error.
+
+ The return status code must fall in the range of
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
+
+ If the value falls outside this range, it will be converted
+ to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
+
+ @retval EFI_SUCCESS The firmware device was successfully updated
+ with the new firmware image.
+ @retval EFI_ABORTED The operation is aborted. Additional details
+ are provided in AbortReason.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpDeviceSetImageWithStatus (
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ IN CONST VOID *VendorCode, OPTIONAL
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL
+ IN UINT32 CapsuleFwVersion,
+ OUT CHAR16 **AbortReason,
+ OUT UINT32 *LastAttemptStatus
+ )
+{
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+
+ return EFI_UNSUPPORTED;
+}
+
/**
Lock the firmware device that contains a firmware image. Once a firmware
device is locked, any attempts to modify the firmware image contents in the
diff --git a/FmpDevicePkg/Include/Library/FmpDeviceLib.h b/FmpDevicePkg/Include/Library/FmpDeviceLib.h
index 9a89f5c2eec5..6abd99fa1f47 100644
--- a/FmpDevicePkg/Include/Library/FmpDeviceLib.h
+++ b/FmpDevicePkg/Include/Library/FmpDeviceLib.h
@@ -2,7 +2,7 @@
Provides firmware device specific services to support updates of a firmware
image stored in a firmware device.

- Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -403,6 +403,50 @@ FmpDeviceCheckImage (
OUT UINT32 *ImageUpdatable
);

+/**
+ Checks if a new firmware image is valid for the firmware device. This
+ function allows firmware update operation to validate the firmware image
+ before FmpDeviceSetImage() is called.
+
+ @param[in] Image Points to a new firmware image.
+ @param[in] ImageSize Size, in bytes, of a new firmware image.
+ @param[out] ImageUpdatable Indicates if a new firmware image is valid for
+ a firmware update to the firmware device. The
+ following values from the Firmware Management
+ Protocol are supported:
+ IMAGE_UPDATABLE_VALID
+ IMAGE_UPDATABLE_INVALID
+ IMAGE_UPDATABLE_INVALID_TYPE
+ IMAGE_UPDATABLE_INVALID_OLD
+ IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE
+ @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. This value will only be checked when this
+ function returns an error.
+
+ The return status code must fall in the range of
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
+
+ If the value falls outside this range, it will be converted
+ to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
+
+ @retval EFI_SUCCESS The image was successfully checked. Additional
+ status information is returned in
+ ImageUpdatable.
+ @retval EFI_INVALID_PARAMETER Image is NULL.
+ @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpDeviceCheckImageWithStatus (
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *ImageUpdatable,
+ OUT UINT32 *LastAttemptStatus
+ );
+
/**
Updates a firmware device with a new firmware image. This function returns
EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image
@@ -466,6 +510,81 @@ FmpDeviceSetImage (
OUT CHAR16 **AbortReason
);

+/**
+ Updates a firmware device with a 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 that the image is a supported image for this firmware device.
+ Return EFI_ABORTED if the image is not supported. Additional details
+ on why the image is not a supported image may be returned in AbortReason.
+ - Validate the data from VendorCode if is not NULL. Firmware image
+ validation must be performed before VendorCode data validation.
+ VendorCode data is ignored or considered invalid if image validation
+ fails. Return EFI_ABORTED if the VendorCode 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] Image Points to the new firmware image.
+ @param[in] ImageSize Size, in bytes, of the new firmware image.
+ @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 to report the progress of
+ updating the firmware device with the new
+ firmware image.
+ @param[in] CapsuleFwVersion The version of the new firmware image from the
+ update capsule that provided the new firmware
+ image.
+ @param[out] AbortReason A pointer to a pointer to a Null-terminated
+ Unicode string providing more details on an
+ aborted operation. The buffer is allocated by
+ this function with
+ EFI_BOOT_SERVICES.AllocatePool(). It is the
+ caller's responsibility to free this buffer with
+ EFI_BOOT_SERVICES.FreePool().
+ @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. This value will only be checked when this
+ function returns an error.
+
+ The return status code must fall in the range of
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
+ LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
+
+ If the value falls outside this range, it will be converted
+ to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
+
+ @retval EFI_SUCCESS The firmware device was successfully updated
+ with the new firmware image.
+ @retval EFI_ABORTED The operation is aborted. Additional details
+ are provided in AbortReason.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpDeviceSetImageWithStatus (
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ IN CONST VOID *VendorCode, OPTIONAL
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL
+ IN UINT32 CapsuleFwVersion,
+ OUT CHAR16 **AbortReason,
+ OUT UINT32 *LastAttemptStatus
+ );
+
/**
Lock the firmware device that contains a firmware image. Once a firmware
device is locked, any attempts to modify the firmware image contents in the
--
2.28.0.windows.1


[PATCH v4 5/6] FmpDevicePkg: Add Last Attempt Status support to dependency libs

Michael Kubacki
 

From: Michael Kubacki <michael.kubacki@...>

The FMP dependency libraries are leveraged during firmware update
to check for dependencies required to update the image.

This change adds granular Last Attempt Status code support to these
services so failures can be more easily observed during the firmware
update process via Last Attempt Status codes.

Cc: Liming Gao <gaoliming@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Guomin Jiang <guomin.jiang@...>
Cc: Wei6 Xu <wei6.xu@...>
Signed-off-by: Michael Kubacki <michael.kubacki@...>
---
FmpDevicePkg/FmpDxe/FmpDxe.c | 31 ++++++-
FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c | 39 +++++---
FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c | 14 ++-
FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c | 93 +++++++++++++++++---
FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c | 7 +-
FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h | 8 +-
FmpDevicePkg/Include/Library/FmpDependencyLib.h | 44 +++++----
7 files changed, 189 insertions(+), 47 deletions(-)

diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c
index 68aacc518a40..843ecbd78b58 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.c
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.c
@@ -730,6 +730,15 @@ GetAllHeaderSize (
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.
@@ -925,7 +934,16 @@ CheckTheImageInternal (
//
// Get the dependency from Image.
//
- Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);
+ Dependencies = GetImageDependency (
+ (EFI_FIRMWARE_IMAGE_AUTHENTICATION *) Image,
+ ImageSize,
+ &DependenciesSize,
+ LastAttemptStatus
+ );
+ if (*LastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {
+ Status = EFI_ABORTED;
+ goto cleanup;
+ }

//
// Check the FmpPayloadHeader
@@ -964,11 +982,18 @@ CheckTheImageInternal (
//
// Evaluate dependency expression
//
- Private->DependenciesSatisfied = CheckFmpDependency (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize);
+ 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;
}

@@ -1181,7 +1206,7 @@ SetTheImage (
//
// Get the dependency from Image.
//
- Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);
+ Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize, &LastAttemptStatus);

//
// No functional error in CheckTheImage. Attempt to get the Version to
diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c b/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c
index 02ed600e0e95..cca83dbe4a14 100644
--- a/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c
+++ b/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c
@@ -17,6 +17,9 @@
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Guid/SystemResourceTable.h>
+#include <LastAttemptStatus.h>
+#include <FmpLastAttemptStatus.h>

/**
Check dependency for firmware update.
@@ -25,6 +28,10 @@
@param[in] Version New version.
@param[in] Dependencies Fmp dependency.
@param[in] DependenciesSize Size, in bytes, of the Fmp dependency.
+ @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds the
+ last attempt status to report back to the caller.
+ This function will set the value to LAST_ATTEMPT_STATUS_SUCCESS
+ if an error code is not set.

@retval TRUE Dependencies are satisfied.
@retval FALSE Dependencies are unsatisfied or dependency check fails.
@@ -36,7 +43,8 @@ CheckFmpDependency (
IN EFI_GUID ImageTypeId,
IN UINT32 Version,
IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL
- IN UINT32 DependenciesSize
+ IN UINT32 DependenciesSize,
+ OUT UINT32 *LastAttemptStatus OPTIONAL
)
{
EFI_STATUS Status;
@@ -44,6 +52,7 @@ CheckFmpDependency (
UINTN Index;
EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
UINTN ImageInfoSize;
+ UINT32 LocalLastAttemptStatus;
UINT32 *DescriptorVer;
UINT8 FmpImageInfoCount;
UINTN *DescriptorSize;
@@ -55,14 +64,15 @@ CheckFmpDependency (
UINTN FmpVersionsCount;
BOOLEAN IsSatisfied;

- FmpImageInfoBuf = NULL;
- DescriptorVer = NULL;
- DescriptorSize = NULL;
- NumberOfFmpInstance = 0;
- FmpVersions = NULL;
- FmpVersionsCount = 0;
- IsSatisfied = TRUE;
- PackageVersionName = NULL;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ FmpImageInfoBuf = NULL;
+ DescriptorVer = NULL;
+ DescriptorSize = NULL;
+ NumberOfFmpInstance = 0;
+ FmpVersions = NULL;
+ FmpVersionsCount = 0;
+ IsSatisfied = TRUE;
+ PackageVersionName = NULL;

//
// Get ImageDescriptors of all FMP instances, and archive them for dependency evaluation.
@@ -77,30 +87,35 @@ CheckFmpDependency (
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "CheckFmpDependency: Get Firmware Management Protocol failed. (%r)", Status));
IsSatisfied = FALSE;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_FMP_PROTOCOL_NOT_FOUND;
goto cleanup;
}

FmpImageInfoBuf = AllocateZeroPool (sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * NumberOfFmpInstance);
if (FmpImageInfoBuf == NULL) {
IsSatisfied = FALSE;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_FMP_INFO_BUFFER_FAILED;
goto cleanup;
}

DescriptorVer = AllocateZeroPool (sizeof(UINT32) * NumberOfFmpInstance);
if (DescriptorVer == NULL ) {
IsSatisfied = FALSE;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_DESC_VER_BUFFER_FAILED;
goto cleanup;
}

DescriptorSize = AllocateZeroPool (sizeof(UINTN) * NumberOfFmpInstance);
if (DescriptorSize == NULL ) {
IsSatisfied = FALSE;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_DESC_SIZE_BUFFER_FAILED;
goto cleanup;
}

FmpVersions = AllocateZeroPool (sizeof(FMP_DEPEX_CHECK_VERSION_DATA) * NumberOfFmpInstance);
if (FmpVersions == NULL) {
IsSatisfied = FALSE;
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_FMP_VER_BUFFER_FAILED;
goto cleanup;
}

@@ -164,7 +179,7 @@ CheckFmpDependency (
// Evaluate firmware image's depex, against the version of other Fmp instances.
//
if (Dependencies != NULL) {
- IsSatisfied = EvaluateDependency (Dependencies, DependenciesSize, FmpVersions, FmpVersionsCount);
+ IsSatisfied = EvaluateDependency (Dependencies, DependenciesSize, FmpVersions, FmpVersionsCount, &LocalLastAttemptStatus);
}

if (!IsSatisfied) {
@@ -194,5 +209,9 @@ CheckFmpDependency (
FreePool (FmpVersions);
}

+ if (LastAttemptStatus != NULL) {
+ *LastAttemptStatus = LocalLastAttemptStatus;
+ }
+
return IsSatisfied;
}
diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c
index 55e9af22909d..160c44e738d5 100644
--- a/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c
+++ b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c
@@ -1,12 +1,14 @@
/** @file
Null instance of FmpDependencyCheckLib.

+ Copyright (c) Microsoft Corporation.<BR>
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

**/
#include <PiDxe.h>
+#include <Guid/SystemResourceTable.h>
#include <Library/FmpDependencyCheckLib.h>

/**
@@ -16,7 +18,10 @@
@param[in] Version New version.
@param[in] Dependencies Fmp dependency.
@param[in] DependenciesSize Size, in bytes, of the Fmp dependency.
-
+ @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds the
+ last attempt status to report back to the caller.
+ This function will set the value to LAST_ATTEMPT_STATUS_SUCCESS
+ if an error code is not set.
@retval TRUE Dependencies are satisfied.
@retval FALSE Dependencies are unsatisfied or dependency check fails.

@@ -27,8 +32,13 @@ CheckFmpDependency (
IN EFI_GUID ImageTypeId,
IN UINT32 Version,
IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL
- IN UINT32 DependenciesSize
+ IN UINT32 DependenciesSize,
+ OUT UINT32 *LastAttemptStatus OPTIONAL
)
{
+ if (LastAttemptStatus != NULL) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+ }
+
return TRUE;
}
diff --git a/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c
index 5ef25d2415cf..b222ace6d6ca 100644
--- a/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c
+++ b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c
@@ -13,6 +13,9 @@
#include <Library/DebugLib.h>
#include <Library/FmpDependencyLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Guid/SystemResourceTable.h>
+#include <LastAttemptStatus.h>
+#include <FmpLastAttemptStatus.h>

//
// Define the initial size of the dependency expression evaluation stack
@@ -203,6 +206,10 @@ Pop (
parameter is optional and can be set to NULL.
@param[in] FmpVersionsCount Element count of the array. When FmpVersions
is NULL, FmpVersionsCount must be 0.
+ @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds the
+ last attempt status to report back to the caller.
+ This function will set the value to LAST_ATTEMPT_STATUS_SUCCESS
+ if an error code is not set.

@retval TRUE Dependency expressions evaluate to TRUE.
@retval FALSE Dependency expressions evaluate to FALSE.
@@ -211,10 +218,11 @@ Pop (
BOOLEAN
EFIAPI
EvaluateDependency (
- IN EFI_FIRMWARE_IMAGE_DEP *Dependencies,
- IN UINTN DependenciesSize,
- IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions OPTIONAL,
- IN UINTN FmpVersionsCount
+ IN EFI_FIRMWARE_IMAGE_DEP *Dependencies,
+ IN UINTN DependenciesSize,
+ IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions, OPTIONAL
+ IN UINTN FmpVersionsCount,
+ OUT UINT32 *LastAttemptStatus OPTIONAL
)
{
EFI_STATUS Status;
@@ -224,6 +232,9 @@ EvaluateDependency (
DEPEX_ELEMENT Element2;
GUID ImageTypeId;
UINT32 Version;
+ UINT32 LocalLastAttemptStatus;
+
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;

//
// Check if parameter is valid.
@@ -249,6 +260,7 @@ EvaluateDependency (
case EFI_FMP_DEP_PUSH_GUID:
if (Iterator + sizeof (EFI_GUID) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize) {
DEBUG ((DEBUG_ERROR, "EvaluateDependency: GUID extends beyond end of dependency expression!\n"));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GUID_BEYOND_DEPEX;
goto Error;
}

@@ -259,6 +271,7 @@ EvaluateDependency (
if(CompareGuid (&FmpVersions[Index].ImageTypeId, &ImageTypeId)){
Status = Push (FmpVersions[Index].Version, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
@@ -266,18 +279,21 @@ EvaluateDependency (
}
if (Index == FmpVersionsCount) {
DEBUG ((DEBUG_ERROR, "EvaluateDependency: %g is not found!\n", &ImageTypeId));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_FMP_NOT_FOUND;
goto Error;
}
break;
case EFI_FMP_DEP_PUSH_VERSION:
if (Iterator + sizeof (UINT32) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize ) {
DEBUG ((DEBUG_ERROR, "EvaluateDependency: VERSION extends beyond end of dependency expression!\n"));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_BEYOND_DEPEX;
goto Error;
}

Version = *(UINT32 *) (Iterator + 1);
Status = Push (Version, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
Iterator = Iterator + sizeof (UINT32);
@@ -286,154 +302,191 @@ EvaluateDependency (
Iterator += AsciiStrnLenS ((CHAR8 *) Iterator, DependenciesSize - (Iterator - Dependencies->Dependencies));
if (Iterator == (UINT8 *) Dependencies->Dependencies + DependenciesSize) {
DEBUG ((DEBUG_ERROR, "EvaluateDependency: STRING extends beyond end of dependency expression!\n"));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_STR_BEYOND_DEPEX;
goto Error;
}
break;
case EFI_FMP_DEP_AND:
Status = Pop (&Element1, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Push (Element1.Value.Boolean & Element2.Value.Boolean, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_OR:
Status = Pop (&Element1, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop(&Element2, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Push (Element1.Value.Boolean | Element2.Value.Boolean, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_NOT:
Status = Pop (&Element1, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Push (!(Element1.Value.Boolean), BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_TRUE:
Status = Push (TRUE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_FALSE:
Status = Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_EQ:
Status = Pop (&Element1, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = (Element1.Value.Version == Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_GT:
Status = Pop (&Element1, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = (Element1.Value.Version > Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_GTE:
Status = Pop (&Element1, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = (Element1.Value.Version >= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_LT:
Status = Pop (&Element1, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus= LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = (Element1.Value.Version < Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_LTE:
Status = Pop (&Element1, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = Pop (&Element2, VersionType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
Status = (Element1.Value.Version <= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE;
goto Error;
}
break;
case EFI_FMP_DEP_END:
Status = Pop (&Element1, BooleanType);
if (EFI_ERROR (Status)) {
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE;
goto Error;
}
return Element1.Value.Boolean;
default:
DEBUG ((DEBUG_ERROR, "EvaluateDependency: Unknown Opcode - %02x!\n", *Iterator));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_UNKNOWN_OPCODE;
goto Error;
}
Iterator++;
}

DEBUG ((DEBUG_ERROR, "EvaluateDependency: No EFI_FMP_DEP_END Opcode in expression!\n"));
+ LocalLastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_END_OPCODE;

Error:
+ if (LastAttemptStatus != NULL) {
+ *LastAttemptStatus = LocalLastAttemptStatus;
+ }
+
return FALSE;
}

/**
Validate the dependency expression and output its size.

- @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP.
- @param[in] MaxDepexSize Max size of the dependency.
- @param[out] DepexSize Size of dependency.
+ @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP.
+ @param[in] MaxDepexSize Max size of the dependency.
+ @param[out] DepexSize Size of dependency.
+ @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds the
+ last attempt status to report back to the caller.
+ If a last attempt status error code is not returned,
+ this function will not modify the LastAttemptStatus value.

@retval TRUE The dependency expression is valid.
@retval FALSE The dependency expression is invalid.
@@ -444,7 +497,8 @@ EFIAPI
ValidateDependency (
IN EFI_FIRMWARE_IMAGE_DEP *Dependencies,
IN UINTN MaxDepexSize,
- OUT UINT32 *DepexSize
+ OUT UINT32 *DepexSize,
+ OUT UINT32 *LastAttemptStatus OPTIONAL
)
{
UINT8 *Depex;
@@ -493,16 +547,23 @@ ValidateDependency (
}
}

+ if (LastAttemptStatus != NULL) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_END_OPCODE;
+ }
+
return FALSE;
}

/**
Get dependency from firmware image.

- @param[in] Image Points to the firmware image.
- @param[in] ImageSize Size, in bytes, of the firmware image.
- @param[out] DepexSize Size, in bytes, of the dependency.
-
+ @param[in] Image Points to the firmware image.
+ @param[in] ImageSize Size, in bytes, of the firmware image.
+ @param[out] DepexSize Size, in bytes, of the dependency.
+ @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds the
+ last attempt status to report back to the caller.
+ If a last attempt status error code is not returned,
+ this function will not modify the LastAttemptStatus value.
@retval The pointer to dependency.
@retval Null

@@ -512,7 +573,8 @@ EFIAPI
GetImageDependency (
IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
IN UINTN ImageSize,
- OUT UINT32 *DepexSize
+ OUT UINT32 *DepexSize,
+ OUT UINT32 *LastAttemptStatus OPTIONAL
)
{
EFI_FIRMWARE_IMAGE_DEP *Depex;
@@ -530,6 +592,9 @@ GetImageDependency (
//
// Pointer overflow. Invalid image.
//
+ if (LastAttemptStatus != NULL) {
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GET_DEPEX_FAILURE;
+ }
return NULL;
}

@@ -539,7 +604,7 @@ GetImageDependency (
//
// Validate the dependency and get the size of dependency
//
- if (ValidateDependency (Depex, MaxDepexSize, DepexSize)) {
+ if (ValidateDependency (Depex, MaxDepexSize, DepexSize, LastAttemptStatus)) {
return Depex;
}

diff --git a/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c
index f8ccdd906f29..92a1ac815d51 100644
--- a/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c
+++ b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c
@@ -1,6 +1,7 @@
/** @file
Unit tests of EvaluateDependency API in FmpDependencyLib.

+ Copyright (c) Microsoft Corporation.<BR>
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -162,6 +163,7 @@ EvaluateDependencyTest (
{
BASIC_TEST_CONTEXT *TestContext;
BOOLEAN EvaluationResult;
+ UINT32 LastAttemptStatus;

TestContext = (BASIC_TEST_CONTEXT *)Context;

@@ -169,8 +171,9 @@ EvaluateDependencyTest (
(EFI_FIRMWARE_IMAGE_DEP *)TestContext->Dependencies,
TestContext->DependenciesSize,
mFmpVersions,
- sizeof(mFmpVersions)/sizeof(FMP_DEPEX_CHECK_VERSION_DATA)
- );
+ sizeof(mFmpVersions)/sizeof(FMP_DEPEX_CHECK_VERSION_DATA),
+ &LastAttemptStatus
+ );

UT_ASSERT_EQUAL (EvaluationResult, TestContext->ExpectedResult);

diff --git a/FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h b/FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h
index ec380c4947bd..785bda9401e6 100644
--- a/FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h
+++ b/FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h
@@ -2,6 +2,7 @@
Fmp Capsule Dependency check functions for Firmware Management Protocol based
firmware updates.

+ Copyright (c) Microsoft Corporation.<BR>
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -21,6 +22,10 @@
@param[in] Version New version.
@param[in] Dependencies Fmp dependency.
@param[in] DependenciesSize Size, in bytes, of the Fmp dependency.
+ @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds the
+ last attempt status to report back to the caller.
+ This function will set the value to LAST_ATTEMPT_STATUS_SUCCESS
+ if an error code is not set.

@retval TRUE Dependencies are satisfied.
@retval FALSE Dependencies are unsatisfied or dependency check fails.
@@ -32,7 +37,8 @@ CheckFmpDependency (
IN EFI_GUID ImageTypeId,
IN UINT32 Version,
IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL
- IN UINT32 DependenciesSize
+ IN UINT32 DependenciesSize,
+ OUT UINT32 *LastAttemptStatus OPTIONAL
);

#endif
diff --git a/FmpDevicePkg/Include/Library/FmpDependencyLib.h b/FmpDevicePkg/Include/Library/FmpDependencyLib.h
index c732903425b4..f460f0f07882 100644
--- a/FmpDevicePkg/Include/Library/FmpDependencyLib.h
+++ b/FmpDevicePkg/Include/Library/FmpDependencyLib.h
@@ -26,9 +26,13 @@ typedef struct {
/**
Validate the dependency expression and output its size.

- @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP.
- @param[in] MaxDepexSize Max size of the dependency.
- @param[out] DepexSize Size of dependency.
+ @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP.
+ @param[in] MaxDepexSize Max size of the dependency.
+ @param[out] DepexSize Size of dependency.
+ @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds the
+ last attempt status to report back to the caller.
+ If a last attempt status error code is not returned,
+ this function will not modify the LastAttemptStatus value.

@retval TRUE The dependency expression is valid.
@retval FALSE The dependency expression is invalid.
@@ -39,16 +43,20 @@ EFIAPI
ValidateDependency (
IN EFI_FIRMWARE_IMAGE_DEP *Dependencies,
IN UINTN MaxDepexSize,
- OUT UINT32 *DepexSize
+ OUT UINT32 *DepexSize,
+ OUT UINT32 *LastAttemptStatus OPTIONAL
);

/**
Get dependency from firmware image.

- @param[in] Image Points to the firmware image.
- @param[in] ImageSize Size, in bytes, of the firmware image.
- @param[out] DepexSize Size, in bytes, of the dependency.
-
+ @param[in] Image Points to the firmware image.
+ @param[in] ImageSize Size, in bytes, of the firmware image.
+ @param[out] DepexSize Size, in bytes, of the dependency.
+ @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds the
+ last attempt status to report back to the caller.
+ If a last attempt status error code is not returned,
+ this function will not modify the LastAttemptStatus value.
@retval The pointer to dependency.
@retval Null

@@ -56,9 +64,10 @@ ValidateDependency (
EFI_FIRMWARE_IMAGE_DEP*
EFIAPI
GetImageDependency (
- IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
- IN UINTN ImageSize,
- OUT UINT32 *DepexSize
+ IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *DepexSize,
+ OUT UINT32 *LastAttemptStatus OPTIONAL
);

/**
@@ -73,6 +82,10 @@ GetImageDependency (
parameter is optional and can be set to NULL.
@param[in] FmpVersionsCount Element count of the array. When FmpVersions
is NULL, FmpVersionsCount must be 0.
+ @param[out] LastAttemptStatus An optional pointer to a UINT32 that holds the
+ last attempt status to report back to the caller.
+ This function will set the value to LAST_ATTEMPT_STATUS_SUCCESS
+ if an error code is not set.

@retval TRUE Dependency expressions evaluate to TRUE.
@retval FALSE Dependency expressions evaluate to FALSE.
@@ -81,10 +94,11 @@ GetImageDependency (
BOOLEAN
EFIAPI
EvaluateDependency (
- IN EFI_FIRMWARE_IMAGE_DEP *Dependencies,
- IN UINTN DependenciesSize,
- IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions OPTIONAL,
- IN UINTN FmpVersionsCount
+ IN EFI_FIRMWARE_IMAGE_DEP *Dependencies,
+ IN UINTN DependenciesSize,
+ IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions, OPTIONAL
+ IN UINTN FmpVersionsCount,
+ OUT UINT32 *LastAttemptStatus OPTIONAL
);

#endif
--
2.28.0.windows.1


[PATCH v4 4/6] FmpDevicePkg/FmpDxe: Improve set image path Last Attempt Status granularity

Michael Kubacki
 

From: Michael Kubacki <michael.kubacki@...>

Increases the level of granularity for Last Attempt Status codes
returned from SetTheImage() in FmpDxe. This allows better
identification of the error that occurred in the set image
operation using Last Attempt Status codes.

Cc: Liming Gao <gaoliming@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Guomin Jiang <guomin.jiang@...>
Cc: Wei6 Xu <wei6.xu@...>
Signed-off-by: Michael Kubacki <michael.kubacki@...>
---
FmpDevicePkg/FmpDxe/FmpDxe.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c
index 858cffd8e5bd..68aacc518a40 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.c
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.c
@@ -1138,6 +1138,7 @@ SetTheImage (
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;
}

@@ -1163,6 +1164,7 @@ SetTheImage (
//
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;
}
@@ -1170,12 +1172,9 @@ SetTheImage (
//
// Call check image to verify the image
//
- Status = CheckTheImage (This, ImageIndex, Image, ImageSize, &Updateable);
+ 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));
- if (Status == EFI_SECURITY_VIOLATION) {
- LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
- }
goto cleanup;
}

@@ -1191,6 +1190,7 @@ SetTheImage (
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;
}
@@ -1218,6 +1218,7 @@ SetTheImage (

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;
}
@@ -1238,6 +1239,7 @@ SetTheImage (
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) {
@@ -1258,10 +1260,12 @@ SetTheImage (
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)
@@ -1277,10 +1281,12 @@ SetTheImage (
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)
@@ -1302,12 +1308,14 @@ SetTheImage (
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;
}
@@ -1372,6 +1380,7 @@ SetTheImage (
mProgressFunc = NULL;

if (Private != NULL) {
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): SetTheImage() LastAttemptStatus: %u.\n", mImageIdName, LastAttemptStatus));
SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
}

--
2.28.0.windows.1


[PATCH v4 3/6] FmpDevicePkg/FmpDxe: Add check image path Last Attempt Status capability

Michael Kubacki
 

From: Michael Kubacki <michael.kubacki@...>

CheckTheImage() is currently used to provide the CheckImage()
implementation for the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance
produced by FmpDxe in addition to being called internally in the
SetImage() path.

Since CheckTheImage() plays a major role in determining the
validity of a given firmware image, an internal version of the
function is introduced - CheckTheImageInternal() that is capable
of returning a Last Attempt Status code to internal callers such
as SetTheImage().

The CheckImage() API as defined in the UEFI Specification for
EFI_FIRMWARE_MANAGEMENT_PROTOCOL is not impacted by this change.

CheckTheImageInternal() contains unique Last Attempt Status codes
during error paths in the function so it is easier to identify
the issue with a particular image through the Last Attempt Status
code value.

Cc: Liming Gao <gaoliming@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Guomin Jiang <guomin.jiang@...>
Cc: Wei6 Xu <wei6.xu@...>
Signed-off-by: Michael Kubacki <michael.kubacki@...>
---
FmpDevicePkg/FmpDxe/FmpDxe.c | 98 +++++++++++++++++---
FmpDevicePkg/FmpDxe/FmpDxe.h | 4 +-
2 files changed, 90 insertions(+), 12 deletions(-)

diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c
index 427b215ddc5f..858cffd8e5bd 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.c
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.c
@@ -721,6 +721,14 @@ GetAllHeaderSize (
@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.

@retval EFI_SUCCESS The image was successfully checked.
@retval EFI_ABORTED The operation is aborted.
@@ -731,15 +739,17 @@ GetAllHeaderSize (
**/
EFI_STATUS
EFIAPI
-CheckTheImage (
+CheckTheImageInternal (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
IN UINT8 ImageIndex,
IN CONST VOID *Image,
IN UINTN ImageSize,
- OUT UINT32 *ImageUpdatable
+ OUT UINT32 *ImageUpdatable,
+ OUT UINT32 *LastAttemptStatus
)
{
EFI_STATUS Status;
+ UINT32 LocalLastAttemptStatus;
FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
UINTN RawSize;
VOID *FmpPayloadHeader;
@@ -755,23 +765,37 @@ CheckTheImage (
EFI_FIRMWARE_IMAGE_DEP *Dependencies;
UINT32 DependenciesSize;

- Status = EFI_SUCCESS;
- RawSize = 0;
- FmpPayloadHeader = NULL;
- FmpPayloadSize = 0;
- Version = 0;
- FmpHeaderSize = 0;
- AllHeaderSize = 0;
- Dependencies = NULL;
- DependenciesSize = 0;
+ 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;
}

@@ -789,6 +813,7 @@ CheckTheImage (
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;
}

@@ -808,6 +833,7 @@ CheckTheImage (
// not sure if this is needed
//
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROVIDED;
return EFI_INVALID_PARAMETER;
}

@@ -817,6 +843,7 @@ CheckTheImage (
if (PublicKeyDataXdr == NULL || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName));
Status = EFI_ABORTED;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CERTIFICATE;
} else {
//
// Try each key from PcdFmpDevicePkcs7CertBufferXdr
@@ -839,6 +866,7 @@ CheckTheImage (
//
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;
}
//
@@ -855,6 +883,7 @@ CheckTheImage (
//
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;
@@ -874,6 +903,11 @@ CheckTheImage (

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;
}

@@ -884,6 +918,7 @@ CheckTheImage (
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;
}

@@ -899,6 +934,7 @@ CheckTheImage (
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);
@@ -906,6 +942,7 @@ CheckTheImage (
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;
}

@@ -920,6 +957,7 @@ CheckTheImage (
);
*ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;
Status = EFI_SUCCESS;
+ *LastAttemptStatus = LAST_ATTEMPT_STATUS_DRIVER_ERROR_VERSION_TOO_LOW;
goto cleanup;
}

@@ -942,6 +980,7 @@ CheckTheImage (
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;
}

@@ -953,6 +992,7 @@ CheckTheImage (
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;
@@ -969,6 +1009,42 @@ CheckTheImage (
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.

diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.h b/FmpDevicePkg/FmpDxe/FmpDxe.h
index 30754dea495e..1177b1828e9a 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.h
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.h
@@ -3,7 +3,7 @@
image stored in a firmware device with platform and firmware device specific
information provided through PCDs and libraries.

- Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -36,6 +36,8 @@
#include <Protocol/VariableLock.h>
#include <Guid/SystemResourceTable.h>
#include <Guid/EventGroup.h>
+#include <LastAttemptStatus.h>
+#include <FmpLastAttemptStatus.h>

#define VERSION_STRING_NOT_SUPPORTED L"VERSION STRING NOT SUPPORTED"
#define VERSION_STRING_NOT_AVAILABLE L"VERSION STRING NOT AVAILABLE"
--
2.28.0.windows.1


[PATCH v4 2/6] FmpDevicePkg: Add Last Attempt Status header files

Michael Kubacki
 

From: Michael Kubacki <michael.kubacki@...>

Introduces a public and a private header file to define more
granular usage of the UEFI Specification defined unsuccessful
vendor range for Last Attempt Status codes. The unsuccessful
vendor range is described in UEFI Specification 2.8A section 23.4.

The public header file Include/LastAttemptStatus.h defines ranges
within the unsuccessful vendor range. At a high-level, the two
main ranges are defined are the FMP Reserved range and the Device
Library Reserved range.

The FMP Reserved range is reserved for usage of components within
FmpDevicePkg. PrivateInclude/FmpLastAttemptStatus.h contains
usage details and specific Last Attempt Status code definitions.

The Device Library Reserved range is reserved for usage by
FmpDeviceLib instances. Each library may define custom Last
Attempt Status codes within the bounds defined in
Include/LastAttemptStatus.h:
[LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE,
LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE]

Cc: Liming Gao <gaoliming@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Guomin Jiang <guomin.jiang@...>
Cc: Wei6 Xu <wei6.xu@...>
Signed-off-by: Michael Kubacki <michael.kubacki@...>
---
FmpDevicePkg/Include/LastAttemptStatus.h | 81 ++++++++++++++++++++
FmpDevicePkg/PrivateInclude/FmpLastAttemptStatus.h | 81 ++++++++++++++++++++
2 files changed, 162 insertions(+)

diff --git a/FmpDevicePkg/Include/LastAttemptStatus.h b/FmpDevicePkg/Include/LastAttemptStatus.h
new file mode 100644
index 000000000000..0dcd1ef71621
--- /dev/null
+++ b/FmpDevicePkg/Include/LastAttemptStatus.h
@@ -0,0 +1,81 @@
+/** @file
+ Defines last attempt status code ranges within the UEFI Specification
+ defined unsuccessful vendor range.
+
+ Copyright (c) Microsoft Corporation.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __LAST_ATTEMPT_STATUS_H__
+#define __LAST_ATTEMPT_STATUS_H__
+
+///
+/// Last Attempt Status Unsuccessful Vendor Range Map
+///
+/// Update this map any time new ranges are added. Pre-existing range definitions cannot be modified
+/// to keep status code definitions consistent over time.
+///
+/// START | END | Usage
+/// ------------------------------------------------------------------|
+/// 0x1000 | 0x17FF | FmpDevicePkg |
+/// 0x1000 | 0x107F | FmpDxe driver |
+/// 0x1080 | 0x109F | FmpDependencyLib |
+/// 0x10A0 | 0x10BF | FmpDependencyCheckLib |
+/// 0x10C0 | 0x17FF | Unused. Available for future expansion. |
+/// 0x1800 | 0x1FFF | FmpDeviceLib instances implementation |
+/// 0x2000 | 0x3FFF | Unused. Available for future expansion. |
+///
+
+///
+/// The minimum value of the FMP reserved range.
+///
+#define LAST_ATTEMPT_STATUS_FMP_RESERVED_MIN_ERROR_CODE_VALUE 0x1000
+
+///
+/// The maximum value of the FMP reserved range.
+///
+#define LAST_ATTEMPT_STATUS_FMP_RESERVED_MAX_ERROR_CODE_VALUE 0x1FFF
+
+///
+/// The minimum value allowed for FmpDxe driver-specific errors.
+///
+#define LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE_VALUE 0x1000
+
+///
+/// The maximum value allowed for FmpDxe driver-specific errors.
+///
+#define LAST_ATTEMPT_STATUS_DRIVER_MAX_ERROR_CODE_VALUE 0x107F
+
+///
+/// The minimum value allowed for FmpDependencyLib related errors.
+///
+#define LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MIN_ERROR_CODE_VALUE 0x1080
+
+///
+/// The maximum value allowed for FmpDependencyLib related errors.
+///
+#define LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MAX_ERROR_CODE_VALUE 0x109F
+
+///
+/// The minimum value allowed for FmpDependencyCheckLib related errors.
+///
+#define LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MIN_ERROR_CODE_VALUE 0x10A0
+
+///
+/// The maximum value allowed for FmpDependencyCheckLib related errors.
+///
+#define LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MAX_ERROR_CODE_VALUE 0x10BF
+
+///
+/// The minimum value allowed for FMP device library errors.
+///
+#define LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE 0x1800
+
+///
+/// The maximum value allowed for FMP device library errors.
+///
+#define LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE 0x1FFF
+
+#endif
diff --git a/FmpDevicePkg/PrivateInclude/FmpLastAttemptStatus.h b/FmpDevicePkg/PrivateInclude/FmpLastAttemptStatus.h
new file mode 100644
index 000000000000..a0cc94f69955
--- /dev/null
+++ b/FmpDevicePkg/PrivateInclude/FmpLastAttemptStatus.h
@@ -0,0 +1,81 @@
+/** @file
+ Defines private last attempt status codes used in FmpDevicePkg.
+
+ Copyright (c) Microsoft Corporation.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __FMP_LAST_ATTEMPT_STATUS_H__
+#define __FMP_LAST_ATTEMPT_STATUS_H__
+
+///
+/// Last attempt status codes defined for additional granularity in FmpDevicePkg components.
+///
+/// These codes are defined within the last attempt status FMP reserved range which extends from
+/// LAST_ATTEMPT_STATUS_FMP_RESERVED_MIN_ERROR_CODE_VALUE to LAST_ATTEMPT_STATUS_FMP_RESERVED_MAX_ERROR_CODE_VALUE.
+///
+/// The following last attempt status code ranges are currently defined for the corresponding component:
+/// * LAST_ATTEMPT_STATUS_DRIVER - FMP driver
+/// * LAST_ATTEMPT_STATUS_DEPENDENCY - FMP dependency functionality
+///
+/// Future last attempt status code additions in FmpDevicePkg should be added as follows:
+/// * FmpDxe driver: Onto the end of the LAST_ATTEMPT_STATUS_DRIVER_ERROR range
+/// * FMP dependency functionality: Onto the end of the LAST_ATTEMPT_STATUS_DEPENDENCY_ERROR range
+/// * Other components: Add a new range onto the end of the last existing range in the enum within the limits of
+/// [LAST_ATTEMPT_STATUS_FMP_RESERVED_MIN_ERROR_CODE_VALUE,LAST_ATTEMPT_STATUS_FMP_RESERVED_MAX_ERROR_CODE_VALUE]
+///
+/// The value of pre-existing last attempt status codes should never be modified to ensure the values remain
+/// consistent over time.
+///
+enum LAST_ATTEMPT_STATUS_EXPANDED_ERROR_LIST
+{
+ ///
+ /// Last attempt status codes used in FmpDxe
+ ///
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER = LAST_ATTEMPT_STATUS_DRIVER_MIN_ERROR_CODE_VALUE,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROGRESS_CALLBACK_ERROR ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_POWER_API ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_THERMAL_API ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_THERMAL ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_CHECK_SYS_ENV_API ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_SYSTEM_ENV ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_SIZE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_ALL_HEADER_SIZE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_GET_FMP_HEADER_VERSION ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_PROVIDED ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_NOT_UPDATABLE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_CERTIFICATE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_IMAGE_INDEX ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_INVALID_KEY_LENGTH_VALUE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_VERSION_TOO_LOW ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_DEVICE_LOCKED ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_IMAGE_AUTH_FAILURE ,
+ LAST_ATTEMPT_STATUS_DRIVER_ERROR_PROTOCOL_ARG_MISSING ,
+
+ ///
+ /// Last attempt status codes used in FmpDependencyLib
+ ///
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GET_DEPEX_FAILURE = LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_LIB_MIN_ERROR_CODE_VALUE,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_NO_END_OPCODE ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_UNKNOWN_OPCODE ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_GUID_BEYOND_DEPEX ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_BEYOND_DEPEX ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_VERSION_STR_BEYOND_DEPEX ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_FMP_NOT_FOUND ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_PUSH_FAILURE ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_LIB_ERROR_POP_FAILURE ,
+
+ //
+ // Last attempt status codes used in FmpDependencyCheckLib
+ //
+ LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_FMP_PROTOCOL_NOT_FOUND = LAST_ATTEMPT_STATUS_FMP_DEPENDENCY_CHECK_LIB_MIN_ERROR_CODE_VALUE,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_FMP_INFO_BUFFER_FAILED ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_DESC_VER_BUFFER_FAILED ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_DESC_SIZE_BUFFER_FAILED ,
+ LAST_ATTEMPT_STATUS_DEPENDENCY_CHECK_LIB_ERROR_MEM_ALLOC_FMP_VER_BUFFER_FAILED
+};
+
+#endif
--
2.28.0.windows.1


[PATCH v4 1/6] MdePkg/SystemResourceTable.h: Add vendor range values

Michael Kubacki
 

From: Michael Kubacki <michael.kubacki@...>

Adds the following macros to define the unsuccessful vendor range
min and max (defined in UEFI Specification 2.8):
1. LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MIN
2. LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX

Cc: Liming Gao <gaoliming@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Guomin Jiang <guomin.jiang@...>
Cc: Wei6 Xu <wei6.xu@...>
Cc: Zhiguang Liu <zhiguang.liu@...>
Signed-off-by: Michael Kubacki <michael.kubacki@...>
---
MdePkg/Include/Guid/SystemResourceTable.h | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/MdePkg/Include/Guid/SystemResourceTable.h b/MdePkg/Include/Guid/SystemResourceTable.h
index 418b8c8d055a..17a26fe7e688 100644
--- a/MdePkg/Include/Guid/SystemResourceTable.h
+++ b/MdePkg/Include/Guid/SystemResourceTable.h
@@ -1,6 +1,7 @@
/** @file
Guid & data structure used for EFI System Resource Table (ESRT)

+ Copyright (c) Microsoft Corporation.<BR>
Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -44,6 +45,18 @@
#define LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT 0x00000007
#define LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES 0x00000008

+///
+/// LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX is defined as
+/// 0x4000 as of UEFI Specification 2.8B. This will be modified in the
+/// future to the correct value 0x3FFF. To ensure correct implementation,
+/// this change is preemptively made in the value defined below.
+///
+/// When the UEFI Specification is updated, this comment block can be
+/// removed.
+///
+#define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MIN 0x00001000
+#define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX 0x00003FFF
+
typedef struct {
///
/// The firmware class field contains a GUID that identifies a firmware component
--
2.28.0.windows.1


[PATCH v4 0/6] Extend Last Attempt Status Usage

Michael Kubacki
 

From: Michael Kubacki <michael.kubacki@...>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2802

This patch series adds more granularity to Last Attempt Status
codes reported during FMP check image and set image operations
that greatly improve precision of the status codes.

The unsuccessful vendor range (0x1000 - 0x4000) was introduced
in UEFI Specification 2.8. At a high-level, two subranges are
defined within that range in this patch series:
1. The FMP Reserved range - reserved for components implemented
in FmpDevicePkg.
2. The FMP Device Library Reserved range - reserved for
FmpDeviceLib instance-specific usage.

The ranges are described in a public header file LastAttemptStatus.h
while the specific codes used within FmpDevicePkg implementation
are defined in a private header file FmpLastAttemptStatus.h.

FmpDeviceLib instances should use the range definition from the
public header file to define Last Attempt Status codes local to
their library instance.

Of note, there's multiple approaches to assigning private status
codes in the FMP Reserved range. For example, individual components
could define their last attempt status codes locally with the
range allocated to the component defined in a package-wide private
header file. However, one goal of the granularity being introduced
is to provide straightforward traceability to an error source.

For that reason, it was chosen to define a constant set of codes at
the package level in FmpLastAttemptStatus.h. For example, if a new
FmpDependencyLib instance is added, it would not be able to reassign
status code values in the pre-existing FMP Dependency range; it
would reuse codes for the same error source and be able to add new
codes onto the range for its usage.

V4 changes:
1. Simplified range value definitions in LastAttemptStatus.h.
Directly assign the values in the macro definition instead
of using calculations.
2. Adjusted range sizes to leave more room for future expansion.

OLD:
START | END | Usage
------------------------------------------------|
0x1000 | 0x1FFF | FmpDevicePkg |
0x1000 | 0x107F | FmpDxe driver |
0x1080 | 0x109F | FMP dependency Libs |
0x2000 | 0x3FFF | FmpDeviceLib instances |

NEW:
START | END | Usage
----------------------------------------------------------------|
0x1000 | 0x17FF | FmpDevicePkg |
0x1000 | 0x107F | FmpDxe driver |
0x1080 | 0x109F | FmpDependencyLib |
0x10A0 | 0x10BF | FmpDependencyCheckLib |
0x10C0 | 0x17FF | Unused. Available for future expansion. |
0x1800 | 0x1FFF | FmpDeviceLib instances implementation |
0x2000 | 0x3FFF | Unused. Available for future expansion. |

3. Broke the single range in v3 for FMP Dependency libraries into
separate ranges.
4. Clarified LastAttemptStatus return values in each function
description.
5. Returned an expected LastAttemptStatus value for some functions
that previously did not return a value.
6. Reverted changes in FmpDxe to call the new FmpDeviceLib APIs
for FmpDeviceCheckImage () and FmpDeviceSetImage (). These will
be added in a future series after impacted platforms in
edk2-platforms are updated to use the new APIs.
7. Instead of directly changing the pre-existing APIs in
FmpDeviceLib to add a LastAttemptStatus parameter, the new
functions were added to the library interface:
* FmpDeviceCheckImageWithStatus ()
* FmpDeviceSetImageWithStatus ()

V3 changes:
1. Enhanced range definitions in LastAttemptStatus.h with more
completeness providing length, min, and max values.
2. Moved the actual Last Attempt Status code assignments to a
private header file PrivateInclude/FmpLastAttemptStatus.h.
3. Changed the value of
LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX
to 0x3FFF instead of 0x4000 even though 0x4000 is defined in
the UEFI specification. The length is 0x4000 but the max
allowed value should be 0x3FFF. This change was made now to
prevent implementation compatibility issues in the future.
4. Included "DEVICE" in the following macro name to clearly
associate it with the FmpDeviceLib library class:
LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_ERROR_xxx
5. Included a map to help the reader better visualize the range
definitions in LastAttemptStatus.h.
6. Included additional documentation describing the enum in
FmpLastAttemptStatus.h. An explicit statement stating that new
codes should be added onto the end of ranges to preserve the
values was added.
7. Simplified error handling logic in FmpDxe for FmpDeviceLib
calls that return Last Attempt Status.
8. V2 had a single memory allocation failure code used for
different memory allocations in CheckFmpDependency () in
FmpDependencyLib. Each potential allocation failure was
assigned a unique code.

V2 changes:
1. Consolidate all previous incremental updates to
LastAttemptStatus.h into one patch (patch 2)
2. Move LastAttemptStatus.h from Include to PrivateInclude
3. Correct patch 1 subject from "FmpDevicePkg" to "MdePkg"

Cc: Liming Gao <gaoliming@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Guomin Jiang <guomin.jiang@...>
Cc: Wei6 Xu <wei6.xu@...>
Cc: Zhiguang Liu <zhiguang.liu@...>
Signed-off-by: Michael Kubacki <michael.kubacki@...>

Michael Kubacki (6):
MdePkg/SystemResourceTable.h: Add vendor range values
FmpDevicePkg: Add Last Attempt Status header files
FmpDevicePkg/FmpDxe: Add check image path Last Attempt Status
capability
FmpDevicePkg/FmpDxe: Improve set image path Last Attempt Status
granularity
FmpDevicePkg: Add Last Attempt Status support to dependency libs
FmpDevicePkg/FmpDeviceLib: Add Last Attempt Status to Check/Set API

FmpDevicePkg/FmpDxe/FmpDxe.c | 146 +++++++++++++++++---
FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c | 39 ++++--
FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c | 14 +-
FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c | 93 +++++++++++--
FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLib.c | 132 +++++++++++++++++-
FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c | 7 +-
FmpDevicePkg/FmpDxe/FmpDxe.h | 4 +-
FmpDevicePkg/Include/LastAttemptStatus.h | 81 +++++++++++
FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h | 8 +-
FmpDevicePkg/Include/Library/FmpDependencyLib.h | 44 ++++--
FmpDevicePkg/Include/Library/FmpDeviceLib.h | 121 +++++++++++++++-
FmpDevicePkg/PrivateInclude/FmpLastAttemptStatus.h | 81 +++++++++++
MdePkg/Include/Guid/SystemResourceTable.h | 13 ++
13 files changed, 718 insertions(+), 65 deletions(-)
create mode 100644 FmpDevicePkg/Include/LastAttemptStatus.h
create mode 100644 FmpDevicePkg/PrivateInclude/FmpLastAttemptStatus.h

--
2.28.0.windows.1


Re: [edk2-staging/EdkRepo] [PATCH V3] EdkRepo: Return exit codes in edkrepo_entry_point.py

Nate DeSimone
 

Reviewed-by: Nate DeSimone <@natedesimone>

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Ashley E Desimone
Sent: Wednesday, September 9, 2020 2:42 PM
To: devel@edk2.groups.io
Cc: Desimone, Nathaniel L <@natedesimone>; Pandya, Puja <puja.pandya@...>; Bret Barkelew <Bret.Barkelew@...>; Agyeman, Prince <prince.agyeman@...>; Bjorge, Erik C <erik.c.bjorge@...>
Subject: [edk2-devel] [edk2-staging/EdkRepo] [PATCH V3] EdkRepo: Return exit codes in edkrepo_entry_point.py

Return the error codes generated by edkrepo_cli that is called in main()

Cc: Nate DeSimone <@natedesimone>
Cc: Puja Pandya <puja.pandya@...>
Cc: Bret Barkelew <Bret.Barkelew@...>
Cc: Prince Agyeman <prince.agyeman@...>
Cc: Erik Bjorge <erik.c.bjorge@...>
Signed-off-by: Ashley E Desimone <ashley.e.desimone@...>
---
edkrepo/edkrepo_entry_point.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/edkrepo/edkrepo_entry_point.py b/edkrepo/edkrepo_entry_point.py index c2ff56a..dd2b36e 100644
--- a/edkrepo/edkrepo_entry_point.py
+++ b/edkrepo/edkrepo_entry_point.py
@@ -91,12 +91,12 @@ def main():
try: mod = importlib.import_module(pref_entry) func = getattr(mod, pref_entry_func)- func()+ return(func()) except Exception as e: print('Unable to launch preferred entry point. Launching default entry point edkrepo.edkrepo_cli.py') traceback.print_exc() import edkrepo.edkrepo_cli- edkrepo.edkrepo_cli.main()+ return edkrepo.edkrepo_cli.main() if __name__ == "__main__": try:--
2.26.2.windows.1


-=-=-=-=-=-=
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#65164): https://edk2.groups.io/g/devel/message/65164
Mute This Topic: https://groups.io/mt/76743015/1767664
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [@natedesimone] -=-=-=-=-=-=


[edk2-staging/EdkRepo] [PATCH V3 0/2] EdkRepo: Add support for SUBST drives

Nate DeSimone
 

Changes in V3:
- Changed loop for finding subst drive to single if statement

Changes in V2:
- Changed get_subst_drive_list() to get_subst_drive_dict()

EdkRepo currently does not handle virtual drives created using the SUBST command.
Specifically, when cloning or syncing a project to a subst drive the includeIf statements
that redirect submodule fetches to mirror servers will be generated with the
subst drive information. This causes git to not activate the includeif since
it specifies the subst path and not the actual path.

To resolve this, EdkRepo will now enumerate the virtual drives created by SUBST and if
the current workspace is on a SUBST virtual drive EdkRepo will convert the workspace
path to the path on the real volume.

Cc: Ashley E Desimone <ashley.e.desimone@...>
Cc: Puja Pandya <puja.pandya@...>
Cc: Bret Barkelew <Bret.Barkelew@...>
Cc: Prince Agyeman <prince.agyeman@...>
Cc: Erik Bjorge <erik.c.bjorge@...>
Signed-off-by: Nate DeSimone <@natedesimone>

Nate DeSimone (2):
EdkRepo: Add function to enumerate subst drives
EdkRepo: Add support for subst drives

edkrepo/commands/clone_command.py | 8 +++++
edkrepo/common/pathfix.py | 50 ++++++++++++++++++++++++++++++-
edkrepo/config/config_factory.py | 10 ++++++-
3 files changed, 66 insertions(+), 2 deletions(-)

--
2.27.0.windows.1


[edk2-staging/EdkRepo] [PATCH V3 1/2] EdkRepo: Add function to enumerate subst drives

Nate DeSimone
 

Cc: Ashley E Desimone <ashley.e.desimone@...>
Cc: Puja Pandya <puja.pandya@...>
Cc: Bret Barkelew <Bret.Barkelew@...>
Cc: Prince Agyeman <prince.agyeman@...>
Cc: Erik Bjorge <erik.c.bjorge@...>
Signed-off-by: Nate DeSimone <@natedesimone>
---
edkrepo/common/pathfix.py | 50 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/edkrepo/common/pathfix.py b/edkrepo/common/pathfix.py
index 1a9c20f..2775442 100644
--- a/edkrepo/common/pathfix.py
+++ b/edkrepo/common/pathfix.py
@@ -3,7 +3,7 @@
## @file
# checkout_command.py
#
-# Copyright (c) 2018- 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
import os
@@ -11,6 +11,7 @@ import sys
if sys.platform == "win32":
from ctypes import windll, POINTER, byref, GetLastError, Structure, WinError
from ctypes import c_void_p, c_ushort, c_int, c_ulong, c_wchar, c_wchar_p
+ from ctypes import create_unicode_buffer

def _is_wow64_process():
kernel32 = windll.kernel32
@@ -211,3 +212,50 @@ def expanduser(path):
userhome = os.path.join(os.path.dirname(userhome), path[1:i])

return userhome + path[i:]
+
+def get_subst_drive_dict():
+ if sys.platform != "win32":
+ return {}
+ def _query_subst_drive(drive_letter):
+ kernel32 = windll.kernel32
+ QueryDosDevice = kernel32.QueryDosDeviceW
+ QueryDosDevice.argtypes = [c_wchar_p, c_wchar_p, c_ulong]
+ QueryDosDevice.restype = c_ulong
+ MAX_PATH = 260
+
+ if len(drive_letter) > 1 or len(drive_letter) == 0:
+ raise ValueError("Bad drive letter")
+ drive = '{}:'.format(drive_letter.upper())
+ drive_buffer = create_unicode_buffer(drive)
+ target_path_buffer_size = c_ulong(MAX_PATH)
+ target_path_buffer = create_unicode_buffer(target_path_buffer_size.value)
+ while True:
+ count = QueryDosDevice(drive_buffer, target_path_buffer, target_path_buffer_size)
+ if count == 0:
+ last_error = GetLastError()
+ if last_error == 122: #ERROR_INSUFFICIENT_BUFFER
+ #Increase the buffer size and try again
+ target_path_buffer_size = c_ulong((target_path_buffer_size.value * 161) / 100)
+ target_path_buffer = create_unicode_buffer(target_path_buffer_size.value)
+ elif last_error == 2: #ERROR_FILE_NOT_FOUND
+ #This is an invalid drive, return an empty string
+ return ''
+ else:
+ raise WinError(last_error)
+ else:
+ break
+ target_path = target_path_buffer.value
+ if len(target_path) > 4 and target_path[0:4] == '\\??\\':
+ if (ord(target_path[4]) >= ord('A') and ord(target_path[4]) <= ord('Z')) or \
+ (ord(target_path[4]) >= ord('a') and ord(target_path[4]) <= ord('z')):
+ #This is a SUBST'd drive, return the path
+ return target_path[4:].strip()
+ #This is a non-SUBST'd (aka real) drive, return an empty string
+ return ''
+ subst_dict = {}
+ for index in range(26):
+ drive_letter = chr(ord('A') + index)
+ target_path = _query_subst_drive(drive_letter)
+ if target_path != '':
+ subst_dict[drive_letter] = target_path
+ return subst_dict
--
2.27.0.windows.1


[edk2-staging/EdkRepo] [PATCH V3 2/2] EdkRepo: Add support for subst drives

Nate DeSimone
 

get_workspace_path() now converts a virtual drive path
to a real path before any git repo operations are done.

Cc: Ashley E Desimone <ashley.e.desimone@...>
Cc: Puja Pandya <puja.pandya@...>
Cc: Bret Barkelew <Bret.Barkelew@...>
Cc: Prince Agyeman <prince.agyeman@...>
Cc: Erik Bjorge <erik.c.bjorge@...>
Signed-off-by: Nate DeSimone <@natedesimone>
---
edkrepo/commands/clone_command.py | 8 ++++++++
edkrepo/config/config_factory.py | 10 +++++++++-
2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/edkrepo/commands/clone_command.py b/edkrepo/commands/clone_command.py
index f638090..8769102 100644
--- a/edkrepo/commands/clone_command.py
+++ b/edkrepo/commands/clone_command.py
@@ -9,6 +9,7 @@

import os
import shutil
+import sys

from edkrepo.commands.edkrepo_command import EdkrepoCommand
from edkrepo.commands.edkrepo_command import SubmoduleSkipArgument, SourceManifestRepoArgument
@@ -20,6 +21,7 @@ from edkrepo.common.edkrepo_exception import EdkrepoInvalidParametersException,
from edkrepo.common.edkrepo_exception import EdkrepoManifestNotFoundException
from edkrepo.common.humble import CLONE_INVALID_WORKSPACE, CLONE_INVALID_PROJECT_ARG, CLONE_INVALID_COMBO_ARG
from edkrepo.common.humble import SPARSE_CHECKOUT, CLONE_INVALID_LOCAL_ROOTS
+from edkrepo.common.pathfix import get_subst_drive_dict
from edkrepo.common.workspace_maintenance.workspace_maintenance import case_insensitive_single_match
from edkrepo.common.workspace_maintenance.manifest_repos_maintenance import pull_all_manifest_repos, find_project_in_all_indices
from edkrepo.common.workspace_maintenance.manifest_repos_maintenance import list_available_manifest_repos
@@ -77,6 +79,12 @@ class CloneCommand(EdkrepoCommand):
workspace_dir = os.getcwd()
else:
workspace_dir = os.path.abspath(workspace_dir)
+ if sys.platform == "win32":
+ subst = get_subst_drive_dict()
+ drive = os.path.splitdrive(workspace_dir)[0][0].upper()
+ if drive in subst:
+ workspace_dir = os.path.join(subst[drive], os.path.splitdrive(workspace_dir)[1][1:])
+ workspace_dir = os.path.normpath(workspace_dir)
if os.path.isdir(workspace_dir) and os.listdir(workspace_dir):
raise EdkrepoInvalidParametersException(CLONE_INVALID_WORKSPACE)
if not os.path.isdir(workspace_dir):
diff --git a/edkrepo/config/config_factory.py b/edkrepo/config/config_factory.py
index a82a438..fe69460 100644
--- a/edkrepo/config/config_factory.py
+++ b/edkrepo/config/config_factory.py
@@ -11,13 +11,16 @@ import os
import sys
import configparser
import collections
-from ctypes import *
+if sys.platform == "win32":
+ from ctypes import oledll, c_void_p, c_uint32, c_wchar_p
+ from ctypes import create_unicode_buffer

import edkrepo.config.humble.config_factory_humble as humble
from edkrepo.common.edkrepo_exception import EdkrepoGlobalConfigNotFoundException, EdkrepoConfigFileInvalidException
from edkrepo.common.edkrepo_exception import EdkrepoWorkspaceInvalidException, EdkrepoGlobalDataDirectoryNotFoundException
from edkrepo.common.edkrepo_exception import EdkrepoConfigFileReadOnlyException
from edkrepo.common.humble import MIRROR_PRIMARY_REPOS_MISSING, MIRROR_DECODE_WARNING, MAX_PATCH_SET_INVALID
+from edkrepo.common.pathfix import get_subst_drive_dict
from edkrepo_manifest_parser import edk_manifest
from edkrepo.common.pathfix import expanduser

@@ -238,6 +241,11 @@ def get_workspace_path():
while True:
if os.path.isdir(os.path.join(path, "repo")):
if os.path.isfile(os.path.join(os.path.join(path, "repo"), "Manifest.xml")):
+ if sys.platform == "win32":
+ subst = get_subst_drive_dict()
+ drive = os.path.splitdrive(path)[0][0].upper()
+ if drive in subst:
+ path = os.path.join(subst[drive], os.path.splitdrive(path)[1][1:])
return path
if os.path.dirname(path) == path:
break
--
2.27.0.windows.1


Re: more development process failure [was: UefiPayloadPkg: Runtime MMCONF]

Guo Dong
 

Sorry to have a long email thread since my merge and thanks all for the comments.
In general, I still feel current process is a little complicated for the maintainers who don't
daily work on EDK2 like me. I have less than %5 of time spent on open source EDK2
UefiPayloadPkg since I focus on bootloaders. It would be great if I could spend the time
mainly on code review instead of the process as of now.

Even after I read https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-
Development-Process#the-maintainer-process-for-the-edk-ii-project as Liming pointed out,
Some info is still not clear for me. E.g. what's the purpose for putting cover letter to patch
set pull request (it looks we could not trace to this PR from code)? is it mandatory or optional?
What if there is no cover letter in the patch set in patch #0 summary? For the patch I merged,
I am still not very sure what info I should put there.

I don't know why Laszlo mentioned BZ for my merge since there is no BZ mentioned in the patchset.
And I also don't know why Laszlo mentioned to send email after the patch is merged since I don't find this
requirement in the development process. I don't think it is doable to ask all the maintainers to monitor EDK2
mail list on how others are doing since there are so many emails every day, especially there is no any patch
for UefiPayloadPkg for several months.

I hope we could simplify the process and have a clear steps in the process soon. So that the maintainers could
focus on the actual code review.

Thanks,
Guo


Tianocore community page on who we are - please review

Soumya Guptha
 

Dear Community members,

 

I have drafted a document “who we are”, explaining Tianocore community structure, members of the community, their role and the current development process. I have drafted this document with the help of the Tianocore Stewards.

We view this as a living document, as our development processes evolve, I will keep this document updated.

 

Please review the draft version of the document (link below) and provide your feedback. Please send it to me, no need to reply all.

I appreciate your input by Friday, Oct 2. After this, I plan on make it live on our TianoCore wiki site.

 

Link: https://github.com/tianocore/tianocore.github.io/wiki/Who-we-are

 

Thanks,

Soumya

 

Soumya Guptha
TianoCore Community Manager



 


[Patch V3 2/2] Readme.rst: Add EmulatorPkg SECURE_BOOT_ENABLE CI status

Michael D Kinney
 

https://bugzilla.tianocore.org/show_bug.cgi?id=2979

Add CI status badges for the EmulatorPkg CI builds with
SECURE_BOOT_ENABLE=TRUE for IA32/X64 and DEBUG/RELEASE/NOOPT.

Cc: Jordan Justen <jordan.l.justen@...>
Cc: Andrew Fish <afish@...>
Cc: Ray Ni <ray.ni@...>
Cc: Divneil Rai Wadhawan <divneil.r.wadhawan@...>
Cc: Sean Brogan <sean.brogan@...>
Signed-off-by: Michael D Kinney <michael.d.kinney@...>
Reviewed-by: Sean Brogan <sean.brogan@...>
---
ReadMe.rst | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/ReadMe.rst b/ReadMe.rst
index a16e13547f..c3c8178373 100644
--- a/ReadMe.rst
+++ b/ReadMe.rst
@@ -28,6 +28,8 @@ Microsoft Windows VS2019
============================= ================= ============= ============= ==============
EmulatorPkg_Win_VS2019_ | IA32 |em32d| |em32r| |em32n|
| | X64 |em64d| |em64r| |em64n|
+| | IA32 FULL |em32fd| |em32fr| |em32fn|
+| | X64 FULL |em64fd| |em64fr| |em64fn|
OvmfPkg_Win_VS2019_ | IA32 |op32d| |op32r| |op32n|
| | X64 |op64d| |op64r| |op64n|
| | IA32 X64 |op3264d| |op3264r| |op3264n|
@@ -44,6 +46,8 @@ ArmVirtPkg_Ubuntu_GCC5_ | AARCH64 |avAArch64du| |avAArch64ru| |avA
| | ARM |avArmdu| |avArmru| |avArmnu|
EmulatorPkg_Ubuntu_GCC5_ | IA32 |em32du| |em32ru| |em32nu|
| | X64 |em64du| |em64ru| |em64nu|
+| | IA32 FULL |em32fdu| |em32fru| |em32fnu|
+| | X64 FULL |em64fdu| |em64fru| |em64fnu|
OvmfPkg_Ubuntu_GCC5_ | IA32 |op32du| |op32ru| |op32nu|
| | X64 |op64du| |op64ru| |op64nu|
| | IA32 X64 |op3264du| |op3264ru| |op3264nu|
@@ -319,6 +323,13 @@ use.
.. |em32n| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_NOOPT
.. |em32nu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_NOOPT

+.. |em32fd| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_DEBUG
+.. |em32fdu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_DEBUG
+.. |em32fr| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_RELEASE
+.. |em32fru| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_RELEASE
+.. |em32fn| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_NOOPT
+.. |em32fnu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_NOOPT
+
.. |em64d| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_DEBUG
.. |em64du| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_DEBUG
.. |em64r| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_RELEASE
@@ -326,6 +337,13 @@ use.
.. |em64n| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_NOOPT
.. |em64nu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_NOOPT

+.. |em64fd| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_DEBUG
+.. |em64fdu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_DEBUG
+.. |em64fr| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_RELEASE
+.. |em64fru| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_RELEASE
+.. |em64fn| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_NOOPT
+.. |em64fnu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_NOOPT
+
.. OvmfPkg

.. |TCBZ_2661| image:: https://img.shields.io/bugzilla/2661?baseUrl=https%3A%2F%2Fbugzilla.tianocore.org
--
2.21.0.windows.1


[Patch V3 1/2] EmulatorPkg: Add CI build for SECURE_BOOT_ENABLE

Michael D Kinney
 

https://bugzilla.tianocore.org/show_bug.cgi?id=2979

Add EmulatorPkg CI builds for SECURE_BOOT_ENABLE=TRUE
for IA32/X64 and DEBUG/RELEASE/NOOPT. Label these as
FULL builds, so if additional build options are added
in the future, they can be added to these FULL builds.

Cc: Jordan Justen <jordan.l.justen@...>
Cc: Andrew Fish <afish@...>
Cc: Ray Ni <ray.ni@...>
Cc: Divneil Rai Wadhawan <divneil.r.wadhawan@...>
Cc: Sean Brogan <sean.brogan@...>
Signed-off-by: Michael D Kinney <michael.d.kinney@...>
Reviewed-by: Sean Brogan <sean.brogan@...>
---
.../.azurepipelines/Ubuntu-GCC5.yml | 43 +++++++++++++++++++
.../.azurepipelines/Windows-VS2019.yml | 43 +++++++++++++++++++
EmulatorPkg/PlatformCI/ReadMe.md | 4 +-
3 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/EmulatorPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml b/EmulatorPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
index 12ef8226ff..0e5f4d9961 100644
--- a/EmulatorPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
+++ b/EmulatorPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
@@ -6,6 +6,7 @@
# Toolchain: GCC5
#
# Copyright (c) Microsoft Corporation.
+# Copyright (c) 2020, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
trigger:
@@ -65,6 +66,48 @@ jobs:
Build.Target: "NOOPT"
Run.Flags: $(run_flags)
Run: $(should_run)
+ EmulatorPkg_X64_FULL_DEBUG:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "DEBUG"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_X64_FULL_RELEASE:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "RELEASE"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_X64_FULL_NOOPT:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "NOOPT"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_DEBUG:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "DEBUG"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_RELEASE:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "RELEASE"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_NOOPT:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "NOOPT"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)

workspace:
clean: all
diff --git a/EmulatorPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml b/EmulatorPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml
index a5baf4b606..2bfce4e0af 100644
--- a/EmulatorPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml
+++ b/EmulatorPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml
@@ -6,6 +6,7 @@
# Toolchain: VS2019
#
# Copyright (c) Microsoft Corporation.
+# Copyright (c) 2020, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
trigger:
@@ -66,6 +67,48 @@ jobs:
Build.Target: "NOOPT"
Run.Flags: $(run_flags)
Run: $(should_run)
+ EmulatorPkg_X64_FULL_DEBUG:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "DEBUG"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_X64_FULL_RELEASE:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "RELEASE"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_X64_FULL_NOOPT:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "NOOPT"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_DEBUG:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "DEBUG"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_RELEASE:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "RELEASE"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_NOOPT:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "NOOPT"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)

workspace:
clean: all
diff --git a/EmulatorPkg/PlatformCI/ReadMe.md b/EmulatorPkg/PlatformCI/ReadMe.md
index c51838ec1a..91c40b2093 100644
--- a/EmulatorPkg/PlatformCI/ReadMe.md
+++ b/EmulatorPkg/PlatformCI/ReadMe.md
@@ -6,13 +6,15 @@ to use the same Pytools based build infrastructure locally.
## Supported Configuration Details

This solution for building and running EmulatorPkg has only been validated with Windows 10
-with VS2019 and Ubuntu 18.04 with GCC5 toolchain. Two different firmware builds are
+with VS2019 and Ubuntu 18.04 with GCC5 toolchain. Four different firmware builds are
supported and are described below.

| Configuration name | Architectures | DSC File |Additional Flags |
| :---- | :----- | :---- | :---- |
| IA32 | IA32 | EmulatorPkg.dsc | None |
| X64 | X64 | EmulatorPkg.dsc | None |
+| IA32 Full | IA32 | EmulatorPkg.dsc | SECURE_BOOT_ENABLE=TRUE |
+| X64 Full | X64 | EmulatorPkg.dsc | SECURE_BOOT_ENABLE=TRUE |

## EDK2 Developer environment

--
2.21.0.windows.1


[Patch V3 0/2] EmulatorPkg: Add CI build for SECURE_BOOT_ENABLE

Michael D Kinney
 

https://bugzilla.tianocore.org/show_bug.cgi?id=2979

Add EmulatorPkg CI builds for SECURE_BOOT_ENABLE=TRUE
for IA32/X64 and DEBUG/RELEASE/NOOPT and update add these
to the CI build status in Readme.rst.

Cc: Jordan Justen <jordan.l.justen@...>
Cc: Andrew Fish <afish@...>
Cc: Ray Ni <ray.ni@...>
Cc: Divneil Rai Wadhawan <divneil.r.wadhawan@...>
Cc: Sean Brogan <sean.brogan@...>
Signed-off-by: Michael D Kinney <michael.d.kinney@...>

Michael D Kinney (2):
EmulatorPkg: Add CI build for SECURE_BOOT_ENABLE
Readme.rst: Add EmulatorPkg SECURE_BOOT_ENABLE CI status

.../.azurepipelines/Ubuntu-GCC5.yml | 43 +++++++++++++++++++
.../.azurepipelines/Windows-VS2019.yml | 43 +++++++++++++++++++
EmulatorPkg/PlatformCI/ReadMe.md | 4 +-
ReadMe.rst | 18 ++++++++
4 files changed, 107 insertions(+), 1 deletion(-)

--
2.21.0.windows.1


Re: [Patch V2] EmulatorPkg: Add CI build for SECURE_BOOT_ENABLE

Michael D Kinney
 

Hi Sean,

Appreciate the review since the change was based on your suggestions.

I agree. I can split out the Readme.rst changes into its own commit.

Mike

-----Original Message-----
From: Sean Brogan <spbrogan@...>
Sent: Friday, September 25, 2020 1:46 PM
To: devel@edk2.groups.io; Kinney, Michael D <michael.d.kinney@...>
Cc: Justen, Jordan L <jordan.l.justen@...>; Andrew Fish <afish@...>; Ni, Ray <ray.ni@...>; Wadhawan, Divneil R
<divneil.r.wadhawan@...>; Sean Brogan <sean.brogan@...>
Subject: Re: [edk2-devel] [Patch V2] EmulatorPkg: Add CI build for SECURE_BOOT_ENABLE


I give my reviewed by for all changes for what it is worth.

One question: Should the EmulatorPkg change be in its own commit just to
keep sereration. I know in Mu we split the edk2 repository and it is
nice that nearly all commits only touch a single "package".

Reviewed-by: Sean Brogan <sean.brogan@...>

Thanks
Sean





On 9/25/2020 1:20 PM, Michael D Kinney wrote:
https://bugzilla.tianocore.org/show_bug.cgi?id=2979

Add EmulatorPkg CI builds for SECURE_BOOT_ENABLE=TRUE
for IA32/X64 and DEBUG/RELEASE/NOOPT. Label these as
FULL builds, so if additional build options are added
in the future, they can be added to these FULL builds.

Cc: Jordan Justen <jordan.l.justen@...>
Cc: Andrew Fish <afish@...>
Cc: Ray Ni <ray.ni@...>
Cc: Divneil Rai Wadhawan <divneil.r.wadhawan@...>
Cc: Sean Brogan <sean.brogan@...>
Signed-off-by: Michael D Kinney <michael.d.kinney@...>
---
.../.azurepipelines/Ubuntu-GCC5.yml | 43 +++++++++++++++++++
.../.azurepipelines/Windows-VS2019.yml | 43 +++++++++++++++++++
EmulatorPkg/PlatformCI/ReadMe.md | 4 +-
ReadMe.rst | 18 ++++++++
4 files changed, 107 insertions(+), 1 deletion(-)

diff --git a/EmulatorPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml b/EmulatorPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
index 12ef8226ff..0e5f4d9961 100644
--- a/EmulatorPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
+++ b/EmulatorPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
@@ -6,6 +6,7 @@
# Toolchain: GCC5
#
# Copyright (c) Microsoft Corporation.
+# Copyright (c) 2020, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
trigger:
@@ -65,6 +66,48 @@ jobs:
Build.Target: "NOOPT"
Run.Flags: $(run_flags)
Run: $(should_run)
+ EmulatorPkg_X64_FULL_DEBUG:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "DEBUG"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_X64_FULL_RELEASE:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "RELEASE"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_X64_FULL_NOOPT:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "NOOPT"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_DEBUG:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "DEBUG"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_RELEASE:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "RELEASE"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_NOOPT:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "NOOPT"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)

workspace:
clean: all
diff --git a/EmulatorPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml b/EmulatorPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml
index a5baf4b606..2bfce4e0af 100644
--- a/EmulatorPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml
+++ b/EmulatorPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml
@@ -6,6 +6,7 @@
# Toolchain: VS2019
#
# Copyright (c) Microsoft Corporation.
+# Copyright (c) 2020, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
trigger:
@@ -66,6 +67,48 @@ jobs:
Build.Target: "NOOPT"
Run.Flags: $(run_flags)
Run: $(should_run)
+ EmulatorPkg_X64_FULL_DEBUG:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "DEBUG"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_X64_FULL_RELEASE:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "RELEASE"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_X64_FULL_NOOPT:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "NOOPT"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_DEBUG:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "DEBUG"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_RELEASE:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "RELEASE"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)
+ EmulatorPkg_IA32_FULL_NOOPT:
+ Build.File: "$(package)/PlatformCI/PlatformBuild.py"
+ Build.Arch: "IA32"
+ Build.Flags: "BLD_*_SECURE_BOOT_ENABLE=TRUE"
+ Build.Target: "NOOPT"
+ Run.Flags: $(run_flags)
+ Run: $(should_run)

workspace:
clean: all
diff --git a/EmulatorPkg/PlatformCI/ReadMe.md b/EmulatorPkg/PlatformCI/ReadMe.md
index c51838ec1a..91c40b2093 100644
--- a/EmulatorPkg/PlatformCI/ReadMe.md
+++ b/EmulatorPkg/PlatformCI/ReadMe.md
@@ -6,13 +6,15 @@ to use the same Pytools based build infrastructure locally.
## Supported Configuration Details

This solution for building and running EmulatorPkg has only been validated with Windows 10
-with VS2019 and Ubuntu 18.04 with GCC5 toolchain. Two different firmware builds are
+with VS2019 and Ubuntu 18.04 with GCC5 toolchain. Four different firmware builds are
supported and are described below.

| Configuration name | Architectures | DSC File |Additional Flags |
| :---- | :----- | :---- | :---- |
| IA32 | IA32 | EmulatorPkg.dsc | None |
| X64 | X64 | EmulatorPkg.dsc | None |
+| IA32 Full | IA32 | EmulatorPkg.dsc | SECURE_BOOT_ENABLE=TRUE |
+| X64 Full | X64 | EmulatorPkg.dsc | SECURE_BOOT_ENABLE=TRUE |

## EDK2 Developer environment

diff --git a/ReadMe.rst b/ReadMe.rst
index a16e13547f..c3c8178373 100644
--- a/ReadMe.rst
+++ b/ReadMe.rst
@@ -28,6 +28,8 @@ Microsoft Windows VS2019
============================= ================= ============= ============= ==============
EmulatorPkg_Win_VS2019_ | IA32 |em32d| |em32r| |em32n|
| | X64 |em64d| |em64r| |em64n|
+| | IA32 FULL |em32fd| |em32fr| |em32fn|
+| | X64 FULL |em64fd| |em64fr| |em64fn|
OvmfPkg_Win_VS2019_ | IA32 |op32d| |op32r| |op32n|
| | X64 |op64d| |op64r| |op64n|
| | IA32 X64 |op3264d| |op3264r| |op3264n|
@@ -44,6 +46,8 @@ ArmVirtPkg_Ubuntu_GCC5_ | AARCH64 |avAArch64du| |avAArch64ru| |avA
| | ARM |avArmdu| |avArmru| |avArmnu|
EmulatorPkg_Ubuntu_GCC5_ | IA32 |em32du| |em32ru| |em32nu|
| | X64 |em64du| |em64ru| |em64nu|
+| | IA32 FULL |em32fdu| |em32fru| |em32fnu|
+| | X64 FULL |em64fdu| |em64fru| |em64fnu|
OvmfPkg_Ubuntu_GCC5_ | IA32 |op32du| |op32ru| |op32nu|
| | X64 |op64du| |op64ru| |op64nu|
| | IA32 X64 |op3264du| |op3264ru| |op3264nu|
@@ -319,6 +323,13 @@ use.
.. |em32n| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emu
latorPkg_IA32_NOOPT
.. |em32nu| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emulat
orPkg_IA32_NOOPT

+.. |em32fd| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emu
latorPkg_IA32_FULL_DEBUG
+.. |em32fdu| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emulat
orPkg_IA32_FULL_DEBUG
+.. |em32fr| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emu
latorPkg_IA32_FULL_RELEASE
+.. |em32fru| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emulat
orPkg_IA32_FULL_RELEASE
+.. |em32fn| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emu
latorPkg_IA32_FULL_NOOPT
+.. |em32fnu| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emulat
orPkg_IA32_FULL_NOOPT
+
.. |em64d| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emu
latorPkg_X64_DEBUG
.. |em64du| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emulat
orPkg_X64_DEBUG
.. |em64r| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emu
latorPkg_X64_RELEASE
@@ -326,6 +337,13 @@ use.
.. |em64n| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emu
latorPkg_X64_NOOPT
.. |em64nu| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emulat
orPkg_X64_NOOPT

+.. |em64fd| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emu
latorPkg_X64_FULL_DEBUG
+.. |em64fdu| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emulat
orPkg_X64_FULL_DEBUG
+.. |em64fr| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emu
latorPkg_X64_FULL_RELEASE
+.. |em64fru| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emulat
orPkg_X64_FULL_RELEASE
+.. |em64fn| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emu
latorPkg_X64_FULL_NOOPT
+.. |em64fnu| image:: https://dev.azure.com/tianocore/edk2-
ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20Emulat
orPkg_X64_FULL_NOOPT
+
.. OvmfPkg

.. |TCBZ_2661| image:: https://img.shields.io/bugzilla/2661?baseUrl=https%3A%2F%2Fbugzilla.tianocore.org