Hi, Jones

Could you let me know what's the benefit of putting these Fake FSRT and Fake 
Capsule lib to MdeModulePkg? Why not purely for Ovmf platform?

Thanks
Feng

-----Original Message-----
From: Peter Jones [mailto:pjo...@redhat.com] 
Sent: Saturday, April 11, 2015 03:02
To: edk2-devel@lists.sourceforge.net
Subject: [edk2] [PATCH 09/11] Add a fake ESRT driver to go with Fake Capsule 
driver.

This patch adds a generator for ESRT data.  To create the ESRT, a table is 
allocated during DXE and filled with the current set of updates which would be 
accepted by the FakeCapsuleLib driver.

With this patch, we have a full (if minimal) framework for testing the /other/ 
side of this API; that is, you can deploy a full stack of production-level OS 
and pre-boot firmware update utilities with no special code /inside/ those 
utilities.  To do so you have to augment them with some system for setting 
variables in the gFakeCapsuleHeaderGuid GUID-space, and something to drive your 
test harness (i.e. simulated user input at some level.)

A sample (and somewhat simplified) workflow is something like this:

   [tester]
    - create {gFakeCapsuleHeaderGuid} variables
    - populate fs with updates
    - sets up OS code to be run when we boot up, so we can test it
    - boots the VM
 ,>[Ovmf] <-'  (that's a curved little arrow, you see, from the previous
 |              thing doing work to the current thing doing work)
 |  - lots of stuff  -----,
 | [Ovmf / FakeEsrtDxe] <-'
 |  - GetVariable({gFakeCapsuleHeaderGuid} variables)  |  - 
InstallConfigurationTable(ESRT)  | [Ovmf] <-'
 |  - loads OS
 | [OS] <-'
 |  - reads the status of updates available from ESRT  |  - looks for 
Capsule####/CapsuleLast/CapsuleMax for previous state  |  - reads update files 
it may have available  |  - makes some decisions from the above  |  - decides 
there's an update!
 |  - sets some state and a BootNext variable to start a pre-boot
 |    application to do firmware updates
 |  - reboots
 | [Ovmf] <-'
 |  - GetVariable({gFakeCapsuleHeaderGuid} variables)  |  - 
InstallConfigurationTable(ESRT)  |  - pre-boot application (fwupdate.efi)  | 
[fwupdate.efi] <-'
 |  - Looks for state left from OS utility  |  - reads the firmware files and 
coalesces them into a scatter gather
 |    list with capsule headers as appropriate
 |  - calls UpdateCapsule() ---,
 | [Ovmf / FakeCapsuleLib ] <--'
 |  - SetVariable() on the appropriate {gFakeCapsuleHeaderGuid} variables
 *  - updates ESRT maybe
 |\-- calls EfiResetSystem() maybe
 |  - returns to caller maybe
 | [fwupdate.efi] <--'
 |  - calls EfiResetSystem()
 +------------'

And then at some point [tester] examines according to some criteria to decide 
if the thing being tested worked.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Peter Jones <pjo...@redhat.com>
---
 MdeModulePkg/Universal/FakeEsrtDxe/FakeEsrtDxe.c   | 359 ++++++++++++++++++++
 MdeModulePkg/Universal/FakeEsrtDxe/FakeEsrtDxe.inf |  59 ++++
 2 files changed, 418 insertions(+)

diff --git a/MdeModulePkg/Universal/FakeEsrtDxe/FakeEsrtDxe.c 
b/MdeModulePkg/Universal/FakeEsrtDxe/FakeEsrtDxe.c
new file mode 100644
index 0000000..662d839
--- /dev/null
+++ b/MdeModulePkg/Universal/FakeEsrtDxe/FakeEsrtDxe.c
@@ -0,0 +1,359 @@
+/** @file
+  Fake Dxe Capsule Library instance that just keeps ESRT data in UEFI
+  Variables.
+
+  Copyright 2015 Red Hat, Inc.
+
+  This program and the accompanying materials are licensed and made  
+ available under the terms and conditions of the BSD License which  
+ accompanies this distribution.  The full text of the license may be  
+ found at http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,  
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR  
+ IMPLIED.
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/DebugLib.h>
+#include <Library/Esrt.h>
+#include <Library/FakeCapsuleBase.h>
+#include <Library/MemoryAllocationLib.h> #include <Library/PrintLib.h> 
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Guid/FakeCapsuleBase.h>
+#include <Guid/EventGroup.h>
+
+STATIC EFI_SYSTEM_RESOURCE_TABLE *GlobalEsrt; STATIC UINTN 
+GlobalEsrtSize;
+
+/**
+  Find an ESRT entry by the FwClass GUID
+
+  @param  FwEntryGuid   GUID to use as lookup key
+  @param  FwEntry       Storage space to hole the entry in.
+
+  @return EFI_NOT_FOUND No such entry could be located.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FakeEsrtGetFwEntryByGuid (
+  IN EFI_GUID FwEntryGuid,
+  OUT EFI_SYSTEM_RESOURCE_ENTRY *FwEntry
+  )
+{
+  RETURN_STATUS Status;
+  CHAR16        *VariableName = NULL;
+  VOID          *VariableData = NULL;
+  UINTN         VariableDataSize = 0;
+  UINT32        VariableAttributes;
+  EFI_GUID      VendorGuid = { 0, };
+
+  DEBUG ((EFI_D_VERBOSE, "%a\n", __FUNCTION__));
+
+  Status = FindEsrtVariableByCapsuleGuid (&FwEntryGuid,
+                                          &VendorGuid,
+                                          &VariableName,
+                                          &VariableData,
+                                          &VariableDataSize,
+                                          &VariableAttributes);  if 
+ (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR,
+            "%a: FindEsrtVariableByCapsuleGuid failed: %r\n",
+            __FUNCTION__,
+            Status
+           ));
+    return Status;
+  }
+
+  FreePool (VariableName);
+  CopyMem (FwEntry, VariableData, VariableDataSize);
+  FreePool (VariableData);
+  return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+FakeEsrtUpdateConfigTableEntry (
+  EFI_SYSTEM_RESOURCE_ENTRY *FwEntry
+  )
+{
+  EFI_SYSTEM_RESOURCE_ENTRY *Entry;
+  UINTN                     i;
+
+  if (GlobalEsrt == NULL ||
+      GlobalEsrtSize <= sizeof (EFI_SYSTEM_RESOURCE_TABLE)) {
+    return EFI_NOT_FOUND;
+  }
+
+  Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(GlobalEsrt + 1);  for (i = 0; i 
+ < GlobalEsrt->FwResourceCount; i++) {
+    if (CompareGuid (&FwEntry->FwClass, &Entry[i].FwClass)) {
+      CopyMem (Entry+i, FwEntry, sizeof (*FwEntry));
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+
+//
+// set new values in an ESRT entry
+//
+STATIC
+EFI_STATUS
+EFIAPI
+FakeEsrtUpdateTableEntryByGuid (
+  IN EFI_GUID FwEntryGuid,
+  IN EFI_SYSTEM_RESOURCE_ENTRY *FwEntry
+  )
+{
+  RETURN_STATUS Status;
+  EFI_GUID      VendorGuid = { 0, };
+  CHAR16        *VariableName = L"Esrt0000";
+  VOID          *VariableData = NULL;
+  UINTN         VariableDataSize = sizeof (EFI_SYSTEM_RESOURCE_ENTRY);
+  UINT32        VariableAttributes;
+  UINTN         NEntries = 0;
+  UINT16        VariableNumber = 0;
+
+  DEBUG ((EFI_D_INFO, "%a\n", __FUNCTION__));  Status = 
+ FakeCapsuleCountEntries(&NEntries);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a:%d FakeCapsuleCountEntries(): %r\n",
+            __FUNCTION__, __LINE__, Status));
+    return Status;
+  }
+
+  VariableData = AllocateZeroPool (VariableDataSize);  if 
+ (!VariableData) {
+    DEBUG ((EFI_D_ERROR, "%a:%d AllocateZeroPool(): %r\n",
+            __FUNCTION__, __LINE__, EFI_OUT_OF_RESOURCES));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CopyMem (VariableData, FwEntry, sizeof (EFI_SYSTEM_RESOURCE_ENTRY));  
+ Status = FindEsrtVariableByCapsuleGuid (&FwEntryGuid,
+                                          &VendorGuid,
+                                          &VariableName,
+                                          &VariableData,
+                                          &VariableDataSize,
+                                          &VariableAttributes
+                                          );  FreePool (VariableData);  
+ VariableData = NULL;  if (Status == EFI_NOT_FOUND) {
+    Status = FindFreeNumberName (L"Esrt",
+                                 &gFakeCapsuleHeaderGuid,
+                                 NEntries * 3,
+                                 &VariableNumber);
+    if (EFI_ERROR (Status)) {
+      if (Status == EFI_NOT_FOUND) {
+        Status = EFI_OUT_OF_RESOURCES;
+      }
+      return Status;
+    }
+  }
+
+  UnicodeSPrint (VariableName, StrSize(L"Esrt0000"), L"Esrt%04X",
+                 VariableNumber);
+  Status = gRT->SetVariable(VariableName,
+                            &gFakeCapsuleHeaderGuid,
+                            EFI_VARIABLE_NON_VOLATILE
+                            | EFI_VARIABLE_BOOTSERVICE_ACCESS
+                            | EFI_VARIABLE_RUNTIME_ACCESS,
+                            sizeof (EFI_SYSTEM_RESOURCE_ENTRY),
+                            FwEntry
+                            );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a:%d SetVariable(%s): %r\n",
+            __FUNCTION__, __LINE__, VariableName, Status));  }  
+ FreePool (VariableName);
+
+  Status = FakeEsrtUpdateConfigTableEntry (FwEntry);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a:%d FakeEsrtUpdateConfigTableEntry(): %r\n",
+            __FUNCTION__, __LINE__, Status));
+  }
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+FakeEsrtPopulateTable (
+  )
+{
+  RETURN_STATUS             Status;
+  CHAR16                    *VariableName = NULL;
+  VOID                      *VariableData = NULL;
+  UINTN                     VariableDataSize;
+  UINT32                    VariableAttributes = 0;
+  EFI_GUID                  VendorGuid = { 0, };
+  UINTN                     NEntries = 0;
+  EFI_SYSTEM_RESOURCE_TABLE Esrt;
+  UINTN                     TableSize;
+  EFI_PHYSICAL_ADDRESS      TableAddr = 0;
+  UINT8                     *TableBuf;
+  UINTN                     i;
+  CHAR16                    CapsuleMax[] = L"Capsule0000";
+  UINTN                     NChars;
+  VOID                      *Esre;
+
+  DEBUG ((EFI_D_VERBOSE, "%a\n", __FUNCTION__));  Status = 
+ FakeCapsuleCountEntries(&NEntries);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  VariableDataSize = sizeof (EFI_SYSTEM_RESOURCE_ENTRY);  VariableData 
+ = AllocateZeroPool (VariableDataSize);  if (!VariableData) {
+    DEBUG ((EFI_D_ERROR, "%a:%d AllocateZeroPool(%d) failed\n",
+            __FUNCTION__, __LINE__, VariableDataSize));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  TableSize = ALIGN_VALUE(sizeof (Esrt)
+                          + NEntries * sizeof (EFI_SYSTEM_RESOURCE_ENTRY),
+                          4096
+                          );
+
+  Status = gBS->AllocatePages (AllocateAnyPages,
+                               EfiRuntimeServicesData,
+                               TableSize / 4096,
+                               &TableAddr
+                               );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a:%d AllocatePages(%d) failed: %r\n",
+            __FUNCTION__, __LINE__, TableSize, Status));
+    return Status;
+  }
+  TableBuf = (UINT8 *)(UINTN)TableAddr;
+
+  Esrt.FwResourceVersion = 1;
+  Esrt.FwResourceMax = (TableSize - sizeof (Esrt))
+                       / sizeof (EFI_SYSTEM_RESOURCE_ENTRY);  
+ Esrt.FwResourceCount = 0;
+
+  Esre = TableBuf + sizeof (Esrt);
+
+  for (i = 0; i < NEntries; i++) {
+    Esre = TableBuf + sizeof (Esrt) + sizeof (EFI_SYSTEM_RESOURCE_ENTRY) * i;
+    VariableData = NULL;
+    VariableDataSize = 0;
+    Status = FindEsrtVariableByCapsuleGuid (NULL,
+                                            &VendorGuid,
+                                            &VariableName,
+                                            &VariableData,
+                                            &VariableDataSize,
+                                            &VariableAttributes
+                                            );
+    if (Status == EFI_NOT_FOUND) {
+      Status = EFI_SUCCESS;
+      break;
+    }
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "%a:%d: FindEsrtVariableByCapsuleGuid failed: %r\n",
+              __FUNCTION__, __LINE__, Status));
+      break;
+    }
+    if (VariableData && VariableDataSize) {
+      CopyMem (Esre, VariableData, VariableDataSize);
+      FreePool (VariableData);
+      VariableData = NULL;
+    }
+  }
+  if (VariableName) {
+    FreePool (VariableName);
+    VariableName = NULL;
+  }
+
+  Esrt.FwResourceCount = i;
+  CopyMem (TableBuf, &Esrt, sizeof (Esrt));
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a:%d: Couldn't get variable: %r\n",
+            __FUNCTION__, __LINE__, Status));
+    gBS->FreePages (TableAddr, TableSize / 4096);
+    return Status;
+  }
+
+  Status = gBS->InstallConfigurationTable (&gEfiEsrtTableGuid, 
+ TableBuf);  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a:%d InstallConfigurationTable failed: %r\n",
+            __FUNCTION__, __LINE__, Status));
+    gBS->FreePages (TableAddr, TableSize / 4096);
+    return Status;
+  }
+
+  GlobalEsrt = (EFI_SYSTEM_RESOURCE_TABLE *)TableBuf;  GlobalEsrtSize = 
+ TableSize;
+
+  NChars = UnicodeSPrint (CapsuleMax, sizeof (CapsuleMax), L"Capsule%04X",
+                          NEntries * 3);  if (NChars != 11) {
+    DEBUG ((EFI_D_ERROR, "%a:%d UnicodeSPrint(Capsule####)=%d (should be 
11)\n",
+            __FUNCTION__,__LINE__, NChars));
+    gBS->FreePages (TableAddr, TableSize / 4096);
+    return EFI_ABORTED;
+  }
+  Status = gRT->SetVariable (L"CapsuleMax",
+                             &gEfiCapsuleReportGuid,
+                             EFI_VARIABLE_NON_VOLATILE
+                             | EFI_VARIABLE_BOOTSERVICE_ACCESS
+                             | EFI_VARIABLE_RUNTIME_ACCESS,
+                             NChars * sizeof (CHAR16),
+                             CapsuleMax
+                             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a:%d: SetVariable(CapsuleMax) failed: %r\n",
+            __FUNCTION__, __LINE__, Status));  }
+
+  return Status;
+}
+
+STATIC CONST ESRT_OPERATION_PROTOCOL mFakeEsrtOperationProtocol = {
+  FakeEsrtPopulateTable,
+  FakeEsrtUpdateTableEntryByGuid,
+  FakeEsrtGetFwEntryByGuid,
+};
+
+EFI_STATUS
+EFIAPI
+FakeEsrtDxeEntryPoint (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  RETURN_STATUS Status;
+
+  DEBUG ((EFI_D_VERBOSE, "%a\n", __FUNCTION__));
+
+  /* Ideally this would be called by some /consumer/ of
+   * gEfiEsrtOperationProtocolGuid, but there's not much of that existing
+   * just yet in the actual tiano tree. */  FakeEsrtPopulateTable();
+
+  Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle,
+                                                &gEfiEsrtOperationProtocolGuid,
+                                                &mFakeEsrtOperationProtocol,
+                                                NULL
+                                                );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "%a: InstallMultipleProtocolInterfaces failed: %r\n",
+            __FUNCTION__, Status));
+  }
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/FakeEsrtDxe/FakeEsrtDxe.inf 
b/MdeModulePkg/Universal/FakeEsrtDxe/FakeEsrtDxe.inf
new file mode 100644
index 0000000..bfcffcf
--- /dev/null
+++ b/MdeModulePkg/Universal/FakeEsrtDxe/FakeEsrtDxe.inf
@@ -0,0 +1,59 @@
+## @file
+#  Build a fake ESRT based on capsules available through FakeCapsuleBase.
+#
+#  Copyright 2015 Red Hat, Inc.
+#
+#  This program and the accompanying materials are licensed and made #  
+available under the terms and conditions of the BSD License which #  
+accompanies this distribution. The full text of the license may be #  
+found at http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" 
+BASIS, #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER 
+EXPRESS OR #  IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FakeEsrtDxe
+  FILE_GUID                      = ef3f0157-4c04-493a-8904-cb6bef9a62aa
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = FakeEsrtDxeEntryPoint
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  FakeEsrtDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  PrintLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiRuntimeServicesTableLib
+  FakeCapsuleBase
+
+[Protocols]
+  gEfiEsrtOperationProtocolGuid
+
+[Guids]
+  gEfiCapsuleReportGuid
+  gEfiEventReadyToBootGuid
+  gEfiEsrtTableGuid
+  gFakeCapsuleHeaderGuid
+
+[Depex]
+  gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
--
2.3.5


------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to