[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] -=-=-=-=-=-=-=-=-=-=-=-