--- /dev/null
+/** @file\r
+ The implementation of IPSEC_CONFIG_PROTOCOL.\r
+\r
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "IpSecConfigImpl.h"\r
+#include "IpSecDebug.h"\r
+\r
+LIST_ENTRY mConfigData[IPsecConfigDataTypeMaximum];\r
+BOOLEAN mSetBySelf = FALSE;\r
+\r
+//\r
+// Common CompareSelector routine entry for spd/sad/pad.\r
+//\r
+IPSEC_COMPARE_SELECTOR mCompareSelector[] = {\r
+ (IPSEC_COMPARE_SELECTOR) CompareSpdSelector,\r
+ (IPSEC_COMPARE_SELECTOR) CompareSaId,\r
+ (IPSEC_COMPARE_SELECTOR) ComparePadId\r
+};\r
+\r
+//\r
+// Common IsZeroSelector routine entry for spd/sad/pad.\r
+//\r
+IPSEC_IS_ZERO_SELECTOR mIsZeroSelector[] = {\r
+ (IPSEC_IS_ZERO_SELECTOR) IsZeroSpdSelector,\r
+ (IPSEC_IS_ZERO_SELECTOR) IsZeroSaId,\r
+ (IPSEC_IS_ZERO_SELECTOR) IsZeroPadId\r
+};\r
+\r
+//\r
+// Common DuplicateSelector routine entry for spd/sad/pad.\r
+//\r
+IPSEC_DUPLICATE_SELECTOR mDuplicateSelector[] = {\r
+ (IPSEC_DUPLICATE_SELECTOR) DuplicateSpdSelector,\r
+ (IPSEC_DUPLICATE_SELECTOR) DuplicateSaId,\r
+ (IPSEC_DUPLICATE_SELECTOR) DuplicatePadId\r
+};\r
+\r
+//\r
+// Common FixPolicyEntry routine entry for spd/sad/pad.\r
+//\r
+IPSEC_FIX_POLICY_ENTRY mFixPolicyEntry[] = {\r
+ (IPSEC_FIX_POLICY_ENTRY) FixSpdEntry,\r
+ (IPSEC_FIX_POLICY_ENTRY) FixSadEntry,\r
+ (IPSEC_FIX_POLICY_ENTRY) FixPadEntry\r
+};\r
+\r
+//\r
+// Common UnfixPolicyEntry routine entry for spd/sad/pad.\r
+//\r
+IPSEC_FIX_POLICY_ENTRY mUnfixPolicyEntry[] = {\r
+ (IPSEC_FIX_POLICY_ENTRY) UnfixSpdEntry,\r
+ (IPSEC_FIX_POLICY_ENTRY) UnfixSadEntry,\r
+ (IPSEC_FIX_POLICY_ENTRY) UnfixPadEntry\r
+};\r
+\r
+//\r
+// Common SetPolicyEntry routine entry for spd/sad/pad.\r
+//\r
+IPSEC_SET_POLICY_ENTRY mSetPolicyEntry[] = {\r
+ (IPSEC_SET_POLICY_ENTRY) SetSpdEntry,\r
+ (IPSEC_SET_POLICY_ENTRY) SetSadEntry,\r
+ (IPSEC_SET_POLICY_ENTRY) SetPadEntry\r
+};\r
+\r
+//\r
+// Common GetPolicyEntry routine entry for spd/sad/pad.\r
+//\r
+IPSEC_GET_POLICY_ENTRY mGetPolicyEntry[] = {\r
+ (IPSEC_GET_POLICY_ENTRY) GetSpdEntry,\r
+ (IPSEC_GET_POLICY_ENTRY) GetSadEntry,\r
+ (IPSEC_GET_POLICY_ENTRY) GetPadEntry\r
+};\r
+\r
+//\r
+// Routine entry for IpSecConfig protocol.\r
+//\r
+EFI_IPSEC_CONFIG_PROTOCOL mIpSecConfigInstance = {\r
+ EfiIpSecConfigSetData,\r
+ EfiIpSecConfigGetData,\r
+ EfiIpSecConfigGetNextSelector,\r
+ EfiIpSecConfigRegisterNotify,\r
+ EfiIpSecConfigUnregisterNotify\r
+};\r
+\r
+/**\r
+ Get the all IPSec configuration variables and store those variables\r
+ to the internal data structure.\r
+\r
+ This founction is called by IpSecConfigInitialize() that is to intialize the\r
+ IPsecConfiguration Protocol.\r
+\r
+ @param[in] Private Point to IPSEC_PRIVATE_DATA.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated.\r
+ @retval EFI_SUCCESS Restore the IPsec Configuration successfully.\r
+ @retval others Other errors is found during the variable getting.\r
+\r
+**/\r
+EFI_STATUS\r
+IpSecConfigRestore (\r
+ IN IPSEC_PRIVATE_DATA *Private\r
+ );\r
+\r
+/**\r
+ Check if the specified EFI_IP_ADDRESS_INFO is in EFI_IP_ADDRESS_INFO list.\r
+\r
+ @param[in] AddressInfo Pointer of IP_ADDRESS_INFO to be search in AddressInfo list.\r
+ @param[in] AddressInfoList A list that contains IP_ADDRESS_INFOs.\r
+ @param[in] AddressCount Point out how many IP_ADDRESS_INFO in the list.\r
+\r
+ @retval TRUE The specified AddressInfo is in the AddressInfoList.\r
+ @retval FALSE The specified AddressInfo is not in the AddressInfoList.\r
+\r
+**/\r
+BOOLEAN\r
+IsInAddressInfoList(\r
+ IN EFI_IP_ADDRESS_INFO *AddressInfo,\r
+ IN EFI_IP_ADDRESS_INFO *AddressInfoList,\r
+ IN UINT32 AddressCount\r
+ )\r
+{\r
+ UINT8 Index;\r
+\r
+ for (Index = 0; Index < AddressCount ; Index++) {\r
+ if (CompareMem (\r
+ AddressInfo,\r
+ &AddressInfoList[Index].Address,\r
+ sizeof (EFI_IP_ADDRESS)\r
+ ) == 0 &&\r
+ AddressInfo->PrefixLength == AddressInfoList[Index].PrefixLength\r
+ ) {\r
+ return TRUE;\r
+ }\r
+ }\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Compare two SPD Selectors.\r
+\r
+ Compare two SPD Selector by the fields of LocalAddressCount/RemoteAddressCount/\r
+ NextLayerProtocol/LocalPort/LocalPortRange/RemotePort/RemotePortRange and the\r
+ Local Addresses and remote Addresses.\r
+\r
+ @param[in] Selector1 Pointer of first SPD Selector.\r
+ @param[in] Selector2 Pointer of second SPD Selector.\r
+\r
+ @retval TRUE This two Selector have the same value in above fields.\r
+ @retval FALSE Not all above fields have the same value in these two Selectors.\r
+\r
+**/\r
+BOOLEAN\r
+CompareSpdSelector (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector1,\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector2\r
+ )\r
+{\r
+ EFI_IPSEC_SPD_SELECTOR *SpdSel1;\r
+ EFI_IPSEC_SPD_SELECTOR *SpdSel2;\r
+ BOOLEAN IsMatch;\r
+ UINTN Index;\r
+\r
+ SpdSel1 = &Selector1->SpdSelector;\r
+ SpdSel2 = &Selector2->SpdSelector;\r
+ IsMatch = TRUE;\r
+\r
+ //\r
+ // Compare the LocalAddressCount/RemoteAddressCount/NextLayerProtocol/\r
+ // LocalPort/LocalPortRange/RemotePort/RemotePortRange fields in the\r
+ // two Spdselectors. Since the SPD supports two directions, it needs to\r
+ // compare two directions.\r
+ //\r
+ if ((SpdSel1->LocalAddressCount != SpdSel2->LocalAddressCount &&\r
+ SpdSel1->LocalAddressCount != SpdSel2->RemoteAddressCount) ||\r
+ (SpdSel1->RemoteAddressCount != SpdSel2->RemoteAddressCount &&\r
+ SpdSel1->RemoteAddressCount != SpdSel2->LocalAddressCount) ||\r
+ SpdSel1->NextLayerProtocol != SpdSel2->NextLayerProtocol ||\r
+ SpdSel1->LocalPort != SpdSel2->LocalPort ||\r
+ SpdSel1->LocalPortRange != SpdSel2->LocalPortRange ||\r
+ SpdSel1->RemotePort != SpdSel2->RemotePort ||\r
+ SpdSel1->RemotePortRange != SpdSel2->RemotePortRange\r
+ ) {\r
+ IsMatch = FALSE;\r
+ return IsMatch;\r
+ }\r
+\r
+ //\r
+ // Compare the all LocalAddress fields in the two Spdselectors.\r
+ // First, SpdSel1->LocalAddress to SpdSel2->LocalAddress && Compare\r
+ // SpdSel1->RemoteAddress to SpdSel2->RemoteAddress. If all match, return\r
+ // TRUE.\r
+ //\r
+ for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) {\r
+ if (!IsInAddressInfoList (\r
+ &SpdSel1->LocalAddress[Index],\r
+ SpdSel2->LocalAddress,\r
+ SpdSel2->LocalAddressCount\r
+ )) {\r
+ IsMatch = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ if (IsMatch) {\r
+ for (Index = 0; Index < SpdSel2->LocalAddressCount; Index++) {\r
+ if (!IsInAddressInfoList (\r
+ &SpdSel2->LocalAddress[Index],\r
+ SpdSel1->LocalAddress,\r
+ SpdSel1->LocalAddressCount\r
+ )) {\r
+ IsMatch = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if (IsMatch) {\r
+ for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) {\r
+ if (!IsInAddressInfoList (\r
+ &SpdSel1->RemoteAddress[Index],\r
+ SpdSel2->RemoteAddress,\r
+ SpdSel2->RemoteAddressCount\r
+ )) {\r
+ IsMatch = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if (IsMatch) {\r
+ for (Index = 0; Index < SpdSel2->RemoteAddressCount; Index++) {\r
+ if (!IsInAddressInfoList (\r
+ &SpdSel2->RemoteAddress[Index],\r
+ SpdSel1->RemoteAddress,\r
+ SpdSel1->RemoteAddressCount\r
+ )) {\r
+ IsMatch = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Finish the one direction compare. If it is matched, return; otherwise,\r
+ // compare the other direction.\r
+ //\r
+ if (IsMatch) {\r
+ return IsMatch;\r
+ }\r
+ //\r
+ // Secondly, the SpdSel1->LocalAddress doesn't equal to SpdSel2->LocalAddress and\r
+ // SpdSel1->RemoteAddress doesn't equal to SpdSel2->RemoteAddress. Try to compare\r
+ // the RemoteAddress to LocalAddress.\r
+ //\r
+ IsMatch = TRUE;\r
+ for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) {\r
+ if (!IsInAddressInfoList (\r
+ &SpdSel1->RemoteAddress[Index],\r
+ SpdSel2->LocalAddress,\r
+ SpdSel2->LocalAddressCount\r
+ )) {\r
+ IsMatch = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ if (IsMatch) {\r
+ for (Index = 0; Index < SpdSel2->RemoteAddressCount; Index++) {\r
+ if (!IsInAddressInfoList (\r
+ &SpdSel2->RemoteAddress[Index],\r
+ SpdSel1->LocalAddress,\r
+ SpdSel1->LocalAddressCount\r
+ )) {\r
+ IsMatch = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if (IsMatch) {\r
+ for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) {\r
+ if (!IsInAddressInfoList (\r
+ &SpdSel1->LocalAddress[Index],\r
+ SpdSel2->RemoteAddress,\r
+ SpdSel2->RemoteAddressCount\r
+ )) {\r
+ IsMatch = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if (IsMatch) {\r
+ for (Index = 0; Index < SpdSel2->LocalAddressCount; Index++) {\r
+ if (!IsInAddressInfoList (\r
+ &SpdSel2->LocalAddress[Index],\r
+ SpdSel1->RemoteAddress,\r
+ SpdSel1->RemoteAddressCount\r
+ )) {\r
+ IsMatch = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ return IsMatch;\r
+}\r
+\r
+/**\r
+ Compare two SA IDs.\r
+\r
+ @param[in] Selector1 Pointer of first SA ID.\r
+ @param[in] Selector2 Pointer of second SA ID.\r
+\r
+ @retval TRUE This two Selectors have the same SA ID.\r
+ @retval FALSE This two Selecotrs don't have the same SA ID.\r
+\r
+**/\r
+BOOLEAN\r
+CompareSaId (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector1,\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector2\r
+ )\r
+{\r
+ EFI_IPSEC_SA_ID *SaId1;\r
+ EFI_IPSEC_SA_ID *SaId2;\r
+ BOOLEAN IsMatch;\r
+\r
+ SaId1 = &Selector1->SaId;\r
+ SaId2 = &Selector2->SaId;\r
+ IsMatch = TRUE;\r
+\r
+ if (CompareMem (SaId1, SaId2, sizeof (EFI_IPSEC_SA_ID)) != 0) {\r
+ IsMatch = FALSE;\r
+ }\r
+\r
+ return IsMatch;\r
+}\r
+\r
+/**\r
+ Compare two PAD IDs.\r
+\r
+ @param[in] Selector1 Pointer of first PAD ID.\r
+ @param[in] Selector2 Pointer of second PAD ID.\r
+\r
+ @retval TRUE This two Selectors have the same PAD ID.\r
+ @retval FALSE This two Selecotrs don't have the same PAD ID.\r
+\r
+**/\r
+BOOLEAN\r
+ComparePadId (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector1,\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector2\r
+ )\r
+{\r
+ EFI_IPSEC_PAD_ID *PadId1;\r
+ EFI_IPSEC_PAD_ID *PadId2;\r
+ BOOLEAN IsMatch;\r
+\r
+ PadId1 = &Selector1->PadId;\r
+ PadId2 = &Selector2->PadId;\r
+ IsMatch = TRUE;\r
+\r
+ //\r
+ // Compare the PeerIdValid fields in PadId.\r
+ //\r
+ if (PadId1->PeerIdValid != PadId2->PeerIdValid) {\r
+ IsMatch = FALSE;\r
+ }\r
+ //\r
+ // Compare the PeerId fields in PadId if PeerIdValid is true.\r
+ //\r
+ if (IsMatch &&\r
+ PadId1->PeerIdValid &&\r
+ AsciiStriCmp ((CONST CHAR8 *) PadId1->Id.PeerId, (CONST CHAR8 *) PadId2->Id.PeerId) != 0\r
+ ) {\r
+ IsMatch = FALSE;\r
+ }\r
+ //\r
+ // Compare the IpAddress fields in PadId if PeerIdValid is false.\r
+ //\r
+ if (IsMatch &&\r
+ !PadId1->PeerIdValid &&\r
+ (PadId1->Id.IpAddress.PrefixLength != PadId2->Id.IpAddress.PrefixLength ||\r
+ CompareMem (&PadId1->Id.IpAddress.Address, &PadId2->Id.IpAddress.Address, sizeof (EFI_IP_ADDRESS)) != 0)\r
+ ) {\r
+ IsMatch = FALSE;\r
+ }\r
+\r
+ return IsMatch;\r
+}\r
+\r
+/**\r
+ Check if the SPD Selector is Zero by its LocalAddressCount and RemoteAddressCount\r
+ fields.\r
+\r
+ @param[in] Selector Pointer of the SPD Selector.\r
+\r
+ @retval TRUE If the SPD Selector is Zero.\r
+ @retval FALSE If the SPD Selector is not Zero.\r
+\r
+**/\r
+BOOLEAN\r
+IsZeroSpdSelector (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector\r
+ )\r
+{\r
+ EFI_IPSEC_SPD_SELECTOR *SpdSel;\r
+ BOOLEAN IsZero;\r
+\r
+ SpdSel = &Selector->SpdSelector;\r
+ IsZero = FALSE;\r
+\r
+ if (SpdSel->LocalAddressCount == 0 && SpdSel->RemoteAddressCount == 0) {\r
+ IsZero = TRUE;\r
+ }\r
+\r
+ return IsZero;\r
+}\r
+\r
+/**\r
+ Check if the SA ID is Zero by its DestAddress.\r
+\r
+ @param[in] Selector Pointer of the SA ID.\r
+\r
+ @retval TRUE If the SA ID is Zero.\r
+ @retval FALSE If the SA ID is not Zero.\r
+\r
+**/\r
+BOOLEAN\r
+IsZeroSaId (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector\r
+ )\r
+{\r
+ EFI_IP_ADDRESS *DestAddr;\r
+ EFI_IP_ADDRESS ZeroAddr;\r
+ BOOLEAN IsZero;\r
+\r
+ DestAddr = &Selector->SaId.DestAddress;\r
+ IsZero = FALSE;\r
+\r
+ ZeroMem (&ZeroAddr, sizeof (EFI_IP_ADDRESS));\r
+\r
+ if (CompareMem (DestAddr, &ZeroAddr, sizeof (EFI_IP_ADDRESS)) == 0) {\r
+ IsZero = TRUE;\r
+ }\r
+\r
+ return IsZero;\r
+}\r
+\r
+/**\r
+ Check if the PAD ID is Zero.\r
+\r
+ @param[in] Selector Pointer of the PAD ID.\r
+\r
+ @retval TRUE If the PAD ID is Zero.\r
+ @retval FALSE If the PAD ID is not Zero.\r
+\r
+**/\r
+BOOLEAN\r
+IsZeroPadId (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector\r
+ )\r
+{\r
+ EFI_IPSEC_PAD_ID *PadId;\r
+ EFI_IPSEC_PAD_ID ZeroId;\r
+ BOOLEAN IsZero;\r
+\r
+ PadId = &Selector->PadId;\r
+ IsZero = FALSE;\r
+\r
+ ZeroMem (&ZeroId, sizeof (EFI_IPSEC_PAD_ID));\r
+\r
+ if (CompareMem (PadId, &ZeroId, sizeof (EFI_IPSEC_PAD_ID)) == 0) {\r
+ IsZero = TRUE;\r
+ }\r
+\r
+ return IsZero;\r
+}\r
+\r
+/**\r
+ Copy Source SPD Selector to the Destination SPD Selector.\r
+\r
+ @param[in, out] DstSel Pointer of Destination SPD Selector.\r
+ @param[in] SrcSel Pointer of Source SPD Selector.\r
+ @param[in, out] Size The size of the Destination SPD Selector. If it\r
+ not NULL and its value less than the size of\r
+ Source SPD Selector, the value of Source SPD\r
+ Selector's size will be passed to caller by this\r
+ parameter.\r
+\r
+ @retval EFI_INVALID_PARAMETER If the Destination or Source SPD Selector is NULL\r
+ @retval EFI_BUFFER_TOO_SMALL If the input Size is less than size of the Source SPD Selector.\r
+ @retval EFI_SUCCESS Copy Source SPD Selector to the Destination SPD\r
+ Selector successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+DuplicateSpdSelector (\r
+ IN OUT EFI_IPSEC_CONFIG_SELECTOR *DstSel,\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *SrcSel,\r
+ IN OUT UINTN *Size\r
+ )\r
+{\r
+ EFI_IPSEC_SPD_SELECTOR *Dst;\r
+ EFI_IPSEC_SPD_SELECTOR *Src;\r
+\r
+ Dst = &DstSel->SpdSelector;\r
+ Src = &SrcSel->SpdSelector;\r
+\r
+ if (Dst == NULL || Src == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Size != NULL && (*Size) < SIZE_OF_SPD_SELECTOR (Src)) {\r
+ *Size = SIZE_OF_SPD_SELECTOR (Src);\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ //\r
+ // Copy the base structure of spd selector.\r
+ //\r
+ CopyMem (Dst, Src, sizeof (EFI_IPSEC_SPD_SELECTOR));\r
+\r
+ //\r
+ // Copy the local address array of spd selector.\r
+ //\r
+ Dst->LocalAddress = (EFI_IP_ADDRESS_INFO *) (Dst + 1);\r
+ CopyMem (\r
+ Dst->LocalAddress,\r
+ Src->LocalAddress,\r
+ sizeof (EFI_IP_ADDRESS_INFO) * Dst->LocalAddressCount\r
+ );\r
+\r
+ //\r
+ // Copy the remote address array of spd selector.\r
+ //\r
+ Dst->RemoteAddress = Dst->LocalAddress + Dst->LocalAddressCount;\r
+ CopyMem (\r
+ Dst->RemoteAddress,\r
+ Src->RemoteAddress,\r
+ sizeof (EFI_IP_ADDRESS_INFO) * Dst->RemoteAddressCount\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Copy Source SA ID to the Destination SA ID.\r
+\r
+ @param[in, out] DstSel Pointer of Destination SA ID.\r
+ @param[in] SrcSel Pointer of Source SA ID.\r
+ @param[in, out] Size The size of the Destination SA ID. If it\r
+ not NULL and its value less than the size of\r
+ Source SA ID, the value of Source SA ID's size\r
+ will be passed to caller by this parameter.\r
+\r
+ @retval EFI_INVALID_PARAMETER If the Destination or Source SA ID is NULL.\r
+ @retval EFI_BUFFER_TOO_SMALL If the input Size less than size of source SA ID.\r
+ @retval EFI_SUCCESS Copy Source SA ID to the Destination SA ID successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+DuplicateSaId (\r
+ IN OUT EFI_IPSEC_CONFIG_SELECTOR *DstSel,\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *SrcSel,\r
+ IN OUT UINTN *Size\r
+ )\r
+{\r
+ EFI_IPSEC_SA_ID *Dst;\r
+ EFI_IPSEC_SA_ID *Src;\r
+\r
+ Dst = &DstSel->SaId;\r
+ Src = &SrcSel->SaId;\r
+\r
+ if (Dst == NULL || Src == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Size != NULL && *Size < sizeof (EFI_IPSEC_SA_ID)) {\r
+ *Size = sizeof (EFI_IPSEC_SA_ID);\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ CopyMem (Dst, Src, sizeof (EFI_IPSEC_SA_ID));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Copy Source PAD ID to the Destination PAD ID.\r
+\r
+ @param[in, out] DstSel Pointer of Destination PAD ID.\r
+ @param[in] SrcSel Pointer of Source PAD ID.\r
+ @param[in, out] Size The size of the Destination PAD ID. If it\r
+ not NULL and its value less than the size of\r
+ Source PAD ID, the value of Source PAD ID's size\r
+ will be passed to caller by this parameter.\r
+\r
+ @retval EFI_INVALID_PARAMETER If the Destination or Source PAD ID is NULL.\r
+ @retval EFI_BUFFER_TOO_SMALL If the input Size less than size of source PAD ID .\r
+ @retval EFI_SUCCESS Copy Source PAD ID to the Destination PAD ID successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+DuplicatePadId (\r
+ IN OUT EFI_IPSEC_CONFIG_SELECTOR *DstSel,\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *SrcSel,\r
+ IN OUT UINTN *Size\r
+ )\r
+{\r
+ EFI_IPSEC_PAD_ID *Dst;\r
+ EFI_IPSEC_PAD_ID *Src;\r
+\r
+ Dst = &DstSel->PadId;\r
+ Src = &SrcSel->PadId;\r
+\r
+ if (Dst == NULL || Src == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Size != NULL && *Size < sizeof (EFI_IPSEC_PAD_ID)) {\r
+ *Size = sizeof (EFI_IPSEC_PAD_ID);\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ CopyMem (Dst, Src, sizeof (EFI_IPSEC_PAD_ID));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Fix the value of some members of SPD Selector.\r
+\r
+ This function is called by IpSecCopyPolicyEntry()which copy the Policy\r
+ Entry into the Variable. Since some members in SPD Selector are pointers,\r
+ a physical address to relative address convertion is required before copying\r
+ this SPD entry into the variable.\r
+\r
+ @param[in] Selector Pointer of SPD Selector.\r
+ @param[in, out] Data Pointer of SPD Data.\r
+\r
+**/\r
+VOID\r
+FixSpdEntry (\r
+ IN EFI_IPSEC_SPD_SELECTOR *Selector,\r
+ IN OUT EFI_IPSEC_SPD_DATA *Data\r
+ )\r
+{\r
+ //\r
+ // It assumes that all ref buffers in spd selector and data are\r
+ // stored in the continous memory and close to the base structure.\r
+ //\r
+ FIX_REF_BUF_ADDR (Selector->LocalAddress, Selector);\r
+ FIX_REF_BUF_ADDR (Selector->RemoteAddress, Selector);\r
+\r
+ if (Data->ProcessingPolicy != NULL) {\r
+ if (Data->ProcessingPolicy->TunnelOption != NULL) {\r
+ FIX_REF_BUF_ADDR (Data->ProcessingPolicy->TunnelOption, Data);\r
+ }\r
+\r
+ FIX_REF_BUF_ADDR (Data->ProcessingPolicy, Data);\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Fix the value of some members of SA ID.\r
+\r
+ This function is called by IpSecCopyPolicyEntry()which copy the Policy\r
+ Entry into the Variable. Since some members in SA ID are pointers,\r
+ a physical address to relative address conversion is required before copying\r
+ this SAD into the variable.\r
+\r
+ @param[in] SaId Pointer of SA ID\r
+ @param[in, out] Data Pointer of SA Data.\r
+\r
+**/\r
+VOID\r
+FixSadEntry (\r
+ IN EFI_IPSEC_SA_ID *SaId,\r
+ IN OUT EFI_IPSEC_SA_DATA *Data\r
+ )\r
+{\r
+ //\r
+ // It assumes that all ref buffers in sad selector and data are\r
+ // stored in the continous memory and close to the base structure.\r
+ //\r
+ if (Data->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {\r
+ FIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.AuthKey, Data);\r
+ }\r
+\r
+ if (SaId->Proto == EfiIPsecESP && Data->AlgoInfo.EspAlgoInfo.EncKey != NULL) {\r
+ FIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.EncKey, Data);\r
+ }\r
+\r
+ if (Data->SpdSelector != NULL) {\r
+ if (Data->SpdSelector->LocalAddress != NULL) {\r
+ FIX_REF_BUF_ADDR (Data->SpdSelector->LocalAddress, Data);\r
+ }\r
+\r
+ FIX_REF_BUF_ADDR (Data->SpdSelector->RemoteAddress, Data);\r
+ FIX_REF_BUF_ADDR (Data->SpdSelector, Data);\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Fix the value of some members of PAD ID.\r
+\r
+ This function is called by IpSecCopyPolicyEntry()which copy the Policy\r
+ Entry into the Variable. Since some members in PAD ID are pointers,\r
+ a physical address to relative address conversion is required before copying\r
+ this PAD into the variable.\r
+\r
+ @param[in] PadId Pointer of PAD ID.\r
+ @param[in, out] Data Pointer of PAD Data.\r
+\r
+**/\r
+VOID\r
+FixPadEntry (\r
+ IN EFI_IPSEC_PAD_ID *PadId,\r
+ IN OUT EFI_IPSEC_PAD_DATA *Data\r
+ )\r
+{\r
+ //\r
+ // It assumes that all ref buffers in pad selector and data are\r
+ // stored in the continous memory and close to the base structure.\r
+ //\r
+ if (Data->AuthData != NULL) {\r
+ FIX_REF_BUF_ADDR (Data->AuthData, Data);\r
+ }\r
+\r
+ if (Data->RevocationData != NULL) {\r
+ FIX_REF_BUF_ADDR (Data->RevocationData, Data);\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Recover the value of some members of SPD Selector.\r
+\r
+ This function is corresponding to FixSpdEntry(). It recovers the value of members\r
+ of SPD Selector that are fixed by FixSpdEntry().\r
+\r
+ @param[in, out] Selector Pointer of SPD Selector.\r
+ @param[in, out] Data Pointer of SPD Data.\r
+\r
+**/\r
+VOID\r
+UnfixSpdEntry (\r
+ IN OUT EFI_IPSEC_SPD_SELECTOR *Selector,\r
+ IN OUT EFI_IPSEC_SPD_DATA *Data\r
+ )\r
+{\r
+ //\r
+ // It assumes that all ref buffers in spd selector and data are\r
+ // stored in the continous memory and close to the base structure.\r
+ //\r
+ UNFIX_REF_BUF_ADDR (Selector->LocalAddress, Selector);\r
+ UNFIX_REF_BUF_ADDR (Selector->RemoteAddress, Selector);\r
+\r
+ if (Data->ProcessingPolicy != NULL) {\r
+ UNFIX_REF_BUF_ADDR (Data->ProcessingPolicy, Data);\r
+ if (Data->ProcessingPolicy->TunnelOption != NULL) {\r
+ UNFIX_REF_BUF_ADDR (Data->ProcessingPolicy->TunnelOption, Data);\r
+ }\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Recover the value of some members of SA ID.\r
+\r
+ This function is corresponding to FixSadEntry(). It recovers the value of members\r
+ of SAD ID that are fixed by FixSadEntry().\r
+\r
+ @param[in, out] SaId Pointer of SAD ID.\r
+ @param[in, out] Data Pointer of SAD Data.\r
+\r
+**/\r
+VOID\r
+UnfixSadEntry (\r
+ IN OUT EFI_IPSEC_SA_ID *SaId,\r
+ IN OUT EFI_IPSEC_SA_DATA *Data\r
+ )\r
+{\r
+ //\r
+ // It assumes that all ref buffers in sad selector and data are\r
+ // stored in the continous memory and close to the base structure.\r
+ //\r
+ if (Data->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {\r
+ UNFIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.AuthKey, Data);\r
+ }\r
+\r
+ if (SaId->Proto == EfiIPsecESP && Data->AlgoInfo.EspAlgoInfo.EncKey != NULL) {\r
+ UNFIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.EncKey, Data);\r
+ }\r
+\r
+ if (Data->SpdSelector != NULL) {\r
+ UNFIX_REF_BUF_ADDR (Data->SpdSelector, Data);\r
+ if (Data->SpdSelector->LocalAddress != NULL) {\r
+ UNFIX_REF_BUF_ADDR (Data->SpdSelector->LocalAddress, Data);\r
+ }\r
+\r
+ UNFIX_REF_BUF_ADDR (Data->SpdSelector->RemoteAddress, Data);\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Recover the value of some members of PAD ID.\r
+\r
+ This function is corresponding to FixPadEntry(). It recovers the value of members\r
+ of PAD ID that are fixed by FixPadEntry().\r
+\r
+ @param[in] PadId Pointer of PAD ID.\r
+ @param[in, out] Data Pointer of PAD Data.\r
+\r
+**/\r
+VOID\r
+UnfixPadEntry (\r
+ IN EFI_IPSEC_PAD_ID *PadId,\r
+ IN OUT EFI_IPSEC_PAD_DATA *Data\r
+ )\r
+{\r
+ //\r
+ // It assumes that all ref buffers in pad selector and data are\r
+ // stored in the continous memory and close to the base structure.\r
+ //\r
+ if (Data->AuthData != NULL) {\r
+ UNFIX_REF_BUF_ADDR (Data->AuthData, Data);\r
+ }\r
+\r
+ if (Data->RevocationData != NULL) {\r
+ UNFIX_REF_BUF_ADDR (Data->RevocationData, Data);\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Set the security policy information for the EFI IPsec driver.\r
+\r
+ The IPsec configuration data has a unique selector/identifier separately to\r
+ identify a data entry.\r
+\r
+ @param[in] Selector Pointer to an entry selector on operated\r
+ configuration data specified by DataType.\r
+ A NULL Selector causes the entire specified-type\r
+ configuration information to be flushed.\r
+ @param[in] Data The data buffer to be set. The structure\r
+ of the data buffer should be EFI_IPSEC_SPD_DATA.\r
+ @param[in] Context Pointer to one entry selector that describes\r
+ the expected position the new data entry will\r
+ be added. If Context is NULL, the new entry will\r
+ be appended the end of database.\r
+\r
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:\r
+ - Selector is not NULL and its LocalAddress\r
+ is NULL or its RemoteAddress is NULL.\r
+ - Data is not NULL and its Action is Protected\r
+ and its plolicy is NULL.\r
+ - Data is not NULL, its Action is not protected,\r
+ and its policy is not NULL.\r
+ - The Action of Data is Protected, its policy\r
+ mode is Tunnel, and its tunnel option is NULL.\r
+ - The Action of Data is protected and its policy\r
+ mode is not Tunnel and it tunnel option is not NULL.\r
+ @retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated.\r
+ @retval EFI_SUCCESS The specified configuration data was obtained successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SetSpdEntry (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector,\r
+ IN VOID *Data,\r
+ IN VOID *Context OPTIONAL\r
+ )\r
+{\r
+ EFI_IPSEC_SPD_SELECTOR *SpdSel;\r
+ EFI_IPSEC_SPD_DATA *SpdData;\r
+ EFI_IPSEC_SPD_SELECTOR *InsertBefore;\r
+ LIST_ENTRY *SpdList;\r
+ LIST_ENTRY *SadList;\r
+ LIST_ENTRY *SpdSas;\r
+ LIST_ENTRY *EntryInsertBefore;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *NextEntry;\r
+ LIST_ENTRY *Entry2;\r
+ IPSEC_SPD_ENTRY *SpdEntry;\r
+ IPSEC_SAD_ENTRY *SadEntry;\r
+ UINTN SpdEntrySize;\r
+ UINTN Index;\r
+\r
+ SpdSel = (Selector == NULL) ? NULL : &Selector->SpdSelector;\r
+ SpdData = (Data == NULL) ? NULL : (EFI_IPSEC_SPD_DATA *) Data;\r
+ InsertBefore = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->SpdSelector;\r
+ SpdList = &mConfigData[IPsecConfigDataTypeSpd];\r
+\r
+ if (SpdSel != NULL) {\r
+ if (SpdSel->LocalAddress == NULL || SpdSel->RemoteAddress == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ if (SpdData != NULL) {\r
+ if ((SpdData->Action == EfiIPsecActionProtect && SpdData->ProcessingPolicy == NULL) ||\r
+ (SpdData->Action != EfiIPsecActionProtect && SpdData->ProcessingPolicy != NULL)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (SpdData->Action == EfiIPsecActionProtect) {\r
+ if ((SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel && SpdData->ProcessingPolicy->TunnelOption == NULL) ||\r
+ (SpdData->ProcessingPolicy->Mode != EfiIPsecTunnel && SpdData->ProcessingPolicy->TunnelOption != NULL)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // The default behavior is to insert the node ahead of the header.\r
+ //\r
+ EntryInsertBefore = SpdList;\r
+\r
+ //\r
+ // Remove the existed spd entry.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SpdList) {\r
+\r
+ SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);\r
+\r
+ if (SpdSel == NULL ||\r
+ CompareSpdSelector ((EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector, (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel)\r
+ ) {\r
+ //\r
+ // Record the existed entry position to keep the original order.\r
+ //\r
+ EntryInsertBefore = SpdEntry->List.ForwardLink;\r
+ RemoveEntryList (&SpdEntry->List);\r
+\r
+ //\r
+ // Update the reverse ref of sad entry in the spd.sas list.\r
+ //\r
+ SpdSas = &SpdEntry->Data->Sas;\r
+ NET_LIST_FOR_EACH (Entry2, SpdSas) {\r
+ SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry2);\r
+ SadEntry->Data->SpdEntry = NULL;\r
+ }\r
+ //\r
+ // Free the existed spd entry\r
+ //\r
+ FreePool (SpdEntry);\r
+ }\r
+ }\r
+ //\r
+ // Return success here if only want to remove the spd entry.\r
+ //\r
+ if (SpdData == NULL || SpdSel == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Search the appointed entry position if InsertBefore is not NULL.\r
+ //\r
+ if (InsertBefore != NULL) {\r
+\r
+ NET_LIST_FOR_EACH (Entry, SpdList) {\r
+ SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);\r
+\r
+ if (CompareSpdSelector (\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector,\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore\r
+ )) {\r
+ EntryInsertBefore = Entry;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Do Padding for the different Arch.\r
+ //\r
+ SpdEntrySize = ALIGN_VARIABLE (sizeof (IPSEC_SPD_ENTRY));\r
+ SpdEntrySize = ALIGN_VARIABLE (SpdEntrySize + (UINTN)SIZE_OF_SPD_SELECTOR (SpdSel));\r
+ SpdEntrySize += IpSecGetSizeOfEfiSpdData (SpdData);\r
+\r
+ SpdEntry = AllocateZeroPool (SpdEntrySize);\r
+\r
+ if (SpdEntry == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Fix the address of Selector and Data buffer and copy them, which is\r
+ // continous memory and close to the base structure of spd entry.\r
+ //\r
+ SpdEntry->Selector = (EFI_IPSEC_SPD_SELECTOR *) ALIGN_POINTER ((SpdEntry + 1), sizeof (UINTN));\r
+ SpdEntry->Data = (IPSEC_SPD_DATA *) ALIGN_POINTER (\r
+ ((UINT8 *) SpdEntry->Selector + SIZE_OF_SPD_SELECTOR (SpdSel)),\r
+ sizeof (UINTN)\r
+ );\r
+\r
+ DuplicateSpdSelector (\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector,\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel,\r
+ NULL\r
+ );\r
+\r
+ CopyMem (\r
+ SpdEntry->Data->Name,\r
+ SpdData->Name,\r
+ sizeof (SpdData->Name)\r
+ );\r
+ SpdEntry->Data->PackageFlag = SpdData->PackageFlag;\r
+ SpdEntry->Data->Action = SpdData->Action;\r
+\r
+ //\r
+ // Fix the address of ProcessingPolicy and copy it if need, which is continous\r
+ // memory and close to the base structure of sad data.\r
+ //\r
+ if (SpdData->Action != EfiIPsecActionProtect) {\r
+ SpdEntry->Data->ProcessingPolicy = NULL;\r
+ } else {\r
+ SpdEntry->Data->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ALIGN_POINTER (\r
+ SpdEntry->Data + 1,\r
+ sizeof (UINTN)\r
+ );\r
+ IpSecDuplicateProcessPolicy (SpdEntry->Data->ProcessingPolicy, SpdData->ProcessingPolicy);\r
+ }\r
+ //\r
+ // Update the sas list of the new spd entry.\r
+ //\r
+ InitializeListHead (&SpdEntry->Data->Sas);\r
+\r
+ SadList = &mConfigData[IPsecConfigDataTypeSad];\r
+\r
+ NET_LIST_FOR_EACH (Entry, SadList) {\r
+ SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);\r
+\r
+ for (Index = 0; Index < SpdData->SaIdCount; Index++) {\r
+\r
+ if (CompareSaId (\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) &SpdData->SaId[Index],\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id\r
+ )) {\r
+ InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd);\r
+ SadEntry->Data->SpdEntry = SpdEntry;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Insert the new spd entry.\r
+ //\r
+ InsertTailList (EntryInsertBefore, &SpdEntry->List);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Set the security association information for the EFI IPsec driver.\r
+\r
+ The IPsec configuration data has a unique selector/identifier separately to\r
+ identify a data entry.\r
+\r
+ @param[in] Selector Pointer to an entry selector on operated\r
+ configuration data specified by DataType.\r
+ A NULL Selector causes the entire specified-type\r
+ configuration information to be flushed.\r
+ @param[in] Data The data buffer to be set. The structure\r
+ of the data buffer should be EFI_IPSEC_SA_DATA.\r
+ @param[in] Context Pointer to one entry selector which describes\r
+ the expected position the new data entry will\r
+ be added. If Context is NULL,the new entry will\r
+ be appended the end of database.\r
+\r
+ @retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated.\r
+ @retval EFI_SUCCESS The specified configuration data was obtained successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SetSadEntry (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector,\r
+ IN VOID *Data,\r
+ IN VOID *Context OPTIONAL\r
+ )\r
+{\r
+ IPSEC_SAD_ENTRY *SadEntry;\r
+ IPSEC_SPD_ENTRY *SpdEntry;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *NextEntry;\r
+ LIST_ENTRY *SadList;\r
+ LIST_ENTRY *SpdList;\r
+ EFI_IPSEC_SA_ID *SaId;\r
+ EFI_IPSEC_SA_DATA *SaData;\r
+ EFI_IPSEC_SA_ID *InsertBefore;\r
+ LIST_ENTRY *EntryInsertBefore;\r
+ UINTN SadEntrySize;\r
+\r
+ SaId = (Selector == NULL) ? NULL : &Selector->SaId;\r
+ SaData = (Data == NULL) ? NULL : (EFI_IPSEC_SA_DATA *) Data;\r
+ InsertBefore = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->SaId;\r
+ SadList = &mConfigData[IPsecConfigDataTypeSad];\r
+\r
+ //\r
+ // The default behavior is to insert the node ahead of the header.\r
+ //\r
+ EntryInsertBefore = SadList;\r
+\r
+ //\r
+ // Remove the existed sad entry.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SadList) {\r
+\r
+ SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);\r
+\r
+ if (SaId == NULL ||\r
+ CompareSaId (\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id,\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SaId\r
+ )) {\r
+ //\r
+ // Record the existed entry position to keep the original order.\r
+ //\r
+ EntryInsertBefore = SadEntry->List.ForwardLink;\r
+\r
+ //\r
+ // Update the related sad.byspd field.\r
+ //\r
+ if (SadEntry->Data->SpdEntry != NULL) {\r
+ RemoveEntryList (&SadEntry->BySpd);\r
+ }\r
+\r
+ RemoveEntryList (&SadEntry->List);\r
+ FreePool (SadEntry);\r
+ }\r
+ }\r
+ //\r
+ // Return success here if only want to remove the sad entry\r
+ //\r
+ if (SaData == NULL || SaId == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Search the appointed entry position if InsertBefore is not NULL.\r
+ //\r
+ if (InsertBefore != NULL) {\r
+\r
+ NET_LIST_FOR_EACH (Entry, SadList) {\r
+ SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);\r
+\r
+ if (CompareSaId (\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id,\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore\r
+ )) {\r
+ EntryInsertBefore = Entry;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Do Padding for different Arch.\r
+ //\r
+ SadEntrySize = ALIGN_VARIABLE (sizeof (IPSEC_SAD_ENTRY));\r
+ SadEntrySize = ALIGN_VARIABLE (SadEntrySize + sizeof (EFI_IPSEC_SA_DATA));\r
+ SadEntrySize = ALIGN_VARIABLE (SadEntrySize + sizeof (IPSEC_SAD_DATA));\r
+\r
+ if (SaId->Proto == EfiIPsecAH) {\r
+ SadEntrySize += SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength;\r
+ } else {\r
+ SadEntrySize = ALIGN_VARIABLE (SadEntrySize + SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength);\r
+ SadEntrySize += SaData->AlgoInfo.EspAlgoInfo.EncKeyLength;\r
+ }\r
+\r
+ SadEntry = AllocateZeroPool (SadEntrySize);\r
+\r
+ if (SadEntry == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Fix the address of Id and Data buffer and copy them, which is\r
+ // continous memory and close to the base structure of sad entry.\r
+ //\r
+ SadEntry->Id = (EFI_IPSEC_SA_ID *) ALIGN_POINTER ((SadEntry + 1), sizeof (UINTN));\r
+ SadEntry->Data = (IPSEC_SAD_DATA *) ALIGN_POINTER ((SadEntry->Id + 1), sizeof (UINTN));\r
+\r
+ CopyMem (SadEntry->Id, SaId, sizeof (EFI_IPSEC_SA_ID));\r
+\r
+ SadEntry->Data->Mode = SaData->Mode;\r
+ SadEntry->Data->SequenceNumber = SaData->SNCount;\r
+ SadEntry->Data->AntiReplayWindowSize = SaData->AntiReplayWindows;\r
+\r
+ ZeroMem (\r
+ &SadEntry->Data->AntiReplayBitmap,\r
+ sizeof (SadEntry->Data->AntiReplayBitmap)\r
+ );\r
+\r
+ ZeroMem (\r
+ &SadEntry->Data->AlgoInfo,\r
+ sizeof (EFI_IPSEC_ALGO_INFO)\r
+ );\r
+\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId = SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId;\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength = SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength;\r
+\r
+ if (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) {\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SadEntry->Data + 1), sizeof (UINTN));\r
+ CopyMem (\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,\r
+ SaData->AlgoInfo.EspAlgoInfo.AuthKey,\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength\r
+ );\r
+ }\r
+\r
+ if (SaId->Proto == EfiIPsecESP) {\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId = SaData->AlgoInfo.EspAlgoInfo.EncAlgoId;\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength = SaData->AlgoInfo.EspAlgoInfo.EncKeyLength;\r
+\r
+ if (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) {\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER (\r
+ ((UINT8 *) (SadEntry->Data + 1) +\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength),\r
+ sizeof (UINTN)\r
+ );\r
+ CopyMem (\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,\r
+ SaData->AlgoInfo.EspAlgoInfo.EncKey,\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength\r
+ );\r
+ }\r
+ }\r
+\r
+ CopyMem (\r
+ &SadEntry->Data->SaLifetime,\r
+ &SaData->SaLifetime,\r
+ sizeof (EFI_IPSEC_SA_LIFETIME)\r
+ );\r
+\r
+ SadEntry->Data->PathMTU = SaData->PathMTU;\r
+ SadEntry->Data->SpdEntry = NULL;\r
+ SadEntry->Data->ESNEnabled = FALSE;\r
+ SadEntry->Data->ManualSet = SaData->ManualSet;\r
+\r
+ //\r
+ // Update the spd.sas list of the spd entry specified by sad.selector\r
+ //\r
+ SpdList = &mConfigData[IPsecConfigDataTypeSpd];\r
+\r
+ for (Entry = SpdList->ForwardLink; Entry != SpdList && SaData->SpdSelector != NULL; Entry = Entry->ForwardLink) {\r
+\r
+ SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);\r
+ if (CompareSpdSelector (\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector,\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector\r
+ ) && SpdEntry->Data->Action == EfiIPsecActionProtect) {\r
+ SadEntry->Data->SpdEntry = SpdEntry;\r
+ InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd);\r
+ }\r
+ }\r
+ //\r
+ // Insert the new sad entry.\r
+ //\r
+ InsertTailList (EntryInsertBefore, &SadEntry->List);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Set the peer authorization configuration information for the EFI IPsec driver.\r
+\r
+ The IPsec configuration data has a unique selector/identifier separately to\r
+ identify a data entry.\r
+\r
+ @param[in] Selector Pointer to an entry selector on operated\r
+ configuration data specified by DataType.\r
+ A NULL Selector causes the entire specified-type\r
+ configuration information to be flushed.\r
+ @param[in] Data The data buffer to be set. The structure\r
+ of the data buffer should be EFI_IPSEC_PAD_DATA.\r
+ @param[in] Context Pointer to one entry selector that describes\r
+ the expected position the new data entry will\r
+ be added. If Context is NULL, the new entry will\r
+ be appended the end of database.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES The required system resources could not be allocated.\r
+ @retval EFI_SUCCESS The specified configuration data was obtained successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SetPadEntry (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector,\r
+ IN VOID *Data,\r
+ IN VOID *Context OPTIONAL\r
+ )\r
+{\r
+ IPSEC_PAD_ENTRY *PadEntry;\r
+ EFI_IPSEC_PAD_ID *PadId;\r
+ EFI_IPSEC_PAD_DATA *PadData;\r
+ LIST_ENTRY *PadList;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *NextEntry;\r
+ EFI_IPSEC_PAD_ID *InsertBefore;\r
+ LIST_ENTRY *EntryInsertBefore;\r
+ UINTN PadEntrySize;\r
+\r
+ PadId = (Selector == NULL) ? NULL : &Selector->PadId;\r
+ PadData = (Data == NULL) ? NULL : (EFI_IPSEC_PAD_DATA *) Data;\r
+ InsertBefore = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->PadId;\r
+ PadList = &mConfigData[IPsecConfigDataTypePad];\r
+\r
+ //\r
+ // The default behavior is to insert the node ahead of the header.\r
+ //\r
+ EntryInsertBefore = PadList;\r
+\r
+ //\r
+ // Remove the existed pad entry.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, PadList) {\r
+\r
+ PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);\r
+\r
+ if (PadId == NULL ||\r
+ ComparePadId ((EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id, (EFI_IPSEC_CONFIG_SELECTOR *) PadId)\r
+ ) {\r
+ //\r
+ // Record the existed entry position to keep the original order.\r
+ //\r
+ EntryInsertBefore = PadEntry->List.ForwardLink;\r
+ RemoveEntryList (&PadEntry->List);\r
+\r
+ FreePool (PadEntry);\r
+ }\r
+ }\r
+ //\r
+ // Return success here if only want to remove the pad entry\r
+ //\r
+ if (PadData == NULL || PadId == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Search the appointed entry position if InsertBefore is not NULL.\r
+ //\r
+ if (InsertBefore != NULL) {\r
+\r
+ NET_LIST_FOR_EACH (Entry, PadList) {\r
+ PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);\r
+\r
+ if (ComparePadId (\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id,\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore\r
+ )) {\r
+ EntryInsertBefore = Entry;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Do PADDING for different arch.\r
+ //\r
+ PadEntrySize = ALIGN_VARIABLE (sizeof (IPSEC_PAD_ENTRY));\r
+ PadEntrySize = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_ID));\r
+ PadEntrySize = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_DATA));\r
+ PadEntrySize = ALIGN_VARIABLE (PadEntrySize + (PadData->AuthData != NULL ? PadData->AuthDataSize : 0));\r
+ PadEntrySize += PadData->RevocationData != NULL ? PadData->RevocationDataSize : 0;\r
+\r
+ PadEntry = AllocateZeroPool (PadEntrySize);\r
+\r
+ if (PadEntry == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Fix the address of Id and Data buffer and copy them, which is\r
+ // continous memory and close to the base structure of pad entry.\r
+ //\r
+ PadEntry->Id = (EFI_IPSEC_PAD_ID *) ALIGN_POINTER ((PadEntry + 1), sizeof (UINTN));\r
+ PadEntry->Data = (EFI_IPSEC_PAD_DATA *) ALIGN_POINTER ((PadEntry->Id + 1), sizeof (UINTN));\r
+\r
+ CopyMem (PadEntry->Id, PadId, sizeof (EFI_IPSEC_PAD_ID));\r
+\r
+ PadEntry->Data->AuthProtocol = PadData->AuthProtocol;\r
+ PadEntry->Data->AuthMethod = PadData->AuthMethod;\r
+ PadEntry->Data->IkeIdFlag = PadData->IkeIdFlag;\r
+\r
+ if (PadData->AuthData != NULL) {\r
+ PadEntry->Data->AuthDataSize = PadData->AuthDataSize;\r
+ PadEntry->Data->AuthData = (VOID *) ALIGN_POINTER (PadEntry->Data + 1, sizeof (UINTN));\r
+ CopyMem (\r
+ PadEntry->Data->AuthData,\r
+ PadData->AuthData,\r
+ PadData->AuthDataSize\r
+ );\r
+ } else {\r
+ PadEntry->Data->AuthDataSize = 0;\r
+ PadEntry->Data->AuthData = NULL;\r
+ }\r
+\r
+ if (PadData->RevocationData != NULL) {\r
+ PadEntry->Data->RevocationDataSize = PadData->RevocationDataSize;\r
+ PadEntry->Data->RevocationData = (VOID *) ALIGN_POINTER (\r
+ ((UINT8 *) (PadEntry->Data + 1) + PadData->AuthDataSize),\r
+ sizeof (UINTN)\r
+ );\r
+ CopyMem (\r
+ PadEntry->Data->RevocationData,\r
+ PadData->RevocationData,\r
+ PadData->RevocationDataSize\r
+ );\r
+ } else {\r
+ PadEntry->Data->RevocationDataSize = 0;\r
+ PadEntry->Data->RevocationData = NULL;\r
+ }\r
+ //\r
+ // Insert the new pad entry.\r
+ //\r
+ InsertTailList (EntryInsertBefore, &PadEntry->List);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function lookup the data entry from IPsec SPD. Return the configuration\r
+ value of the specified SPD Entry.\r
+\r
+ @param[in] Selector Pointer to an entry selector which is an identifier\r
+ of the SPD entry.\r
+ @param[in, out] DataSize On output the size of data returned in Data.\r
+ @param[out] Data The buffer to return the contents of the IPsec\r
+ configuration data. The type of the data buffer\r
+ is associated with the DataType.\r
+\r
+ @retval EFI_SUCCESS The specified configuration data was obtained successfully.\r
+ @retval EFI_INVALID_PARAMETER Data is NULL and *DataSize is not zero.\r
+ @retval EFI_NOT_FOUND The configuration data specified by Selector is not found.\r
+ @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been\r
+ updated with the size needed to complete the request.\r
+\r
+**/\r
+EFI_STATUS\r
+GetSpdEntry (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector,\r
+ IN OUT UINTN *DataSize,\r
+ OUT VOID *Data\r
+ )\r
+{\r
+ IPSEC_SPD_ENTRY *SpdEntry;\r
+ IPSEC_SAD_ENTRY *SadEntry;\r
+ EFI_IPSEC_SPD_SELECTOR *SpdSel;\r
+ EFI_IPSEC_SPD_DATA *SpdData;\r
+ LIST_ENTRY *SpdList;\r
+ LIST_ENTRY *SpdSas;\r
+ LIST_ENTRY *Entry;\r
+ UINTN RequiredSize;\r
+\r
+ SpdSel = &Selector->SpdSelector;\r
+ SpdData = (EFI_IPSEC_SPD_DATA *) Data;\r
+ SpdList = &mConfigData[IPsecConfigDataTypeSpd];\r
+\r
+ NET_LIST_FOR_EACH (Entry, SpdList) {\r
+ SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);\r
+\r
+ //\r
+ // Find the required spd entry\r
+ //\r
+ if (CompareSpdSelector (\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel,\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector\r
+ )) {\r
+\r
+ RequiredSize = IpSecGetSizeOfSpdData (SpdEntry->Data);\r
+ if (*DataSize < RequiredSize) {\r
+ *DataSize = RequiredSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ if (SpdData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *DataSize = RequiredSize;\r
+\r
+ //\r
+ // Extract and fill all SaId array from the spd.sas list\r
+ //\r
+ SpdSas = &SpdEntry->Data->Sas;\r
+ SpdData->SaIdCount = 0;\r
+\r
+ NET_LIST_FOR_EACH (Entry, SpdSas) {\r
+ SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry);\r
+ CopyMem (\r
+ &SpdData->SaId[SpdData->SaIdCount++],\r
+ SadEntry->Id,\r
+ sizeof (EFI_IPSEC_SA_ID)\r
+ );\r
+ }\r
+ //\r
+ // Fill the other fields in spd data.\r
+ //\r
+ CopyMem (SpdData->Name, SpdEntry->Data->Name, sizeof (SpdData->Name));\r
+\r
+ SpdData->PackageFlag = SpdEntry->Data->PackageFlag;\r
+ SpdData->Action = SpdEntry->Data->Action;\r
+\r
+ if (SpdData->Action != EfiIPsecActionProtect) {\r
+ SpdData->ProcessingPolicy = NULL;\r
+ } else {\r
+ SpdData->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ((UINT8 *) SpdData + sizeof (EFI_IPSEC_SPD_DATA) + (SpdData->SaIdCount - 1) * sizeof (EFI_IPSEC_SA_ID));\r
+\r
+ IpSecDuplicateProcessPolicy (\r
+ SpdData->ProcessingPolicy,\r
+ SpdEntry->Data->ProcessingPolicy\r
+ );\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ This function lookup the data entry from IPsec SAD. Return the configuration\r
+ value of the specified SAD Entry.\r
+\r
+ @param[in] Selector Pointer to an entry selector which is an identifier\r
+ of the SAD entry.\r
+ @param[in, out] DataSize On output, the size of data returned in Data.\r
+ @param[out] Data The buffer to return the contents of the IPsec\r
+ configuration data. The type of the data buffer\r
+ is associated with the DataType.\r
+\r
+ @retval EFI_SUCCESS The specified configuration data was obtained successfully.\r
+ @retval EFI_NOT_FOUND The configuration data specified by Selector is not found.\r
+ @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been\r
+ updated with the size needed to complete the request.\r
+\r
+**/\r
+EFI_STATUS\r
+GetSadEntry (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector,\r
+ IN OUT UINTN *DataSize,\r
+ OUT VOID *Data\r
+ )\r
+{\r
+ IPSEC_SAD_ENTRY *SadEntry;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *SadList;\r
+ EFI_IPSEC_SA_ID *SaId;\r
+ EFI_IPSEC_SA_DATA *SaData;\r
+ UINTN RequiredSize;\r
+\r
+ SaId = &Selector->SaId;\r
+ SaData = (EFI_IPSEC_SA_DATA *) Data;\r
+ SadList = &mConfigData[IPsecConfigDataTypeSad];\r
+\r
+ NET_LIST_FOR_EACH (Entry, SadList) {\r
+ SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);\r
+\r
+ //\r
+ // Find the required sad entry.\r
+ //\r
+ if (CompareSaId (\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SaId,\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id\r
+ )) {\r
+ //\r
+ // Calculate the required size of the sad entry.\r
+ // Data Layout is follows:\r
+ // |EFI_IPSEC_SA_DATA\r
+ // |AuthKey\r
+ // |EncryptKey (Optional)\r
+ // |SpdSelector (Optional)\r
+ //\r
+ RequiredSize = ALIGN_VARIABLE (sizeof (EFI_IPSEC_SA_DATA));\r
+\r
+ if (SaId->Proto == EfiIPsecAH) {\r
+ RequiredSize = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength);\r
+ } else {\r
+ RequiredSize = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength);\r
+ RequiredSize = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength);\r
+ }\r
+\r
+ if (SadEntry->Data->SpdEntry != NULL) {\r
+ RequiredSize += SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdEntry->Selector);\r
+ }\r
+\r
+\r
+\r
+ if (*DataSize < RequiredSize) {\r
+ *DataSize = RequiredSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ //\r
+ // Fill the data fields of sad entry.\r
+ //\r
+ *DataSize = RequiredSize;\r
+ SaData->Mode = SadEntry->Data->Mode;\r
+ SaData->SNCount = SadEntry->Data->SequenceNumber;\r
+ SaData->AntiReplayWindows = SadEntry->Data->AntiReplayWindowSize;\r
+\r
+ CopyMem (\r
+ &SaData->SaLifetime,\r
+ &SadEntry->Data->SaLifetime,\r
+ sizeof (EFI_IPSEC_SA_LIFETIME)\r
+ );\r
+\r
+ ZeroMem (\r
+ &SaData->AlgoInfo,\r
+ sizeof (EFI_IPSEC_ALGO_INFO)\r
+ );\r
+\r
+ if (SaId->Proto == EfiIPsecAH) {\r
+ //\r
+ // Copy AH alogrithm INFO to SaData\r
+ //\r
+ SaData->AlgoInfo.AhAlgoInfo.AuthAlgoId = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthAlgoId;\r
+ SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength;\r
+ if (SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength != 0) {\r
+ SaData->AlgoInfo.AhAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN));\r
+ CopyMem (\r
+ SaData->AlgoInfo.AhAlgoInfo.AuthKey,\r
+ SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKey,\r
+ SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength\r
+ );\r
+ }\r
+ } else if (SaId->Proto == EfiIPsecESP) {\r
+ //\r
+ // Copy ESP alogrithem INFO to SaData\r
+ //\r
+ SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId;\r
+ SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength;\r
+ if (SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) {\r
+ SaData->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN));\r
+ CopyMem (\r
+ SaData->AlgoInfo.EspAlgoInfo.AuthKey,\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,\r
+ SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength\r
+ );\r
+ }\r
+\r
+ SaData->AlgoInfo.EspAlgoInfo.EncAlgoId = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId;\r
+ SaData->AlgoInfo.EspAlgoInfo.EncKeyLength = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength;\r
+\r
+ if (SaData->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) {\r
+ SaData->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER (\r
+ ((UINT8 *) (SaData + 1) +\r
+ SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength),\r
+ sizeof (UINTN)\r
+ );\r
+ CopyMem (\r
+ SaData->AlgoInfo.EspAlgoInfo.EncKey,\r
+ SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,\r
+ SaData->AlgoInfo.EspAlgoInfo.EncKeyLength\r
+ );\r
+ }\r
+ }\r
+\r
+ SaData->PathMTU = SadEntry->Data->PathMTU;\r
+\r
+ //\r
+ // Fill the spd selector field of sad data\r
+ //\r
+ if (SadEntry->Data->SpdEntry != NULL) {\r
+\r
+ SaData->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *) (\r
+ (UINT8 *)SaData +\r
+ RequiredSize -\r
+ SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdEntry->Selector)\r
+ );\r
+\r
+ DuplicateSpdSelector (\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdEntry->Selector,\r
+ NULL\r
+ );\r
+\r
+ } else {\r
+\r
+ SaData->SpdSelector = NULL;\r
+ }\r
+\r
+ SaData->ManualSet = SadEntry->Data->ManualSet;\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ This function lookup the data entry from IPsec PAD. Return the configuration\r
+ value of the specified PAD Entry.\r
+\r
+ @param[in] Selector Pointer to an entry selector which is an identifier\r
+ of the PAD entry.\r
+ @param[in, out] DataSize On output the size of data returned in Data.\r
+ @param[out] Data The buffer to return the contents of the IPsec\r
+ configuration data. The type of the data buffer\r
+ is associated with the DataType.\r
+\r
+ @retval EFI_SUCCESS The specified configuration data was obtained successfully.\r
+ @retval EFI_NOT_FOUND The configuration data specified by Selector is not found.\r
+ @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been\r
+ updated with the size needed to complete the request.\r
+\r
+**/\r
+EFI_STATUS\r
+GetPadEntry (\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector,\r
+ IN OUT UINTN *DataSize,\r
+ OUT VOID *Data\r
+ )\r
+{\r
+ IPSEC_PAD_ENTRY *PadEntry;\r
+ LIST_ENTRY *PadList;\r
+ LIST_ENTRY *Entry;\r
+ EFI_IPSEC_PAD_ID *PadId;\r
+ EFI_IPSEC_PAD_DATA *PadData;\r
+ UINTN RequiredSize;\r
+\r
+ PadId = &Selector->PadId;\r
+ PadData = (EFI_IPSEC_PAD_DATA *) Data;\r
+ PadList = &mConfigData[IPsecConfigDataTypePad];\r
+\r
+ NET_LIST_FOR_EACH (Entry, PadList) {\r
+ PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);\r
+\r
+ //\r
+ // Find the required pad entry.\r
+ //\r
+ if (ComparePadId (\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) PadId,\r
+ (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id\r
+ )) {\r
+ //\r
+ // Calculate the required size of the pad entry.\r
+ //\r
+ RequiredSize = ALIGN_VARIABLE (sizeof (EFI_IPSEC_PAD_DATA));\r
+ RequiredSize = ALIGN_VARIABLE (RequiredSize + PadEntry->Data->AuthDataSize);\r
+ RequiredSize += PadEntry->Data->RevocationDataSize;\r
+\r
+ if (*DataSize < RequiredSize) {\r
+ *DataSize = RequiredSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ //\r
+ // Fill the data fields of pad entry\r
+ //\r
+ *DataSize = RequiredSize;\r
+ PadData->AuthProtocol = PadEntry->Data->AuthProtocol;\r
+ PadData->AuthMethod = PadEntry->Data->AuthMethod;\r
+ PadData->IkeIdFlag = PadEntry->Data->IkeIdFlag;\r
+\r
+ //\r
+ // Copy Authentication data.\r
+ //\r
+ if (PadEntry->Data->AuthData != NULL) {\r
+\r
+ PadData->AuthDataSize = PadEntry->Data->AuthDataSize;\r
+ PadData->AuthData = (VOID *) ALIGN_POINTER ((PadData + 1), sizeof (UINTN));\r
+ CopyMem (\r
+ PadData->AuthData,\r
+ PadEntry->Data->AuthData,\r
+ PadData->AuthDataSize\r
+ );\r
+ } else {\r
+\r
+ PadData->AuthDataSize = 0;\r
+ PadData->AuthData = NULL;\r
+ }\r
+ //\r
+ // Copy Revocation Data.\r
+ //\r
+ if (PadEntry->Data->RevocationData != NULL) {\r
+\r
+ PadData->RevocationDataSize = PadEntry->Data->RevocationDataSize;\r
+ PadData->RevocationData = (VOID *) ALIGN_POINTER (\r
+ ((UINT8 *) (PadData + 1) + PadData->AuthDataSize),\r
+ sizeof (UINTN)\r
+ );\r
+ CopyMem (\r
+ PadData->RevocationData,\r
+ PadEntry->Data->RevocationData,\r
+ PadData->RevocationDataSize\r
+ );\r
+ } else {\r
+\r
+ PadData->RevocationDataSize = 0;\r
+ PadData->RevocationData = NULL;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Copy Source Process Policy to the Destination Process Policy.\r
+\r
+ @param[in] Dst Pointer to the Source Process Policy.\r
+ @param[in] Src Pointer to the Destination Process Policy.\r
+\r
+**/\r
+VOID\r
+IpSecDuplicateProcessPolicy (\r
+ IN EFI_IPSEC_PROCESS_POLICY *Dst,\r
+ IN EFI_IPSEC_PROCESS_POLICY *Src\r
+ )\r
+{\r
+ //\r
+ // Firstly copy the structure content itself.\r
+ //\r
+ CopyMem (Dst, Src, sizeof (EFI_IPSEC_PROCESS_POLICY));\r
+\r
+ //\r
+ // Recursively copy the tunnel option if needed.\r
+ //\r
+ if (Dst->Mode != EfiIPsecTunnel) {\r
+ ASSERT (Dst->TunnelOption == NULL);\r
+ } else {\r
+ Dst->TunnelOption = (EFI_IPSEC_TUNNEL_OPTION *) ALIGN_POINTER ((Dst + 1), sizeof (UINTN));\r
+ CopyMem (\r
+ Dst->TunnelOption,\r
+ Src->TunnelOption,\r
+ sizeof (EFI_IPSEC_TUNNEL_OPTION)\r
+ );\r
+ }\r
+}\r
+\r
+/**\r
+ Calculate the a whole size of EFI_IPSEC_SPD_DATA, which includes the buffer size pointed\r
+ to by the pointer members.\r
+\r
+ @param[in] SpdData Pointer to a specified EFI_IPSEC_SPD_DATA.\r
+\r
+ @return the whole size the specified EFI_IPSEC_SPD_DATA.\r
+\r
+**/\r
+UINTN\r
+IpSecGetSizeOfEfiSpdData (\r
+ IN EFI_IPSEC_SPD_DATA *SpdData\r
+ )\r
+{\r
+ UINTN Size;\r
+\r
+ Size = ALIGN_VARIABLE (sizeof (IPSEC_SPD_DATA));\r
+\r
+ if (SpdData->Action == EfiIPsecActionProtect) {\r
+ Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_PROCESS_POLICY));\r
+\r
+ if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) {\r
+ Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_TUNNEL_OPTION));\r
+ }\r
+ }\r
+\r
+ return Size;\r
+}\r
+\r
+/**\r
+ Calculate the a whole size of IPSEC_SPD_DATA which includes the buffer size pointed\r
+ to by the pointer members and the buffer size used by the Sa List.\r
+\r
+ @param[in] SpdData Pointer to the specified IPSEC_SPD_DATA.\r
+\r
+ @return the whole size of IPSEC_SPD_DATA.\r
+\r
+**/\r
+UINTN\r
+IpSecGetSizeOfSpdData (\r
+ IN IPSEC_SPD_DATA *SpdData\r
+ )\r
+{\r
+ UINTN Size;\r
+ LIST_ENTRY *Link;\r
+\r
+ Size = sizeof (EFI_IPSEC_SPD_DATA) - sizeof (EFI_IPSEC_SA_ID);\r
+\r
+ if (SpdData->Action == EfiIPsecActionProtect) {\r
+ Size += sizeof (EFI_IPSEC_PROCESS_POLICY);\r
+\r
+ if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) {\r
+ Size += sizeof (EFI_IPSEC_TUNNEL_OPTION);\r
+ }\r
+ }\r
+\r
+ NET_LIST_FOR_EACH (Link, &SpdData->Sas) {\r
+ Size += sizeof (EFI_IPSEC_SA_ID);\r
+ }\r
+\r
+ return Size;\r
+}\r
+\r
+/**\r
+ Get the IPsec Variable.\r
+\r
+ Get the all variables which start with the string contained in VaraiableName.\r
+ Since all IPsec related variable store in continual space, those kinds of\r
+ variable can be searched by the EfiGetNextVariableName. Those variables also are\r
+ returned in a continual buffer.\r
+\r
+ @param[in] VariableName Pointer to a specified Variable Name.\r
+ @param[in] VendorGuid Pointer to a specified Vendor Guid.\r
+ @param[in] Attributes Point to memory location to return the attributes\r
+ of variable. If the point is NULL, the parameter\r
+ would be ignored.\r
+ @param[in, out] DataSize As input, point to the maximum size of return\r
+ Data-Buffer. As output, point to the actual\r
+ size of the returned Data-Buffer.\r
+ @param[in] Data Point to return Data-Buffer.\r
+\r
+ @retval EFI_ABORTED If the Variable size which contained in the variable\r
+ structure doesn't match the variable size obtained\r
+ from the EFIGetVariable.\r
+ @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has\r
+ been updated with the size needed to complete the request.\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval others Other errors found during the variable getting.\r
+**/\r
+EFI_STATUS\r
+IpSecGetVariable (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN UINT32 *Attributes, OPTIONAL\r
+ IN OUT UINTN *DataSize,\r
+ IN VOID *Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GUID VendorGuidI;\r
+ UINTN VariableNameLength;\r
+ CHAR16 *VariableNameI;\r
+ UINTN VariableNameISize;\r
+ UINTN VariableNameISizeNew;\r
+ UINTN VariableIndex;\r
+ UINTN VariableCount;\r
+ IP_SEC_VARIABLE_INFO IpSecVariableInfo;\r
+ UINTN DataSizeI;\r
+\r
+ //\r
+ // The variable name constructor is "VariableName + Info/0001/0002/... + NULL".\r
+ // So the varialbe name is like "VariableNameInfo", "VariableName0001", ...\r
+ // "VariableNameNULL".\r
+ //\r
+ VariableNameLength = StrLen (VariableName);\r
+ VariableNameISize = (VariableNameLength + 5) * sizeof (CHAR16);\r
+ VariableNameI = AllocateZeroPool (VariableNameISize);\r
+ ASSERT (VariableNameI != NULL);\r
+\r
+ //\r
+ // Construct the varible name of ipsecconfig meta data.\r
+ //\r
+ UnicodeSPrint (VariableNameI, VariableNameISize, L"%s%s", VariableName, L"Info");\r
+\r
+ DataSizeI = sizeof (IpSecVariableInfo);\r
+\r
+ Status = gRT->GetVariable (\r
+ VariableNameI,\r
+ VendorGuid,\r
+ Attributes,\r
+ &DataSizeI,\r
+ &IpSecVariableInfo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (*DataSize < IpSecVariableInfo.VariableSize) {\r
+ *DataSize = IpSecVariableInfo.VariableSize;\r
+ Status = EFI_BUFFER_TOO_SMALL;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ VariableCount = IpSecVariableInfo.VariableCount;\r
+ VariableNameI[0] = L'\0';\r
+\r
+ while (VariableCount != 0) {\r
+ //\r
+ // Get the variable name one by one in the variable database.\r
+ //\r
+ VariableNameISizeNew = VariableNameISize;\r
+ Status = gRT->GetNextVariableName (\r
+ &VariableNameISizeNew,\r
+ VariableNameI,\r
+ &VendorGuidI\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ VariableNameI = ReallocatePool (\r
+ VariableNameISize,\r
+ VariableNameISizeNew,\r
+ VariableNameI\r
+ );\r
+ VariableNameISize = VariableNameISizeNew;\r
+\r
+ Status = gRT->GetNextVariableName (\r
+ &VariableNameISizeNew,\r
+ VariableNameI,\r
+ &VendorGuidI\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ //\r
+ // Check whether the current variable is the required "ipsecconfig".\r
+ //\r
+ if (StrnCmp (VariableNameI, VariableName, VariableNameLength) == 0 ||\r
+ CompareGuid (VendorGuid, &VendorGuidI)\r
+ ) {\r
+ //\r
+ // Parse the variable count of the current ipsecconfig data.\r
+ //\r
+ VariableIndex = StrDecimalToUintn (VariableNameI + VariableNameLength);\r
+ if (VariableIndex!= 0 && VariableIndex <= IpSecVariableInfo.VariableCount) {\r
+ //\r
+ // Get the variable size of the current ipsecconfig data.\r
+ //\r
+ DataSizeI = 0;\r
+ Status = gRT->GetVariable (\r
+ VariableNameI,\r
+ VendorGuid,\r
+ Attributes,\r
+ &DataSizeI,\r
+ NULL\r
+ );\r
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
+ //\r
+ // Validate the variable count and variable size.\r
+ //\r
+ if (VariableIndex != IpSecVariableInfo.VariableCount) {\r
+ //\r
+ // If the varaibe is not the last one, its size should be the max\r
+ // size of the single variable.\r
+ //\r
+ if (DataSizeI != IpSecVariableInfo.SingleVariableSize) {\r
+ return EFI_ABORTED;\r
+ }\r
+ } else {\r
+ if (DataSizeI != IpSecVariableInfo.VariableSize % IpSecVariableInfo.SingleVariableSize) {\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+ //\r
+ // Get the variable data of the current ipsecconfig data and\r
+ // store it into user buffer continously.\r
+ //\r
+ Status = gRT->GetVariable (\r
+ VariableNameI,\r
+ VendorGuid,\r
+ Attributes,\r
+ &DataSizeI,\r
+ (UINT8 *) Data + (VariableIndex - 1) * IpSecVariableInfo.SingleVariableSize\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ VariableCount--;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // The VariableCount in "VariableNameInfo" varaible should have the correct\r
+ // numbers of variables which name starts with VariableName.\r
+ //\r
+ if (VariableCount != 0) {\r
+ Status = EFI_ABORTED;\r
+ }\r
+\r
+ON_EXIT:\r
+ FreePool (VariableNameI);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Set the IPsec variables.\r
+\r
+ Set all IPsec variables which start with the specified variable name. Those variables\r
+ are set one by one.\r
+\r
+ @param[in] VariableName The name of the vendor's variable. It is a\r
+ Null-Terminated Unicode String.\r
+ @param[in] VendorGuid Unify identifier for vendor.\r
+ @param[in] Attributes Point to memory location to return the attributes of\r
+ variable. If the point is NULL, the parameter would be ignored.\r
+ @param[in] DataSize The size in bytes of Data-Buffer.\r
+ @param[in] Data Points to the content of the variable.\r
+\r
+ @retval EFI_SUCCESS The firmware successfully stored the variable and its data, as\r
+ defined by the Attributes.\r
+ @retval others Storing the variables failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IpSecSetVariable (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN UINT32 Attributes,\r
+ IN UINTN DataSize,\r
+ IN VOID *Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *VariableNameI;\r
+ UINTN VariableNameSize;\r
+ UINTN VariableIndex;\r
+ IP_SEC_VARIABLE_INFO IpSecVariableInfo;\r
+ UINT64 MaximumVariableStorageSize;\r
+ UINT64 RemainingVariableStorageSize;\r
+ UINT64 MaximumVariableSize;\r
+\r
+ Status = gRT->QueryVariableInfo (\r
+ Attributes,\r
+ &MaximumVariableStorageSize,\r
+ &RemainingVariableStorageSize,\r
+ &MaximumVariableSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // "VariableName + Info/0001/0002/... + NULL"\r
+ //\r
+ VariableNameSize = (StrLen (VariableName) + 5) * sizeof (CHAR16);\r
+ VariableNameI = AllocateZeroPool (VariableNameSize);\r
+\r
+ if (VariableNameI == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
+ //\r
+ // Construct the variable of ipsecconfig general information. Like the total\r
+ // numbers of the Ipsecconfig variables, the total size of all ipsecconfig variables.\r
+ //\r
+ UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%s", VariableName, L"Info");\r
+ MaximumVariableSize -= VariableNameSize;\r
+\r
+ IpSecVariableInfo.VariableCount = (UINT32) ((DataSize + (UINTN) MaximumVariableSize - 1) / (UINTN) MaximumVariableSize);\r
+ IpSecVariableInfo.VariableSize = (UINT32) DataSize;\r
+ IpSecVariableInfo.SingleVariableSize = (UINT32) MaximumVariableSize;\r
+\r
+ //\r
+ // Set the variable of ipsecconfig general information.\r
+ //\r
+ Status = gRT->SetVariable (\r
+ VariableNameI,\r
+ VendorGuid,\r
+ Attributes,\r
+ sizeof (IpSecVariableInfo),\r
+ &IpSecVariableInfo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Error set ipsecconfig meta data with %r\n", Status));\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ for (VariableIndex = 0; VariableIndex < IpSecVariableInfo.VariableCount; VariableIndex++) {\r
+ //\r
+ // Construct and set the variable of ipsecconfig data one by one.\r
+ // The index of variable name begin from 0001, and the varaible name\r
+ // likes "VariableName0001", "VaraiableName0002"....\r
+ //\r
+ UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%04d", VariableName, VariableIndex + 1);\r
+ Status = gRT->SetVariable (\r
+ VariableNameI,\r
+ VendorGuid,\r
+ Attributes,\r
+ (VariableIndex == IpSecVariableInfo.VariableCount - 1) ?\r
+ (DataSize % (UINTN) MaximumVariableSize) :\r
+ (UINTN) MaximumVariableSize,\r
+ (UINT8 *) Data + VariableIndex * (UINTN) MaximumVariableSize\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Error set ipsecconfig variable data with %r\n", Status));\r
+ goto ON_EXIT;\r
+ }\r
+ }\r
+\r
+ON_EXIT:\r
+ if (VariableNameI != NULL) {\r
+ FreePool (VariableNameI);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Return the configuration value for the EFI IPsec driver.\r
+\r
+ This function lookup the data entry from IPsec database or IKEv2 configuration\r
+ information. The expected data type and unique identification are described in\r
+ DataType and Selector parameters.\r
+\r
+ @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.\r
+ @param[in] DataType The type of data to retrieve.\r
+ @param[in] Selector Pointer to an entry selector that is an identifier of the IPsec\r
+ configuration data entry.\r
+ @param[in, out] DataSize On output the size of data returned in Data.\r
+ @param[out] Data The buffer to return the contents of the IPsec configuration data.\r
+ The type of the data buffer associated with the DataType.\r
+\r
+ @retval EFI_SUCCESS The specified configuration data was obtained successfully.\r
+ @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:\r
+ - This is NULL.\r
+ - Selector is NULL.\r
+ - DataSize is NULL.\r
+ - Data is NULL and *DataSize is not zero\r
+ @retval EFI_NOT_FOUND The configuration data specified by Selector is not found.\r
+ @retval EFI_UNSUPPORTED The specified DataType is not supported.\r
+ @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been\r
+ updated with the size needed to complete the request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiIpSecConfigGetData (\r
+ IN EFI_IPSEC_CONFIG_PROTOCOL *This,\r
+ IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector,\r
+ IN OUT UINTN *DataSize,\r
+ OUT VOID *Data\r
+ )\r
+{\r
+ if (This == NULL || Selector == NULL || DataSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (*DataSize != 0 && Data == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (DataType >= IPsecConfigDataTypeMaximum) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return mGetPolicyEntry[DataType](Selector, DataSize, Data);\r
+}\r
+\r
+/**\r
+ Set the security association, security policy and peer authorization configuration\r
+ information for the EFI IPsec driver.\r
+\r
+ This function is used to set the IPsec configuration information of type DataType for\r
+ the EFI IPsec driver.\r
+ The IPsec configuration data has a unique selector/identifier separately to identify\r
+ a data entry. The selector structure depends on DataType's definition.\r
+ Using SetData() with a Data of NULL causes the IPsec configuration data entry identified\r
+ by DataType and Selector to be deleted.\r
+\r
+ @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.\r
+ @param[in] DataType The type of data to be set.\r
+ @param[in] Selector Pointer to an entry selector on operated configuration data\r
+ specified by DataType. A NULL Selector causes the entire\r
+ specified-type configuration information to be flushed.\r
+ @param[in] Data The data buffer to be set. The structure of the data buffer is\r
+ associated with the DataType.\r
+ @param[in] InsertBefore Pointer to one entry selector which describes the expected\r
+ position the new data entry will be added. If InsertBefore is NULL,\r
+ the new entry will be appended to the end of the database.\r
+\r
+ @retval EFI_SUCCESS The specified configuration entry data was set successfully.\r
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:\r
+ - This is NULL.\r
+ @retval EFI_UNSUPPORTED The specified DataType is not supported.\r
+ @retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiIpSecConfigSetData (\r
+ IN EFI_IPSEC_CONFIG_PROTOCOL *This,\r
+ IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector,\r
+ IN VOID *Data,\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *InsertBefore OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (DataType >= IPsecConfigDataTypeMaximum) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = mSetPolicyEntry[DataType](Selector, Data, InsertBefore);\r
+\r
+ if (!EFI_ERROR (Status) && !mSetBySelf) {\r
+ //\r
+ // Save the updated config data into variable.\r
+ //\r
+ IpSecConfigSave ();\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Enumerates the current selector for IPsec configuration data entry.\r
+\r
+ This function is called multiple times to retrieve the entry Selector in IPsec\r
+ configuration database. On each call to GetNextSelector(), the next entry\r
+ Selector are retrieved into the output interface.\r
+\r
+ If the entire IPsec configuration database has been iterated, the error\r
+ EFI_NOT_FOUND is returned.\r
+ If the Selector buffer is too small for the next Selector copy, an\r
+ EFI_BUFFER_TOO_SMALL error is returned, and SelectorSize is updated to reflect\r
+ the size of buffer needed.\r
+\r
+ On the initial call to GetNextSelector() to start the IPsec configuration database\r
+ search, a pointer to the buffer with all zero value is passed in Selector. Calls\r
+ to SetData() between calls to GetNextSelector may produce unpredictable results.\r
+\r
+ @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.\r
+ @param[in] DataType The type of IPsec configuration data to retrieve.\r
+ @param[in, out] SelectorSize The size of the Selector buffer.\r
+ @param[in, out] Selector On input, supplies the pointer to last Selector that was\r
+ returned by GetNextSelector().\r
+ On output, returns one copy of the current entry Selector\r
+ of a given DataType.\r
+\r
+ @retval EFI_SUCCESS The specified configuration data was obtained successfully.\r
+ @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:\r
+ - This is NULL.\r
+ - SelectorSize is NULL.\r
+ - Selector is NULL.\r
+ @retval EFI_NOT_FOUND The next configuration data entry was not found.\r
+ @retval EFI_UNSUPPORTED The specified DataType is not supported.\r
+ @retval EFI_BUFFER_TOO_SMALL The SelectorSize is too small for the result. This parameter\r
+ has been updated with the size needed to complete the search\r
+ request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiIpSecConfigGetNextSelector (\r
+ IN EFI_IPSEC_CONFIG_PROTOCOL *This,\r
+ IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,\r
+ IN OUT UINTN *SelectorSize,\r
+ IN OUT EFI_IPSEC_CONFIG_SELECTOR *Selector\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ IPSEC_COMMON_POLICY_ENTRY *CommonEntry;\r
+ BOOLEAN IsFound;\r
+\r
+ if (This == NULL || Selector == NULL || SelectorSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (DataType >= IPsecConfigDataTypeMaximum) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ IsFound = FALSE;\r
+\r
+ NET_LIST_FOR_EACH (Link, &mConfigData[DataType]) {\r
+ CommonEntry = BASE_CR (Link, IPSEC_COMMON_POLICY_ENTRY, List);\r
+\r
+ if (IsFound || mIsZeroSelector[DataType](Selector)) {\r
+ //\r
+ // If found the appointed entry, then duplicate the next one and return,\r
+ // or if the appointed entry is zero, then return the first one directly.\r
+ //\r
+ return mDuplicateSelector[DataType](Selector, CommonEntry->Selector, SelectorSize);\r
+ } else {\r
+ //\r
+ // Set the flag if find the appointed entry.\r
+ //\r
+ IsFound = mCompareSelector[DataType](Selector, CommonEntry->Selector);\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Register an event that is to be signaled whenever a configuration process on the\r
+ specified IPsec configuration information is done.\r
+\r
+ The register function is not surpport now and always returns EFI_UNSUPPORTED.\r
+\r
+ @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.\r
+ @param[in] DataType The type of data to be registered the event for.\r
+ @param[in] Event The event to be registered.\r
+\r
+ @retval EFI_SUCCESS The event is registered successfully.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.\r
+ @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.\r
+ @retval EFI_UNSUPPORTED The notify registration is unsupported, or the specified\r
+ DataType is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiIpSecConfigRegisterNotify (\r
+ IN EFI_IPSEC_CONFIG_PROTOCOL *This,\r
+ IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,\r
+ IN EFI_EVENT Event\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Remove the specified event that was previously registered on the specified IPsec\r
+ configuration data.\r
+\r
+ This function is not support now and alwasy return EFI_UNSUPPORTED.\r
+\r
+ @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.\r
+ @param[in] DataType The configuration data type to remove the registered event for.\r
+ @param[in] Event The event to be unregistered.\r
+\r
+ @retval EFI_SUCCESS The event was removed successfully.\r
+ @retval EFI_NOT_FOUND The Event specified by DataType could not be found in the\r
+ database.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.\r
+ @retval EFI_UNSUPPORTED The notify registration is unsupported, or the specified\r
+ DataType is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiIpSecConfigUnregisterNotify (\r
+ IN EFI_IPSEC_CONFIG_PROTOCOL *This,\r
+ IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,\r
+ IN EFI_EVENT Event\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Copy whole data in specified EFI_SIPEC_CONFIG_SELECTOR and the Data to a buffer.\r
+\r
+ This function is a caller defined function, and it is called by the IpSecVisitConfigData().\r
+ The orignal caller is IpSecConfigSave(), which calls the IpsecVisitConfigData() to\r
+ copy all types of IPsec Config datas into one buffer and store this buffer into firmware in\r
+ the form of several variables.\r
+\r
+ @param[in] Type A specified IPSEC_CONFIG_DATA_TYPE.\r
+ @param[in] Selector Points to a EFI_IPSEC_CONFIG_SELECTOR to be copied\r
+ to the buffer.\r
+ @param[in] Data Points to data to be copied to the buffer. The\r
+ Data type is related to the Type.\r
+ @param[in] SelectorSize The size of the Selector.\r
+ @param[in] DataSize The size of the Data.\r
+ @param[in, out] Buffer The buffer to store the Selector and Data.\r
+\r
+ @retval EFI_SUCCESS Copy the Selector and Data to a buffer successfully.\r
+ @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+IpSecCopyPolicyEntry (\r
+ IN EFI_IPSEC_CONFIG_DATA_TYPE Type,\r
+ IN EFI_IPSEC_CONFIG_SELECTOR *Selector,\r
+ IN VOID *Data,\r
+ IN UINTN SelectorSize,\r
+ IN UINTN DataSize,\r
+ IN OUT IPSEC_VARIABLE_BUFFER *Buffer\r
+ )\r
+{\r
+ IPSEC_VAR_ITEM_HEADER SelectorHeader;\r
+ IPSEC_VAR_ITEM_HEADER DataHeader;\r
+ UINTN EntrySize;\r
+ UINT8 *TempPoint;\r
+\r
+ if (Type == IPsecConfigDataTypeSad) {\r
+ //\r
+ // Don't save automatically-generated sa entry into variable.\r
+ //\r
+ if (((EFI_IPSEC_SA_DATA *) Data)->ManualSet == FALSE) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ //\r
+ // Increase the capacity size of the buffer if needed.\r
+ //\r
+ EntrySize = ALIGN_VARIABLE (sizeof (SelectorHeader));\r
+ EntrySize = ALIGN_VARIABLE (EntrySize + SelectorSize);\r
+ EntrySize = ALIGN_VARIABLE (EntrySize + sizeof (SelectorHeader));\r
+ EntrySize = ALIGN_VARIABLE (EntrySize + DataSize);\r
+\r
+ //EntrySize = SelectorSize + DataSize + 2 * sizeof (SelectorHeader);\r
+ if (Buffer->Capacity - Buffer->Size < EntrySize) {\r
+ //\r
+ // Calculate the required buffer\r
+ //\r
+ Buffer->Capacity += EntrySize;\r
+ TempPoint = AllocatePool (Buffer->Capacity);\r
+\r
+ if (Buffer->Ptr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Copy the old Buffer to new buffer and free the old one.\r
+ //\r
+ CopyMem (TempPoint, Buffer->Ptr, Buffer->Size);\r
+ FreePool (Buffer->Ptr);\r
+\r
+ Buffer->Ptr = TempPoint;\r
+ }\r
+\r
+ mFixPolicyEntry[Type](Selector, Data);\r
+\r
+ //\r
+ // Fill the selector header and copy it into buffer.\r
+ //\r
+ SelectorHeader.Type = (UINT8) (Type | IPSEC_VAR_ITEM_HEADER_LOGO_BIT);\r
+ SelectorHeader.Size = (UINT16) SelectorSize;\r
+\r
+ CopyMem (\r
+ Buffer->Ptr + Buffer->Size,\r
+ &SelectorHeader,\r
+ sizeof (SelectorHeader)\r
+ );\r
+ Buffer->Size = ALIGN_VARIABLE (Buffer->Size + sizeof (SelectorHeader));\r
+\r
+ //\r
+ // Copy the selector into buffer.\r
+ //\r
+ CopyMem (\r
+ Buffer->Ptr + Buffer->Size,\r
+ Selector,\r
+ SelectorSize\r
+ );\r
+ Buffer->Size = ALIGN_VARIABLE (Buffer->Size + SelectorSize);\r
+\r
+ //\r
+ // Fill the data header and copy it into buffer.\r
+ //\r
+ DataHeader.Type = (UINT8) Type;\r
+ DataHeader.Size = (UINT16) DataSize;\r
+\r
+ CopyMem (\r
+ Buffer->Ptr + Buffer->Size,\r
+ &DataHeader,\r
+ sizeof (DataHeader)\r
+ );\r
+ Buffer->Size = ALIGN_VARIABLE (Buffer->Size + sizeof (DataHeader));\r
+ //\r
+ // Copy the data into buffer.\r
+ //\r
+ CopyMem (\r
+ Buffer->Ptr + Buffer->Size,\r
+ Data,\r
+ DataSize\r
+ );\r
+ Buffer->Size = ALIGN_VARIABLE (Buffer->Size + DataSize);\r
+\r
+ mUnfixPolicyEntry[Type](Selector, Data);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Visit all IPsec Configurations of specified Type and call the caller defined\r
+ interface.\r
+\r
+ @param[in] DataType The specified IPsec Config Data Type.\r
+ @param[in] Routine The function defined by the caller.\r
+ @param[in] Context The data passed to the Routine.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated\r
+ @retval EFI_SUCCESS This function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+IpSecVisitConfigData (\r
+ IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,\r
+ IN IPSEC_COPY_POLICY_ENTRY Routine,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS GetNextStatus;\r
+ EFI_STATUS GetDataStatus;\r
+ EFI_STATUS RoutineStatus;\r
+ EFI_IPSEC_CONFIG_SELECTOR *Selector;\r
+ VOID *Data;\r
+ UINTN SelectorSize;\r
+ UINTN DataSize;\r
+ UINTN SelectorBufferSize;\r
+ UINTN DataBufferSize;\r
+ BOOLEAN FirstGetNext;\r
+\r
+ FirstGetNext = TRUE;\r
+ DataBufferSize = 0;\r
+ Data = NULL;\r
+ SelectorBufferSize = sizeof (EFI_IPSEC_CONFIG_SELECTOR);\r
+ Selector = AllocateZeroPool (SelectorBufferSize);\r
+\r
+ if (Selector == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ while (TRUE) {\r
+ //\r
+ // Get the real size of the selector.\r
+ //\r
+ SelectorSize = SelectorBufferSize;\r
+ GetNextStatus = EfiIpSecConfigGetNextSelector (\r
+ &mIpSecConfigInstance,\r
+ DataType,\r
+ &SelectorSize,\r
+ Selector\r
+ );\r
+ if (GetNextStatus == EFI_BUFFER_TOO_SMALL) {\r
+ FreePool (Selector);\r
+ SelectorBufferSize = SelectorSize;\r
+ //\r
+ // Allocate zero pool for the first selector, while store the last\r
+ // selector content for the other selectors.\r
+ //\r
+ if (FirstGetNext) {\r
+ Selector = AllocateZeroPool (SelectorBufferSize);\r
+ } else {\r
+ Selector = AllocateCopyPool (SelectorBufferSize, Selector);\r
+ }\r
+\r
+ if (Selector == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Get the content of the selector.\r
+ //\r
+ GetNextStatus = EfiIpSecConfigGetNextSelector (\r
+ &mIpSecConfigInstance,\r
+ DataType,\r
+ &SelectorSize,\r
+ Selector\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (GetNextStatus)) {\r
+ break;\r
+ }\r
+\r
+ FirstGetNext = FALSE;\r
+\r
+ //\r
+ // Get the real size of the policy entry according to the selector.\r
+ //\r
+ DataSize = DataBufferSize;\r
+ GetDataStatus = EfiIpSecConfigGetData (\r
+ &mIpSecConfigInstance,\r
+ DataType,\r
+ Selector,\r
+ &DataSize,\r
+ Data\r
+ );\r
+ if (GetDataStatus == EFI_BUFFER_TOO_SMALL) {\r
+ if (Data != NULL) {\r
+ FreePool (Data);\r
+ }\r
+\r
+ DataBufferSize = DataSize;\r
+ Data = AllocateZeroPool (DataBufferSize);\r
+\r
+ if (Data == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Get the content of the policy entry according to the selector.\r
+ //\r
+ GetDataStatus = EfiIpSecConfigGetData (\r
+ &mIpSecConfigInstance,\r
+ DataType,\r
+ Selector,\r
+ &DataSize,\r
+ Data\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (GetDataStatus)) {\r
+ break;\r
+ }\r
+ //\r
+ // Prepare the buffer of updated policy entry, which is stored in\r
+ // the continous memory, and then save into variable later.\r
+ //\r
+ RoutineStatus = Routine (\r
+ DataType,\r
+ Selector,\r
+ Data,\r
+ SelectorSize,\r
+ DataSize,\r
+ Context\r
+ );\r
+ if (EFI_ERROR (RoutineStatus)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Data != NULL) {\r
+ FreePool (Data);\r
+ }\r
+\r
+ if (Selector != NULL) {\r
+ FreePool (Selector);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function is the subfunction of EFIIpSecConfigSetData.\r
+\r
+ This function call IpSecSetVaraible to set the IPsec Configuration into the firmware.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated.\r
+ @retval EFI_SUCCESS Saved the configration successfully.\r
+ @retval Others Other errors were found while obtaining the variable.\r
+\r
+**/\r
+EFI_STATUS\r
+IpSecConfigSave (\r
+ VOID\r
+ )\r
+{\r
+ IPSEC_VARIABLE_BUFFER Buffer;\r
+ EFI_STATUS Status;\r
+ EFI_IPSEC_CONFIG_DATA_TYPE Type;\r
+\r
+ Buffer.Size = 0;\r
+ Buffer.Capacity = IPSEC_DEFAULT_VARIABLE_SIZE;\r
+ Buffer.Ptr = AllocateZeroPool (Buffer.Capacity);\r
+\r
+ if (Buffer.Ptr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // For each policy database, prepare the contious buffer to save into variable.\r
+ //\r
+ for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) {\r
+ IpSecVisitConfigData (\r
+ Type,\r
+ (IPSEC_COPY_POLICY_ENTRY) IpSecCopyPolicyEntry,\r
+ &Buffer\r
+ );\r
+ }\r
+ //\r
+ // Save the updated policy database into variable.\r
+ //\r
+ Status = IpSecSetVariable (\r
+ IPSECCONFIG_VARIABLE_NAME,\r
+ &gEfiIpSecConfigProtocolGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ Buffer.Size,\r
+ Buffer.Ptr\r
+ );\r
+\r
+ FreePool (Buffer.Ptr);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get the all IPSec configuration variables and store those variables\r
+ to the internal data structure.\r
+\r
+ This founction is called by IpSecConfigInitialize() which is to intialize the\r
+ IPsecConfiguration Protocol.\r
+\r
+ @param[in] Private Point to IPSEC_PRIVATE_DATA.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated\r
+ @retval EFI_SUCCESS Restore the IPsec Configuration successfully.\r
+ @retval others Other errors is found while obtaining the variable.\r
+\r
+**/\r
+EFI_STATUS\r
+IpSecConfigRestore (\r
+ IN IPSEC_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ UINT8 *Buffer;\r
+ IPSEC_VAR_ITEM_HEADER *Header;\r
+ UINT8 *Ptr;\r
+ EFI_IPSEC_CONFIG_SELECTOR *Selector;\r
+ EFI_IPSEC_CONFIG_DATA_TYPE Type;\r
+ VOID *Data;\r
+ UINT8 Value;\r
+ UINTN Size;\r
+\r
+ Value = 0;\r
+ Size = sizeof (Value);\r
+ BufferSize = 0;\r
+ Buffer = NULL;\r
+\r
+ Status = gRT->GetVariable (\r
+ IPSECCONFIG_STATUS_NAME,\r
+ &gEfiIpSecConfigProtocolGuid,\r
+ NULL,\r
+ &Size,\r
+ &Value\r
+ );\r
+\r
+ if (!EFI_ERROR (Status) && Value == IPSEC_STATUS_ENABLED) {\r
+ Private->IpSec.DisabledFlag = FALSE;\r
+ }\r
+ //\r
+ // Get the real size of policy database in variable.\r
+ //\r
+ Status = IpSecGetVariable (\r
+ IPSECCONFIG_VARIABLE_NAME,\r
+ &gEfiIpSecConfigProtocolGuid,\r
+ NULL,\r
+ &BufferSize,\r
+ Buffer\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+\r
+ Buffer = AllocateZeroPool (BufferSize);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Get the content of policy database in variable.\r
+ //\r
+ Status = IpSecGetVariable (\r
+ IPSECCONFIG_VARIABLE_NAME,\r
+ &gEfiIpSecConfigProtocolGuid,\r
+ NULL,\r
+ &BufferSize,\r
+ Buffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Buffer);\r
+ return Status;\r
+ }\r
+\r
+ for (Ptr = Buffer; Ptr < Buffer + BufferSize;) {\r
+\r
+ Header = (IPSEC_VAR_ITEM_HEADER *) Ptr;\r
+ Type = (EFI_IPSEC_CONFIG_DATA_TYPE) (Header->Type & IPSEC_VAR_ITEM_HEADER_CONTENT_BIT);\r
+ ASSERT (((Header->Type & 0x80) == IPSEC_VAR_ITEM_HEADER_LOGO_BIT) && (Type < IPsecConfigDataTypeMaximum));\r
+\r
+ Selector = (EFI_IPSEC_CONFIG_SELECTOR *) ALIGN_POINTER (Header + 1, sizeof (UINTN));\r
+ Header = (IPSEC_VAR_ITEM_HEADER *) ALIGN_POINTER (\r
+ (UINT8 *) Selector + Header->Size,\r
+ sizeof (UINTN)\r
+ );\r
+ ASSERT (Header->Type == Type);\r
+\r
+ Data = ALIGN_POINTER (Header + 1, sizeof (UINTN));\r
+\r
+ mUnfixPolicyEntry[Type](Selector, Data);\r
+\r
+ //\r
+ // Update each policy entry according to the content in variable.\r
+ //\r
+ mSetBySelf = TRUE;\r
+ Status = EfiIpSecConfigSetData (\r
+ &Private->IpSecConfig,\r
+ Type,\r
+ Selector,\r
+ Data,\r
+ NULL\r
+ );\r
+ mSetBySelf = FALSE;\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Buffer);\r
+ return Status;\r
+ }\r
+\r
+ Ptr = ALIGN_POINTER ((UINT8 *) Data + Header->Size, sizeof (UINTN));\r
+ }\r
+\r
+ FreePool (Buffer);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Install and Initialize IPsecConfig protocol\r
+\r
+ @param[in, out] Private Pointer to IPSEC_PRIVATE_DATA. After this function finish,\r
+ the pointer of IPsecConfig Protocol implementation will copy\r
+ into its IPsecConfig member.\r
+\r
+ @retval EFI_SUCCESS Initialized the IPsecConfig Protocol successfully.\r
+ @retval Others Initializing the IPsecConfig Protocol failed.\r
+**/\r
+EFI_STATUS\r
+IpSecConfigInitialize (\r
+ IN OUT IPSEC_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ EFI_IPSEC_CONFIG_DATA_TYPE Type;\r
+\r
+ CopyMem (\r
+ &Private->IpSecConfig,\r
+ &mIpSecConfigInstance,\r
+ sizeof (EFI_IPSEC_CONFIG_PROTOCOL)\r
+ );\r
+\r
+ //\r
+ // Initialize the list head of policy database.\r
+ //\r
+ for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) {\r
+ InitializeListHead (&mConfigData[Type]);\r
+ }\r
+ //\r
+ // Restore the content of policy database according to the variable.\r
+ //\r
+ IpSecConfigRestore (Private);\r
+\r
+ return gBS->InstallMultipleProtocolInterfaces (\r
+ &Private->Handle,\r
+ &gEfiIpSecConfigProtocolGuid,\r
+ &Private->IpSecConfig,\r
+ NULL\r
+ );\r
+}\r