[AMD Official Use Only - General]

Correct email address
Reviewed-by: Abner Chang <abner.ch...@amd.com>

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Chang,
> Abner via groups.io
> Sent: Friday, May 5, 2023 8:56 AM
> To: Nickle Wang <nick...@nvidia.com>; devel@edk2.groups.io
> Cc: Igor Kulchytskyy <ig...@ami.com>
> Subject: Re: [edk2-devel] [edk2-redfish-client][PATCH 2/8] RedfishClientPkg:
> Add EDKII ETag driver
> 
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
> 
> 
> [AMD Official Use Only - General]
> 
> Reviewed-by: Abner Chang <abner.ch...@hpe.com>
> 
> > -----Original Message-----
> > From: Nickle Wang <nick...@nvidia.com>
> > Sent: Thursday, May 4, 2023 10:22 PM
> > To: devel@edk2.groups.io
> > Cc: Chang, Abner <abner.ch...@amd.com>; Igor Kulchytskyy
> > <ig...@ami.com>
> > Subject: [edk2-redfish-client][PATCH 2/8] RedfishClientPkg: Add EDKII
> > ETag driver
> >
> > Caution: This message originated from an External Source. Use proper
> > caution when opening attachments, clicking links, or responding.
> >
> >
> > Implement EDKII ETag protocol to manipulate ETag of HTTP content.
> >
> > Signed-off-by: Nickle Wang <nick...@nvidia.com>
> > Cc: Abner Chang <abner.ch...@amd.com>
> > Cc: Igor Kulchytskyy <ig...@ami.com>
> > ---
> >  .../RedfishETagDxe/RedfishETagDxe.inf         |  45 +
> >  .../Protocol/EdkIIRedfishETagProtocol.h       |  76 ++
> >  .../RedfishETagDxe/RedfishETagDxe.h           |  70 ++
> >  .../RedfishETagDxe/RedfishETagDxe.c           | 772 ++++++++++++++++++
> >  4 files changed, 963 insertions(+)
> >  create mode 100644
> RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.inf
> >  create mode 100644
> > RedfishClientPkg/Include/Protocol/EdkIIRedfishETagProtocol.h
> >  create mode 100644 RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.h
> >  create mode 100644 RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.c
> >
> > diff --git a/RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.inf
> > b/RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.inf
> > new file mode 100644
> > index 00000000..e29a1045
> > --- /dev/null
> > +++ b/RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.inf
> > @@ -0,0 +1,45 @@
> > +## @file
> > +#
> > +#  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> #
> > +#
> > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > +
> > +[Defines]
> > +  INF_VERSION               = 0x0001000b
> > +  BASE_NAME                 = RedfishETagDxe
> > +  FILE_GUID                 = F7BB0BB2-9796-485F-9F00-C0EB47E9F92B
> > +  MODULE_TYPE               = DXE_DRIVER
> > +  VERSION_STRING            = 1.0
> > +  ENTRY_POINT               = RedfishETagDriverEntryPoint
> > +  UNLOAD_IMAGE              = RedfishETagDriverUnload
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  MdeModulePkg/MdeModulePkg.dec
> > +  RedfishPkg/RedfishPkg.dec
> > +  RedfishClientPkg/RedfishClientPkg.dec
> > +
> > +[Sources]
> > +  RedfishETagDxe.h
> > +  RedfishETagDxe.c
> > +
> > +[LibraryClasses]
> > +  BaseLib
> > +  BaseMemoryLib
> > +  DebugLib
> > +  MemoryAllocationLib
> > +  UefiLib
> > +  UefiBootServicesTableLib
> > +  UefiRuntimeServicesTableLib
> > +  UefiDriverEntryPoint
> > +
> > +[Protocols]
> > +  gEdkIIRedfishETagProtocolGuid           ## PRODUCED ##
> > +
> > +[Guids]
> > +  gEfiEventExitBootServicesGuid           ## CONSUMES ## Event
> > +
> > +[Depex]
> > +  TRUE
> > diff --git
> > a/RedfishClientPkg/Include/Protocol/EdkIIRedfishETagProtocol.h
> > b/RedfishClientPkg/Include/Protocol/EdkIIRedfishETagProtocol.h
> > new file mode 100644
> > index 00000000..4e10965a
> > --- /dev/null
> > +++ b/RedfishClientPkg/Include/Protocol/EdkIIRedfishETagProtocol.h
> > @@ -0,0 +1,76 @@
> > +/** @file
> > +  This file defines the EDKII_REDFISH_FEATURE_PROTOCOL interface.
> > +
> > +  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> > +
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#ifndef EDKII_REDFISH_ETAG_PROTOCOL_H_ #define
> > +EDKII_REDFISH_ETAG_PROTOCOL_H_
> > +
> > +typedef struct _EDKII_REDFISH_ETAG_PROTOCOL
> > +EDKII_REDFISH_ETAG_PROTOCOL;
> > +
> > +/**
> > +  Get ETag string by given URI
> > +
> > +  @param[in]   This                    Pointer to 
> > EDKII_REDFISH_ETAG_PROTOCOL
> > instance.
> > +  @param[in]   Uri                     Target URI to search.
> > +  @param[out]  ETag                    The ETag string to corresponding 
> > URI.
> > +
> > +  @retval EFI_SUCCESS                  The ETag is found successfully.
> > +  @retval EFI_INVALID_PARAMETER        Invalid parameter is given.
> > +
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EDKII_REDFISH_ETAG_PROTOCOL_GET)(
> > +  IN  EDKII_REDFISH_ETAG_PROTOCOL *This,
> > +  IN  CHAR8                       *Uri,
> > +  OUT CHAR8                       **ETag
> > +  );
> > +
> > +/**
> > +  Keep ETag string which maps to given Uri.
> > +
> > +  @param[in]   This                Pointer to EDKII_REDFISH_ETAG_PROTOCOL
> > instance.
> > +  @param[in]   Uri                 The target Uri which related to ETag.
> > +  @param[in]   ETag                The ETag to add. If ETag is NULL, the 
> > record of
> > correspoonding URI will be removed.
> > +
> > +  @retval EFI_SUCCESS              This handler has been stoped 
> > successfully.
> > +  @retval Others                   Some error happened.
> > +
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EDKII_REDFISH_ETAG_PROTOCOL_SET)(
> > +  IN  EDKII_REDFISH_ETAG_PROTOCOL   *This,
> > +  IN  CHAR8                         *Uri,
> > +  IN  CHAR8                         *ETag
> > +  );
> > +
> > +/**
> > +  Refresh the ETag database and save database to variable.
> > +
> > +  @param[in]   This                Pointer to EDKII_REDFISH_ETAG_PROTOCOL
> > instance.
> > +
> > +  @retval EFI_SUCCESS              This handler has been stoped 
> > successfully.
> > +  @retval Others                   Some error happened.
> > +
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EDKII_REDFISH_ETAG_PROTOCOL_FLUSH)(
> > +  IN  EDKII_REDFISH_ETAG_PROTOCOL    *This
> > +  );
> > +
> > +struct _EDKII_REDFISH_ETAG_PROTOCOL {
> > +  EDKII_REDFISH_ETAG_PROTOCOL_GET      Get;
> > +  EDKII_REDFISH_ETAG_PROTOCOL_SET      Set;
> > +  EDKII_REDFISH_ETAG_PROTOCOL_FLUSH    Flush;
> > +};
> > +
> > +extern EFI_GUID  gEdkIIRedfishETagProtocolGuid;
> > +
> > +#endif
> > diff --git a/RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.h
> > b/RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.h
> > new file mode 100644
> > index 00000000..6dffa9d7
> > --- /dev/null
> > +++ b/RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.h
> > @@ -0,0 +1,70 @@
> > +/** @file
> > +  Common header file for RedfishETagDxe driver.
> > +
> > +  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> > +
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#ifndef REDFISH_ETAG_DXE_H_
> > +#define REDFISH_ETAG_DXE_H_
> > +
> > +#include <Uefi.h>
> > +
> > +//
> > +// Libraries
> > +//
> > +#include <Library/BaseLib.h>
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/DebugLib.h>
> > +
> > +#include <Library/MemoryAllocationLib.h> #include
> > +<Library/UefiBootServicesTableLib.h>
> > +#include <Library/UefiDriverEntryPoint.h> #include
> > +<Library/UefiLib.h> #include <Library/UefiRuntimeServicesTableLib.h>
> > +
> > +#include <Protocol/EdkIIRedfishETagProtocol.h>
> > +
> > +#include <Guid/VariableFormat.h>
> > +
> > +#define ETAG_VARIABLE_NAME  L"RedfishETag"
> > +#define IS_EMPTY_STRING(a)  ((a) == NULL || (a)[0] == '\0') #define
> > +ETAG_DEBUG_ENABLED  0x00
> > +
> > +//
> > +// Definition of REDFISH_ETAG_RECORD
> > +//
> > +typedef struct {
> > +  LIST_ENTRY    List;
> > +  CHAR8         *Uri;
> > +  CHAR8         *ETag;
> > +  UINTN         Size;
> > +} REDFISH_ETAG_RECORD;
> > +
> > +#define REDFISH_ETAG_RECORD_FROM_LIST(a)  BASE_CR (a,
> > +REDFISH_ETAG_RECORD, List)
> > +
> > +//
> > +// Definition of REDFISH_ETAG_LIST
> > +//
> > +typedef struct {
> > +  LIST_ENTRY    Listheader;
> > +  UINTN         TotalSize;
> > +  UINTN         Count;
> > +} REDFISH_ETAG_LIST;
> > +
> > +//
> > +// Definition of REDFISH_ETAG_PRIVATE_DATA // typedef struct {
> > +  EFI_HANDLE                     ImageHandle;
> > +  REDFISH_ETAG_LIST              ETagList;
> > +  EDKII_REDFISH_ETAG_PROTOCOL    Protocol;
> > +  EFI_STRING                     VariableName;
> > +  EFI_EVENT                      Event;
> > +} REDFISH_ETAG_PRIVATE_DATA;
> > +
> > +#define REDFISH_ETAG_PRIVATE_FROM_THIS(a)  BASE_CR (a,
> > +REDFISH_ETAG_PRIVATE_DATA, Protocol)
> > +
> > +#endif
> > diff --git a/RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.c
> > b/RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.c
> > new file mode 100644
> > index 00000000..af920afc
> > --- /dev/null
> > +++ b/RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.c
> > @@ -0,0 +1,772 @@
> > +/** @file
> > +
> > +  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> > +
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include "RedfishETagDxe.h"
> > +
> > +REDFISH_ETAG_PRIVATE_DATA  *mRedfishETagPrivate = NULL;
> > +
> > +/**
> > +  Release REDFISH_ETAG_RECORD resource
> > +
> > +  @param[in]    Record    Pointer to REDFISH_ETAG_RECORD instance
> > +
> > +  @retval EFI_SUCCESS             REDFISH_ETAG_RECORD is released
> > successfully.
> > +  @retval EFI_INVALID_PARAMETER   Record is NULL
> > +
> > +**/
> > +EFI_STATUS
> > +ReleaseETagRecord (
> > +  IN REDFISH_ETAG_RECORD  *Record
> > +  )
> > +{
> > +  if (Record == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  if (Record->Uri != NULL) {
> > +    FreePool (Record->Uri);
> > +  }
> > +
> > +  if (Record->ETag != NULL) {
> > +    FreePool (Record->ETag);
> > +  }
> > +
> > +  FreePool (Record);
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Create new Etag resource.
> > +
> > +  @param[in]    Uri   The URI string matching to this ETAG.
> > +  @param[in]    ETag  ETAG string.
> > +
> > +  @retval REDFISH_ETAG_RECORD *   Pointer to newly created ETAG.
> > +  @retval NULL                    No memory available.
> > +
> > +**/
> > +REDFISH_ETAG_RECORD *
> > +NewETagRecord (
> > +  IN  CHAR8  *Uri,
> > +  IN  CHAR8  *ETag
> > +  )
> > +{
> > +  REDFISH_ETAG_RECORD  *NewRecord;
> > +  UINTN                Size;
> > +
> > +  if (IS_EMPTY_STRING (Uri) || IS_EMPTY_STRING (ETag)) {
> > +    return NULL;
> > +  }
> > +
> > +  NewRecord = AllocateZeroPool (sizeof (REDFISH_ETAG_RECORD));  if
> > + (NewRecord == NULL) {
> > +    return NULL;
> > +  }
> > +
> > +  Size           = AsciiStrSize (Uri);
> > +  NewRecord->Uri = AllocateCopyPool (Size, Uri);  if (NewRecord->Uri
> > + ==
> > + NULL) {
> > +    goto ON_ERROR;
> > +  }
> > +
> > +  NewRecord->Size = Size;
> > +  Size            = AsciiStrSize (ETag);
> > +  NewRecord->ETag = AllocateCopyPool (Size, ETag);  if
> > + (NewRecord->ETag == NULL) {
> > +    goto ON_ERROR;
> > +  }
> > +
> > +  NewRecord->Size += Size;
> > +  return NewRecord;
> > +
> > +ON_ERROR:
> > +
> > +  if (NewRecord != NULL) {
> > +    ReleaseETagRecord (NewRecord);
> > +  }
> > +
> > +  return NULL;
> > +}
> > +
> > +/**
> > +  Add new ETAG by given URI and ETAG string to specify List.
> > +
> > +  @param[in]    List  Target ETAG list to add.
> > +  @param[in]    Uri   The URI string matching to this ETAG.
> > +  @param[in]    ETag  ETAG string.
> > +
> > +  @retval EFI_SUCCESS   ETAG recourd is added.
> > +  @retval Others        Fail to add ETAG.
> > +
> > +**/
> > +EFI_STATUS
> > +AddETagRecord (
> > +  IN  REDFISH_ETAG_LIST  *List,
> > +  IN  CHAR8              *Uri,
> > +  IN  CHAR8              *ETag
> > +  )
> > +{
> > +  REDFISH_ETAG_RECORD  *NewRecord;
> > +
> > +  if ((List == NULL) || IS_EMPTY_STRING (Uri) || IS_EMPTY_STRING (ETag))
> {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  NewRecord = NewETagRecord (Uri, ETag);  if (NewETagRecord == NULL) {
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  InsertTailList (&List->Listheader, &NewRecord->List);
> > + ++List->Count;
> > + List->TotalSize += NewRecord->Size;
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Delete an ETAG by given ETAG instance.
> > +
> > +  @param[in]    List    Target ETAG list to be removed.
> > +  @param[in]    Record  Pointer to the instance to be deleted.
> > +
> > +  @retval EFI_SUCCESS   ETAG recourd is removed.
> > +  @retval Others        Fail to add ETAG.
> > +
> > +**/
> > +EFI_STATUS
> > +DeleteETagRecord (
> > +  IN  REDFISH_ETAG_LIST    *List,
> > +  IN  REDFISH_ETAG_RECORD  *Record
> > +  )
> > +{
> > +  if ((List == NULL) || (Record == NULL)) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  RemoveEntryList (&Record->List);
> > +  --List->Count;
> > +  List->TotalSize -= Record->Size;
> > +
> > +  return ReleaseETagRecord (Record);
> > +}
> > +
> > +/**
> > +  Search on given ListHeader for given URI string.
> > +
> > +  @param[in]    ListHeader  Target list to search.
> > +  @param[in]    Uri         Target URI to search.
> > +
> > +  @retval REDFISH_ETAG_RECORD   Target ETAG is found.
> > +  @retval NULL                  No ETAG with given URI is found.
> > +
> > +**/
> > +REDFISH_ETAG_RECORD *
> > +FindETagRecord (
> > +  IN  LIST_ENTRY  *ListHeader,
> > +  IN  CHAR8       *Uri
> > +  )
> > +{
> > +  LIST_ENTRY           *List;
> > +  REDFISH_ETAG_RECORD  *Record;
> > +
> > +  if (IsListEmpty (ListHeader)) {
> > +    return NULL;
> > +  }
> > +
> > +  Record = NULL;
> > +  List   = GetFirstNode (ListHeader);
> > +  while (!IsNull (ListHeader, List)) {
> > +    Record = REDFISH_ETAG_RECORD_FROM_LIST (List);
> > +
> > +    if (AsciiStrCmp (Record->Uri, Uri) == 0) {
> > +      return Record;
> > +    }
> > +
> > +    List = GetNextNode (ListHeader, List);  }
> > +
> > +  return NULL;
> > +}
> > +
> > +#if ETAG_DEBUG_ENABLED
> > +
> > +/**
> > +  Debug output the ETAG list.
> > +
> > +  @param[in]    ETagList  Target list to dump
> > +  @param[in]    Msg       Debug message string.
> > +
> > +  @retval EFI_SUCCESS             Debug dump finished.
> > +  @retval EFI_INVALID_PARAMETER   ETagList is NULL.
> > +
> > +**/
> > +EFI_STATUS
> > +DumpETagList (
> > +  IN  REDFISH_ETAG_LIST  *ETagList,
> > +  IN  EFI_STRING         Msg
> > +  )
> > +{
> > +  LIST_ENTRY           *List;
> > +  REDFISH_ETAG_RECORD  *Record;
> > +
> > +  if (ETagList == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  if (!IS_EMPTY_STRING (Msg)) {
> > +    DEBUG ((DEBUG_ERROR, "%s\n", Msg));  }
> > +
> > +  if (IsListEmpty (&ETagList->Listheader)) {
> > +    DEBUG ((DEBUG_INFO, "ETag list is empty\n"));
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  DEBUG ((DEBUG_INFO, "Count: %d Total Size: %d\n", ETagList->Count,
> > + ETagList->TotalSize));  Record = NULL;
> > +  List   = GetFirstNode (&ETagList->Listheader);
> > +  while (!IsNull (&ETagList->Listheader, List)) {
> > +    Record = REDFISH_ETAG_RECORD_FROM_LIST (List);
> > +
> > +    DEBUG ((DEBUG_INFO, "ETag: %a Uri: %a Size: %d\n", Record->ETag,
> > + Record->Uri, Record->Size));
> > +
> > +    List = GetNextNode (&ETagList->Listheader, List);  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Debug output raw data buffer.
> > +
> > +  @param[in]    Buffer      Debug output data buffer.
> > +  @param[in]    BufferSize  The size of Buffer in byte.
> > +
> > +  @retval EFI_SUCCESS             Debug dump finished.
> > +  @retval EFI_INVALID_PARAMETER   Buffer is NULL.
> > +
> > +**/
> > +EFI_STATUS
> > +DumpRawBuffer (
> > +  IN  CHAR8  *Buffer,
> > +  IN  UINTN  BufferSize
> > +  )
> > +{
> > +  UINTN  Index;
> > +
> > +  if (Buffer == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Index = 0;
> > +
> > +  DEBUG ((DEBUG_ERROR, "Buffer size: %d\n", BufferSize));  while
> > + (Buffer[Index] != '\0') {
> > +    DEBUG ((DEBUG_ERROR, "(%d) %c ", (Index + 1), Buffer[Index]));
> > +
> > +    ++Index;
> > +  }
> > +
> > +  DEBUG ((DEBUG_ERROR, "\n"));
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +#endif
> > +
> > +/**
> > +  Release all ETag from list.
> > +
> > +  @param[in]    ETagList    The list to be released.
> > +
> > +  @retval EFI_SUCCESS             All etag is released.
> > +  @retval EFI_INVALID_PARAMETER   ETagList is NULL.
> > +
> > +**/
> > +EFI_STATUS
> > +ReleaseETagList (
> > +  IN  REDFISH_ETAG_LIST  *ETagList
> > +  )
> > +{
> > +  LIST_ENTRY           *List;
> > +  LIST_ENTRY           *Next;
> > +  REDFISH_ETAG_RECORD  *Record;
> > +
> > +  if (ETagList == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  if (IsListEmpty (&ETagList->Listheader)) {
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  Record = NULL;
> > +  Next   = NULL;
> > +  List   = GetFirstNode (&ETagList->Listheader);
> > +  while (!IsNull (&ETagList->Listheader, List)) {
> > +    Record = REDFISH_ETAG_RECORD_FROM_LIST (List);
> > +    Next   = GetNextNode (&ETagList->Listheader, List);
> > +
> > +    DeleteETagRecord (ETagList, Record);
> > +
> > +    List = Next;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Save etag in list to UEFI variable.
> > +
> > +  @param[in]    ETagList      The list to be saved.
> > +  @param[in]    VariableName  The UEFI variable name.
> > +
> > +  @retval EFI_SUCCESS             All etag is saved.
> > +  @retval EFI_INVALID_PARAMETER   VariableName or ETagList is NULL.
> > +
> > +**/
> > +EFI_STATUS
> > +SaveETagList (
> > +  IN  REDFISH_ETAG_LIST  *ETagList,
> > +  IN  EFI_STRING         VariableName
> > +  )
> > +{
> > +  LIST_ENTRY           *List;
> > +  REDFISH_ETAG_RECORD  *Record;
> > +  CHAR8                *VarData;
> > +  VOID                 *Data;
> > +  CHAR8                *Seeker;
> > +  UINTN                VarSize;
> > +  UINTN                StrSize;
> > +  EFI_STATUS           Status;
> > +
> > +  if ((ETagList == NULL) || IS_EMPTY_STRING (VariableName)) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  if (IsListEmpty (&ETagList->Listheader)) {
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  //
> > +  // Caculate the total size we need to keep ETag list.
> > +  //
> > +  VarSize = ETagList->TotalSize + 1; // terminator character  VarData
> > + = AllocateZeroPool (VarSize);  if (VarData == NULL) {
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  Seeker = VarData;
> > +  Record = NULL;
> > +  List   = GetFirstNode (&ETagList->Listheader);
> > +  while (!IsNull (&ETagList->Listheader, List)) {
> > +    Record = REDFISH_ETAG_RECORD_FROM_LIST (List);
> > +
> > +    StrSize = AsciiStrSize (Record->Uri);
> > +    CopyMem (Seeker, Record->Uri, StrSize);
> > +
> > +    Seeker += (StrSize - 1);
> > +    *Seeker = '|';
> > +    ++Seeker;
> > +
> > +    StrSize = AsciiStrSize (Record->ETag);
> > +    CopyMem (Seeker, Record->ETag, StrSize);
> > +
> > +    Seeker += (StrSize - 1);
> > +    *Seeker = '\n';
> > +
> > +    ++Seeker;
> > +
> > +    List = GetNextNode (&ETagList->Listheader, List);  }
> > +
> > +  *Seeker = '\0';
> > +
> > + #if ETAG_DEBUG_ENABLED
> > +  DumpRawBuffer (VarData, VarSize);
> > + #endif
> > +
> > +  ASSERT (((UINTN)Seeker - (UINTN)VarData + 1) == VarSize);
> > +
> > +  //
> > +  // Check if variable exists already. If yes, remove it first.
> > +  //
> > +  Status = GetVariable2 (
> > +             VariableName,
> > +             &gEfiCallerIdGuid,
> > +             (VOID *)&Data,
> > +             NULL
> > +             );
> > +  if (!EFI_ERROR (Status)) {
> > +    FreePool (Data);
> > +    gRT->SetVariable (VariableName, &gEfiCallerIdGuid,
> > + VARIABLE_ATTRIBUTE_NV_BS, 0, NULL);  }
> > +
> > +  return gRT->SetVariable (VariableName, &gEfiCallerIdGuid,
> > +VARIABLE_ATTRIBUTE_NV_BS, VarSize, (VOID *)VarData); }
> > +
> > +/**
> > +  Read etag from UEFI variable if it exists.
> > +
> > +  @param[in]    ETagList      The list to be loaded.
> > +  @param[in]    VariableName  The UEFI variable name.
> > +
> > +  @retval EFI_SUCCESS             All etag is read successfully.
> > +  @retval EFI_INVALID_PARAMETER   VariableName or ETagList is NULL.
> > +  @retval EFI_NOT_FOUND           No etag is found on UEFI variable.
> > +
> > +**/
> > +EFI_STATUS
> > +InitialETagList (
> > +  IN  REDFISH_ETAG_LIST  *ETagList,
> > +  IN  EFI_STRING         VariableName
> > +  )
> > +{
> > +  CHAR8       *VarData;
> > +  CHAR8       *UriPointer;
> > +  CHAR8       *ETagPointer;
> > +  CHAR8       *Seeker;
> > +  UINTN       VariableSize;
> > +  EFI_STATUS  Status;
> > +
> > +  if ((ETagList == NULL) || IS_EMPTY_STRING (VariableName)) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  //
> > +  // Check if variable exists already.
> > +  //
> > +  Status = GetVariable2 (
> > +             VariableName,
> > +             &gEfiCallerIdGuid,
> > +             (VOID *)&VarData,
> > +             &VariableSize
> > +             );
> > +  if (EFI_ERROR (Status)) {
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  Seeker      = VarData;
> > +  UriPointer  = VarData;
> > +  ETagPointer = VarData;
> > +  while (*Seeker != '\0') {
> > +    //
> > +    // Find URI
> > +    //
> > +    Seeker = AsciiStrStr (UriPointer, "|");
> > +    if (Seeker == NULL) {
> > +      DEBUG ((DEBUG_ERROR, "%a, data corrupted\n", __FUNCTION__));
> > +      Status = EFI_DEVICE_ERROR;
> > +      goto ON_ERROR;
> > +    }
> > +
> > +    *Seeker     = '\0';
> > +    ETagPointer = ++Seeker;
> > +
> > +    //
> > +    // Find ETAG
> > +    //
> > +    Seeker = AsciiStrStr (ETagPointer, "\n");
> > +    if (Seeker == NULL) {
> > +      DEBUG ((DEBUG_ERROR, "%a, data corrupted\n", __FUNCTION__));
> > +      Status = EFI_DEVICE_ERROR;
> > +      goto ON_ERROR;
> > +    }
> > +
> > +    *Seeker = '\0';
> > +
> > +    AddETagRecord (ETagList, UriPointer, ETagPointer);
> > +
> > +    UriPointer = ++Seeker;
> > +  }
> > +
> > + #if ETAG_DEBUG_ENABLED
> > +  DumpETagList (ETagList, L"Initial ETag List from Variable"); #endif
> > +
> > +  Status = EFI_SUCCESS;
> > +
> > +ON_ERROR:
> > +
> > +  FreePool (VarData);
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Get ETag string by given URI
> > +
> > +  @param[in]   This                    Pointer to 
> > EDKII_REDFISH_ETAG_PROTOCOL
> > instance.
> > +  @param[in]   Uri                     Target URI to search.
> > +  @param[out]  ETag                    The ETag string to corresponding 
> > URI.
> > +
> > +  @retval EFI_SUCCESS                  The ETag is found successfully.
> > +  @retval EFI_INVALID_PARAMETER        Invalid parameter is given.
> > +
> > +**/
> > +EFI_STATUS
> > +RedfishETagGet (
> > +  IN  EDKII_REDFISH_ETAG_PROTOCOL  *This,
> > +  IN  CHAR8                        *Uri,
> > +  OUT CHAR8                        **ETag
> > +  )
> > +{
> > +  REDFISH_ETAG_RECORD        *Target;
> > +  REDFISH_ETAG_PRIVATE_DATA  *Private;
> > +
> > +  if ((This == NULL) || IS_EMPTY_STRING (Uri) || (ETag == NULL)) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Private = REDFISH_ETAG_PRIVATE_FROM_THIS (This);
> > +
> > +  *ETag = NULL;
> > +
> > +  Target = FindETagRecord (&Private->ETagList.Listheader, Uri);  if
> > + (Target == NULL) {
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  *ETag = AllocateCopyPool (AsciiStrSize (Target->ETag),
> > + Target->ETag);
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Keep ETag string which maps to given Uri.
> > +
> > +  @param[in]   This                Pointer to EDKII_REDFISH_ETAG_PROTOCOL
> > instance.
> > +  @param[in]   Uri                 The target Uri which related to ETag.
> > +  @param[in]   ETag                The ETag to add. If ETag is NULL, the 
> > record of
> > correspoonding URI will be removed.
> > +
> > +  @retval EFI_SUCCESS              This handler has been stoped 
> > successfully.
> > +  @retval Others                   Some error happened.
> > +
> > +**/
> > +EFI_STATUS
> > +RedfishETagSet (
> > +  IN  EDKII_REDFISH_ETAG_PROTOCOL  *This,
> > +  IN  CHAR8                        *Uri,
> > +  IN  CHAR8                        *ETag  OPTIONAL
> > +  )
> > +{
> > +  REDFISH_ETAG_RECORD        *Target;
> > +  REDFISH_ETAG_PRIVATE_DATA  *Private;
> > +  EFI_STATUS                 Status;
> > +
> > +  if ((This == NULL) || IS_EMPTY_STRING (Uri)) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Private = REDFISH_ETAG_PRIVATE_FROM_THIS (This);
> > +
> > +  Status = EFI_NOT_FOUND;
> > +  Target = FindETagRecord (&Private->ETagList.Listheader, Uri);  if
> > + (Target != NULL) {
> > +    //
> > +    // Remove old one and create new one.
> > +    //
> > +    Status = DeleteETagRecord (&Private->ETagList, Target);  }
> > +
> > +  //
> > +  // When ETag is NULL, it means that we want to remov this record.
> > +  //
> > +  if (ETag == NULL) {
> > +    return Status;
> > +  }
> > +
> > +  return AddETagRecord (&Private->ETagList, Uri, ETag); }
> > +
> > +/**
> > +  Refresh the ETag database and save database to variable.
> > +
> > +  @param[in]   This                Pointer to EDKII_REDFISH_ETAG_PROTOCOL
> > instance.
> > +
> > +  @retval EFI_SUCCESS              This handler has been stoped 
> > successfully.
> > +  @retval Others                   Some error happened.
> > +
> > +**/
> > +EFI_STATUS
> > +RedfishETagFlush (
> > +  IN  EDKII_REDFISH_ETAG_PROTOCOL  *This
> > +  )
> > +{
> > +  REDFISH_ETAG_PRIVATE_DATA  *Private;
> > +  EFI_STATUS                 Status;
> > +
> > +  if (This == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Private = REDFISH_ETAG_PRIVATE_FROM_THIS (This);
> > +
> > +  Status = SaveETagList (&Private->ETagList, Private->VariableName);
> > + if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_ERROR, "%a, save ETag list to variable: %s failed:
> > + %r\n", __FUNCTION__, Private->VariableName, Status));  }
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Callback function executed when the ExitBootService event group is
> > signaled.
> > +
> > +  @param[in]   Event    Event whose notification function is being invoked.
> > +  @param[out]  Context  Pointer to the Context buffer
> > +
> > +**/
> > +VOID
> > +EFIAPI
> > +RedfishETagOnExitBootService (
> > +  IN  EFI_EVENT  Event,
> > +  OUT VOID       *Context
> > +  )
> > +{
> > +  //
> > +  // Memory is about to be released. Keep list into variable.
> > +  //
> > +  RedfishETagFlush (&mRedfishETagPrivate->Protocol); }
> > +
> > +/**
> > +  Unloads an image.
> > +
> > +  @param[in]  ImageHandle           Handle that identifies the image to be
> > unloaded.
> > +
> > +  @retval EFI_SUCCESS           The image has been unloaded.
> > +  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image
> > handle.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +RedfishETagDriverUnload (
> > +  IN EFI_HANDLE  ImageHandle
> > +  )
> > +{
> > +  EFI_STATUS  Status;
> > +
> > +  if (mRedfishETagPrivate != NULL) {
> > +    Status = gBS->UninstallProtocolInterface (
> > +                    mRedfishETagPrivate->ImageHandle,
> > +                    &gEdkIIRedfishETagProtocolGuid,
> > +                    (VOID *)&mRedfishETagPrivate->Protocol
> > +                    );
> > +    if (EFI_ERROR (Status)) {
> > +      DEBUG ((DEBUG_ERROR, "%a, can not uninstall
> > gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status));
> > +      ASSERT (FALSE);
> > +    }
> > +
> > +    ReleaseETagList (&mRedfishETagPrivate->ETagList);
> > +
> > +    if (mRedfishETagPrivate->VariableName != NULL) {
> > +      FreePool (mRedfishETagPrivate->VariableName);
> > +    }
> > +
> > +    if (mRedfishETagPrivate->Event != NULL) {
> > +      gBS->CloseEvent (mRedfishETagPrivate->Event);
> > +    }
> > +
> > +    FreePool (mRedfishETagPrivate);
> > +    mRedfishETagPrivate = NULL;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +//
> > +// EDKII_REDFISH_ETAG_PROTOCOL.
> > +//
> > +EDKII_REDFISH_ETAG_PROTOCOL  mRedfishETagProtocol = {
> > +  RedfishETagGet,
> > +  RedfishETagSet,
> > +  RedfishETagFlush
> > +};
> > +
> > +/**
> > +  This is the declaration of an EFI image entry point. This entry
> > +point is
> > +  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers
> > +including
> > +  both device drivers and bus drivers.
> > +
> > +  @param[in]  ImageHandle       The firmware allocated handle for the UEFI
> > image.
> > +  @param[in]  SystemTable       A pointer to the EFI System Table.
> > +
> > +  @retval EFI_SUCCESS           The operation completed successfully.
> > +  @retval Others                An unexpected error occurred.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +RedfishETagDriverEntryPoint (
> > +  IN EFI_HANDLE        ImageHandle,
> > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > +  )
> > +{
> > +  EFI_STATUS  Status;
> > +
> > +  mRedfishETagPrivate = AllocateZeroPool (sizeof
> > + (REDFISH_ETAG_PRIVATE_DATA));  if (mRedfishETagPrivate == NULL) {
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  InitializeListHead (&mRedfishETagPrivate->ETagList.Listheader);
> > +  mRedfishETagPrivate->VariableName = AllocateCopyPool (StrSize
> > + (ETAG_VARIABLE_NAME), ETAG_VARIABLE_NAME);  if
> > (mRedfishETagPrivate->VariableName == NULL) {
> > +    goto ON_ERROR;
> > +  }
> > +
> > +  mRedfishETagPrivate->ImageHandle = ImageHandle;  CopyMem
> > + (&mRedfishETagPrivate->Protocol, &mRedfishETagProtocol, sizeof
> > + (EDKII_REDFISH_ETAG_PROTOCOL));
> > +
> > +  Status = gBS->InstallProtocolInterface (
> > +                  &ImageHandle,
> > +                  &gEdkIIRedfishETagProtocolGuid,
> > +                  EFI_NATIVE_INTERFACE,
> > +                  (VOID *)&mRedfishETagPrivate->Protocol
> > +                  );
> > +  if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_ERROR, "%a, can not install
> > gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status));
> > +    ASSERT (FALSE);
> > +    goto ON_ERROR;
> > +  }
> > +
> > +  //
> > +  // Create Exit Boot Service event.
> > +  //
> > +  Status = gBS->CreateEventEx (
> > +                  EVT_NOTIFY_SIGNAL,
> > +                  TPL_CALLBACK,
> > +                  RedfishETagOnExitBootService,
> > +                  NULL,
> > +                  &gEfiEventExitBootServicesGuid,
> > +                  &mRedfishETagPrivate->Event
> > +                  );
> > +  if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_ERROR, "%a: Fail to register Exit Boot Service
> > + event.",
> > __FUNCTION__));
> > +    goto ON_ERROR;
> > +  }
> > +
> > +  //
> > +  // Read existing record from variable.
> > +  //
> > +  Status = InitialETagList (&mRedfishETagPrivate->ETagList,
> > + mRedfishETagPrivate->VariableName);
> > +  if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_INFO, "%a, Initial ETag List: %r\n", __FUNCTION__,
> > + Status));  }
> > +
> > +  return EFI_SUCCESS;
> > +
> > +ON_ERROR:
> > +
> > +  RedfishETagDriverUnload (ImageHandle);
> > +
> > +  return Status;
> > +}
> > --
> > 2.17.1
> 
> 
> 
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#104056): https://edk2.groups.io/g/devel/message/104056
Mute This Topic: https://groups.io/mt/98684703/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-



Reply via email to