Home | History | Annotate | Download | only in IpSecDxe
      1 /** @file
      2   The implementation of IPSEC_CONFIG_PROTOCOL.
      3 
      4   Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "IpSecConfigImpl.h"
     17 #include "IpSecDebug.h"
     18 
     19 LIST_ENTRY                mConfigData[IPsecConfigDataTypeMaximum];
     20 BOOLEAN                   mSetBySelf = FALSE;
     21 
     22 //
     23 // Common CompareSelector routine entry for SPD/SAD/PAD.
     24 //
     25 IPSEC_COMPARE_SELECTOR    mCompareSelector[] = {
     26   (IPSEC_COMPARE_SELECTOR) CompareSpdSelector,
     27   (IPSEC_COMPARE_SELECTOR) CompareSaId,
     28   (IPSEC_COMPARE_SELECTOR) ComparePadId
     29 };
     30 
     31 //
     32 // Common IsZeroSelector routine entry for SPD/SAD/PAD.
     33 //
     34 IPSEC_IS_ZERO_SELECTOR    mIsZeroSelector[] = {
     35   (IPSEC_IS_ZERO_SELECTOR) IsZeroSpdSelector,
     36   (IPSEC_IS_ZERO_SELECTOR) IsZeroSaId,
     37   (IPSEC_IS_ZERO_SELECTOR) IsZeroPadId
     38 };
     39 
     40 //
     41 // Common DuplicateSelector routine entry for SPD/SAD/PAD.
     42 //
     43 IPSEC_DUPLICATE_SELECTOR  mDuplicateSelector[] = {
     44   (IPSEC_DUPLICATE_SELECTOR) DuplicateSpdSelector,
     45   (IPSEC_DUPLICATE_SELECTOR) DuplicateSaId,
     46   (IPSEC_DUPLICATE_SELECTOR) DuplicatePadId
     47 };
     48 
     49 //
     50 // Common FixPolicyEntry routine entry for SPD/SAD/PAD.
     51 //
     52 IPSEC_FIX_POLICY_ENTRY    mFixPolicyEntry[] = {
     53   (IPSEC_FIX_POLICY_ENTRY) FixSpdEntry,
     54   (IPSEC_FIX_POLICY_ENTRY) FixSadEntry,
     55   (IPSEC_FIX_POLICY_ENTRY) FixPadEntry
     56 };
     57 
     58 //
     59 // Common UnfixPolicyEntry routine entry for SPD/SAD/PAD.
     60 //
     61 IPSEC_FIX_POLICY_ENTRY    mUnfixPolicyEntry[] = {
     62   (IPSEC_FIX_POLICY_ENTRY) UnfixSpdEntry,
     63   (IPSEC_FIX_POLICY_ENTRY) UnfixSadEntry,
     64   (IPSEC_FIX_POLICY_ENTRY) UnfixPadEntry
     65 };
     66 
     67 //
     68 // Common SetPolicyEntry routine entry for SPD/SAD/PAD.
     69 //
     70 IPSEC_SET_POLICY_ENTRY    mSetPolicyEntry[] = {
     71   (IPSEC_SET_POLICY_ENTRY) SetSpdEntry,
     72   (IPSEC_SET_POLICY_ENTRY) SetSadEntry,
     73   (IPSEC_SET_POLICY_ENTRY) SetPadEntry
     74 };
     75 
     76 //
     77 // Common GetPolicyEntry routine entry for SPD/SAD/PAD.
     78 //
     79 IPSEC_GET_POLICY_ENTRY    mGetPolicyEntry[] = {
     80   (IPSEC_GET_POLICY_ENTRY) GetSpdEntry,
     81   (IPSEC_GET_POLICY_ENTRY) GetSadEntry,
     82   (IPSEC_GET_POLICY_ENTRY) GetPadEntry
     83 };
     84 
     85 //
     86 // Routine entry for IpSecConfig protocol.
     87 //
     88 EFI_IPSEC_CONFIG_PROTOCOL mIpSecConfigInstance = {
     89   EfiIpSecConfigSetData,
     90   EfiIpSecConfigGetData,
     91   EfiIpSecConfigGetNextSelector,
     92   EfiIpSecConfigRegisterNotify,
     93   EfiIpSecConfigUnregisterNotify
     94 };
     95 
     96 /**
     97   Get the all IPSec configuration variables and store those variables
     98   to the internal data structure.
     99 
    100   This founction is called by IpSecConfigInitialize() that is to intialize the
    101   IPsecConfiguration Protocol.
    102 
    103   @param[in]  Private            Point to IPSEC_PRIVATE_DATA.
    104 
    105   @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated.
    106   @retval EFI_SUCCESS            Restore the IPsec Configuration successfully.
    107   @retval  others                Other errors is found during the variable getting.
    108 
    109 **/
    110 EFI_STATUS
    111 IpSecConfigRestore (
    112   IN IPSEC_PRIVATE_DATA               *Private
    113   );
    114 
    115 /**
    116   Check if the specified EFI_IP_ADDRESS_INFO is in EFI_IP_ADDRESS_INFO list.
    117 
    118   @param[in]   AddressInfo         Pointer of IP_ADDRESS_INFO to be search in AddressInfo list.
    119   @param[in]   AddressInfoList     A list that contains IP_ADDRESS_INFOs.
    120   @param[in]   AddressCount        Point out how many IP_ADDRESS_INFO in the list.
    121 
    122   @retval  TRUE    The specified AddressInfo is in the AddressInfoList.
    123   @retval  FALSE   The specified AddressInfo is not in the AddressInfoList.
    124 
    125 **/
    126 BOOLEAN
    127 IsInAddressInfoList(
    128   IN EFI_IP_ADDRESS_INFO              *AddressInfo,
    129   IN EFI_IP_ADDRESS_INFO              *AddressInfoList,
    130   IN UINT32                           AddressCount
    131   )
    132 {
    133   UINT8           Index;
    134   EFI_IP_ADDRESS  ZeroAddress;
    135 
    136   ZeroMem(&ZeroAddress, sizeof (EFI_IP_ADDRESS));
    137 
    138   //
    139   // Zero Address means any address is matched.
    140   //
    141   if (AddressCount == 1) {
    142     if (CompareMem (
    143           &AddressInfoList[0].Address,
    144           &ZeroAddress,
    145           sizeof (EFI_IP_ADDRESS)
    146           ) == 0) {
    147       return TRUE;
    148     }
    149   }
    150   for (Index = 0; Index < AddressCount ; Index++) {
    151     if (CompareMem (
    152           AddressInfo,
    153           &AddressInfoList[Index].Address,
    154           sizeof (EFI_IP_ADDRESS)
    155           ) == 0 &&
    156           AddressInfo->PrefixLength == AddressInfoList[Index].PrefixLength
    157           ) {
    158        return TRUE;
    159      }
    160   }
    161   return FALSE;
    162 }
    163 
    164 /**
    165   Compare two SPD Selectors.
    166 
    167   Compare two SPD Selector by the fields of LocalAddressCount/RemoteAddressCount/
    168   NextLayerProtocol/LocalPort/LocalPortRange/RemotePort/RemotePortRange and the
    169   Local Addresses and remote Addresses.
    170 
    171   @param[in]   Selector1           Pointer of first SPD Selector.
    172   @param[in]   Selector2           Pointer of second SPD Selector.
    173 
    174   @retval  TRUE    This two Selector have the same value in above fields.
    175   @retval  FALSE   Not all above fields have the same value in these two Selectors.
    176 
    177 **/
    178 BOOLEAN
    179 CompareSpdSelector (
    180   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector1,
    181   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector2
    182   )
    183 {
    184   EFI_IPSEC_SPD_SELECTOR  *SpdSel1;
    185   EFI_IPSEC_SPD_SELECTOR  *SpdSel2;
    186   BOOLEAN                 IsMatch;
    187   UINTN                   Index;
    188 
    189   SpdSel1 = &Selector1->SpdSelector;
    190   SpdSel2 = &Selector2->SpdSelector;
    191   IsMatch = TRUE;
    192 
    193   //
    194   // Compare the LocalAddressCount/RemoteAddressCount/NextLayerProtocol/
    195   // LocalPort/LocalPortRange/RemotePort/RemotePortRange fields in the
    196   // two Spdselectors. Since the SPD supports two directions, it needs to
    197   // compare two directions.
    198   //
    199   if ((SpdSel1->LocalAddressCount != SpdSel2->LocalAddressCount &&
    200        SpdSel1->LocalAddressCount != SpdSel2->RemoteAddressCount) ||
    201       (SpdSel1->RemoteAddressCount != SpdSel2->RemoteAddressCount &&
    202        SpdSel1->RemoteAddressCount != SpdSel2->LocalAddressCount) ||
    203        SpdSel1->NextLayerProtocol != SpdSel2->NextLayerProtocol ||
    204        SpdSel1->LocalPort != SpdSel2->LocalPort ||
    205        SpdSel1->LocalPortRange != SpdSel2->LocalPortRange ||
    206        SpdSel1->RemotePort != SpdSel2->RemotePort ||
    207        SpdSel1->RemotePortRange != SpdSel2->RemotePortRange
    208        ) {
    209     IsMatch = FALSE;
    210     return IsMatch;
    211   }
    212 
    213   //
    214   // Compare the all LocalAddress fields in the two Spdselectors.
    215   // First, SpdSel1->LocalAddress to SpdSel2->LocalAddress && Compare
    216   // SpdSel1->RemoteAddress to SpdSel2->RemoteAddress. If all match, return
    217   // TRUE.
    218   //
    219   for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) {
    220     if (!IsInAddressInfoList (
    221           &SpdSel1->LocalAddress[Index],
    222           SpdSel2->LocalAddress,
    223           SpdSel2->LocalAddressCount
    224           )) {
    225       IsMatch = FALSE;
    226       break;
    227     }
    228   }
    229   if (IsMatch) {
    230     for (Index = 0; Index < SpdSel2->LocalAddressCount; Index++) {
    231       if (!IsInAddressInfoList (
    232             &SpdSel2->LocalAddress[Index],
    233             SpdSel1->LocalAddress,
    234             SpdSel1->LocalAddressCount
    235             )) {
    236         IsMatch = FALSE;
    237         break;
    238       }
    239     }
    240   }
    241   if (IsMatch) {
    242     for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) {
    243       if (!IsInAddressInfoList (
    244             &SpdSel1->RemoteAddress[Index],
    245             SpdSel2->RemoteAddress,
    246             SpdSel2->RemoteAddressCount
    247             )) {
    248         IsMatch = FALSE;
    249         break;
    250       }
    251     }
    252   }
    253   if (IsMatch) {
    254     for (Index = 0; Index < SpdSel2->RemoteAddressCount; Index++) {
    255       if (!IsInAddressInfoList (
    256             &SpdSel2->RemoteAddress[Index],
    257             SpdSel1->RemoteAddress,
    258             SpdSel1->RemoteAddressCount
    259             )) {
    260         IsMatch = FALSE;
    261         break;
    262       }
    263     }
    264   }
    265   //
    266   // Finish the one direction compare. If it is matched, return; otherwise,
    267   // compare the other direction.
    268   //
    269   if (IsMatch) {
    270     return IsMatch;
    271   }
    272   //
    273   // Secondly, the SpdSel1->LocalAddress doesn't equal to  SpdSel2->LocalAddress and
    274   // SpdSel1->RemoteAddress doesn't equal to SpdSel2->RemoteAddress. Try to compare
    275   // the RemoteAddress to LocalAddress.
    276   //
    277   IsMatch = TRUE;
    278   for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) {
    279     if (!IsInAddressInfoList (
    280           &SpdSel1->RemoteAddress[Index],
    281           SpdSel2->LocalAddress,
    282           SpdSel2->LocalAddressCount
    283           )) {
    284       IsMatch = FALSE;
    285       break;
    286     }
    287   }
    288   if (IsMatch) {
    289     for (Index = 0; Index < SpdSel2->RemoteAddressCount; Index++) {
    290       if (!IsInAddressInfoList (
    291             &SpdSel2->RemoteAddress[Index],
    292             SpdSel1->LocalAddress,
    293             SpdSel1->LocalAddressCount
    294             )) {
    295         IsMatch = FALSE;
    296         break;
    297       }
    298     }
    299   }
    300   if (IsMatch) {
    301     for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) {
    302       if (!IsInAddressInfoList (
    303             &SpdSel1->LocalAddress[Index],
    304             SpdSel2->RemoteAddress,
    305             SpdSel2->RemoteAddressCount
    306             )) {
    307         IsMatch = FALSE;
    308         break;
    309       }
    310     }
    311   }
    312   if (IsMatch) {
    313     for (Index = 0; Index < SpdSel2->LocalAddressCount; Index++) {
    314       if (!IsInAddressInfoList (
    315             &SpdSel2->LocalAddress[Index],
    316             SpdSel1->RemoteAddress,
    317             SpdSel1->RemoteAddressCount
    318             )) {
    319         IsMatch = FALSE;
    320         break;
    321       }
    322     }
    323   }
    324   return IsMatch;
    325 }
    326 
    327 /**
    328   Find if the two SPD Selectors has subordinative.
    329 
    330   Compare two SPD Selector by the fields of LocalAddressCount/RemoteAddressCount/
    331   NextLayerProtocol/LocalPort/LocalPortRange/RemotePort/RemotePortRange and the
    332   Local Addresses and remote Addresses.
    333 
    334   @param[in]   Selector1           Pointer of first SPD Selector.
    335   @param[in]   Selector2           Pointer of second SPD Selector.
    336 
    337   @retval  TRUE    The first SPD Selector is subordinate Selector of second SPD Selector.
    338   @retval  FALSE   The first SPD Selector is not subordinate Selector of second
    339                    SPD Selector.
    340 
    341 **/
    342 BOOLEAN
    343 IsSubSpdSelector (
    344   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector1,
    345   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector2
    346   )
    347 {
    348   EFI_IPSEC_SPD_SELECTOR  *SpdSel1;
    349   EFI_IPSEC_SPD_SELECTOR  *SpdSel2;
    350   BOOLEAN                 IsMatch;
    351   UINTN                   Index;
    352 
    353   SpdSel1 = &Selector1->SpdSelector;
    354   SpdSel2 = &Selector2->SpdSelector;
    355   IsMatch = TRUE;
    356 
    357   //
    358   // Compare the LocalAddressCount/RemoteAddressCount/NextLayerProtocol/
    359   // LocalPort/LocalPortRange/RemotePort/RemotePortRange fields in the
    360   // two Spdselectors. Since the SPD supports two directions, it needs to
    361   // compare two directions.
    362   //
    363   if (SpdSel1->LocalAddressCount > SpdSel2->LocalAddressCount ||
    364       SpdSel1->RemoteAddressCount > SpdSel2->RemoteAddressCount ||
    365       (SpdSel1->NextLayerProtocol != SpdSel2->NextLayerProtocol && SpdSel2->NextLayerProtocol != 0xffff) ||
    366       (SpdSel1->LocalPort > SpdSel2->LocalPort && SpdSel2->LocalPort != 0)||
    367       (SpdSel1->LocalPortRange > SpdSel2->LocalPortRange && SpdSel1->LocalPort != 0)||
    368       (SpdSel1->RemotePort > SpdSel2->RemotePort && SpdSel2->RemotePort != 0) ||
    369       (SpdSel1->RemotePortRange > SpdSel2->RemotePortRange && SpdSel2->RemotePort != 0)
    370       ) {
    371     IsMatch = FALSE;
    372   }
    373 
    374   //
    375   // Compare the all LocalAddress fields in the two Spdselectors.
    376   // First, SpdSel1->LocalAddress to SpdSel2->LocalAddress && Compare
    377   // SpdSel1->RemoteAddress to SpdSel2->RemoteAddress. If all match, return
    378   // TRUE.
    379   //
    380   if (IsMatch) {
    381     for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) {
    382       if (!IsInAddressInfoList (
    383             &SpdSel1->LocalAddress[Index],
    384             SpdSel2->LocalAddress,
    385             SpdSel2->LocalAddressCount
    386             )) {
    387         IsMatch = FALSE;
    388         break;
    389       }
    390     }
    391 
    392     if (IsMatch) {
    393       for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) {
    394         if (!IsInAddressInfoList (
    395               &SpdSel1->RemoteAddress[Index],
    396               SpdSel2->RemoteAddress,
    397               SpdSel2->RemoteAddressCount
    398               )) {
    399           IsMatch = FALSE;
    400           break;
    401         }
    402       }
    403     }
    404   }
    405   if (IsMatch) {
    406     return IsMatch;
    407   }
    408 
    409   //
    410   //
    411   // The SPD selector in SPD entry is two way.
    412   //
    413   // Compare the LocalAddressCount/RemoteAddressCount/NextLayerProtocol/
    414   // LocalPort/LocalPortRange/RemotePort/RemotePortRange fields in the
    415   // two Spdselectors. Since the SPD supports two directions, it needs to
    416   // compare two directions.
    417   //
    418   IsMatch = TRUE;
    419   if (SpdSel1->LocalAddressCount > SpdSel2->RemoteAddressCount ||
    420       SpdSel1->RemoteAddressCount > SpdSel2->LocalAddressCount ||
    421       (SpdSel1->NextLayerProtocol != SpdSel2->NextLayerProtocol && SpdSel2->NextLayerProtocol != 0xffff) ||
    422       (SpdSel1->LocalPort > SpdSel2->RemotePort && SpdSel2->RemotePort != 0)||
    423       (SpdSel1->LocalPortRange > SpdSel2->RemotePortRange && SpdSel1->RemotePort != 0)||
    424       (SpdSel1->RemotePort > SpdSel2->LocalPort && SpdSel2->LocalPort != 0) ||
    425       (SpdSel1->RemotePortRange > SpdSel2->LocalPortRange && SpdSel2->LocalPort != 0)
    426       ) {
    427     IsMatch = FALSE;
    428     return IsMatch;
    429   }
    430 
    431   //
    432   // Compare the all LocalAddress fields in the two Spdselectors.
    433   // First, SpdSel1->LocalAddress to SpdSel2->LocalAddress && Compare
    434   // SpdSel1->RemoteAddress to SpdSel2->RemoteAddress. If all match, return
    435   // TRUE.
    436   //
    437   for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) {
    438     if (!IsInAddressInfoList (
    439           &SpdSel1->LocalAddress[Index],
    440           SpdSel2->RemoteAddress,
    441           SpdSel2->RemoteAddressCount
    442           )) {
    443       IsMatch = FALSE;
    444       break;
    445     }
    446   }
    447 
    448   if (IsMatch) {
    449     for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) {
    450       if (!IsInAddressInfoList (
    451             &SpdSel1->RemoteAddress[Index],
    452             SpdSel2->LocalAddress,
    453             SpdSel2->LocalAddressCount
    454             )) {
    455         IsMatch = FALSE;
    456         break;
    457       }
    458     }
    459   }
    460   return IsMatch;
    461 
    462 }
    463 
    464 /**
    465   Compare two SA IDs.
    466 
    467   @param[in]   Selector1           Pointer of first SA ID.
    468   @param[in]   Selector2           Pointer of second SA ID.
    469 
    470   @retval  TRUE    This two Selectors have the same SA ID.
    471   @retval  FALSE   This two Selecotrs don't have the same SA ID.
    472 
    473 **/
    474 BOOLEAN
    475 CompareSaId (
    476   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector1,
    477   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector2
    478   )
    479 {
    480   EFI_IPSEC_SA_ID *SaId1;
    481   EFI_IPSEC_SA_ID *SaId2;
    482   BOOLEAN         IsMatch;
    483 
    484   SaId1   = &Selector1->SaId;
    485   SaId2   = &Selector2->SaId;
    486   IsMatch = TRUE;
    487 
    488   if (CompareMem (SaId1, SaId2, sizeof (EFI_IPSEC_SA_ID)) != 0) {
    489     IsMatch = FALSE;
    490   }
    491 
    492   return IsMatch;
    493 }
    494 
    495 /**
    496   Compare two PAD IDs.
    497 
    498   @param[in]   Selector1           Pointer of first PAD ID.
    499   @param[in]   Selector2           Pointer of second PAD ID.
    500 
    501   @retval  TRUE    This two Selectors have the same PAD ID.
    502   @retval  FALSE   This two Selecotrs don't have the same PAD ID.
    503 
    504 **/
    505 BOOLEAN
    506 ComparePadId (
    507   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector1,
    508   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector2
    509   )
    510 {
    511   EFI_IPSEC_PAD_ID  *PadId1;
    512   EFI_IPSEC_PAD_ID  *PadId2;
    513   BOOLEAN           IsMatch;
    514 
    515   PadId1  = &Selector1->PadId;
    516   PadId2  = &Selector2->PadId;
    517   IsMatch = TRUE;
    518 
    519   //
    520   // Compare the PeerIdValid fields in PadId.
    521   //
    522   if (PadId1->PeerIdValid != PadId2->PeerIdValid) {
    523     IsMatch = FALSE;
    524   }
    525   //
    526   // Compare the PeerId fields in PadId if PeerIdValid is true.
    527   //
    528   if (IsMatch &&
    529       PadId1->PeerIdValid &&
    530       AsciiStriCmp ((CONST CHAR8 *) PadId1->Id.PeerId, (CONST CHAR8 *) PadId2->Id.PeerId) != 0
    531       ) {
    532     IsMatch = FALSE;
    533   }
    534   //
    535   // Compare the IpAddress fields in PadId if PeerIdValid is false.
    536   //
    537   if (IsMatch &&
    538       !PadId1->PeerIdValid &&
    539       (PadId1->Id.IpAddress.PrefixLength != PadId2->Id.IpAddress.PrefixLength ||
    540        CompareMem (&PadId1->Id.IpAddress.Address, &PadId2->Id.IpAddress.Address, sizeof (EFI_IP_ADDRESS)) != 0)
    541       ) {
    542     IsMatch = FALSE;
    543   }
    544 
    545   return IsMatch;
    546 }
    547 
    548 /**
    549   Check if the SPD Selector is Zero by its LocalAddressCount and RemoteAddressCount
    550   fields.
    551 
    552   @param[in]  Selector      Pointer of the SPD Selector.
    553 
    554   @retval     TRUE          If the SPD Selector is Zero.
    555   @retval     FALSE         If the SPD Selector is not Zero.
    556 
    557 **/
    558 BOOLEAN
    559 IsZeroSpdSelector (
    560   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector
    561   )
    562 {
    563   EFI_IPSEC_SPD_SELECTOR  *SpdSel;
    564   BOOLEAN                 IsZero;
    565 
    566   SpdSel  = &Selector->SpdSelector;
    567   IsZero  = FALSE;
    568 
    569   if (SpdSel->LocalAddressCount == 0 && SpdSel->RemoteAddressCount == 0) {
    570     IsZero = TRUE;
    571   }
    572 
    573   return IsZero;
    574 }
    575 
    576 /**
    577   Check if the SA ID is Zero by its DestAddress.
    578 
    579   @param[in]  Selector      Pointer of the SA ID.
    580 
    581   @retval     TRUE          If the SA ID is Zero.
    582   @retval     FALSE         If the SA ID is not Zero.
    583 
    584 **/
    585 BOOLEAN
    586 IsZeroSaId (
    587   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector
    588   )
    589 {
    590   BOOLEAN                   IsZero;
    591   EFI_IPSEC_CONFIG_SELECTOR ZeroSelector;
    592 
    593   IsZero    = FALSE;
    594 
    595   ZeroMem (&ZeroSelector, sizeof (EFI_IPSEC_CONFIG_SELECTOR));
    596 
    597   if (CompareMem (&ZeroSelector, Selector, sizeof (EFI_IPSEC_CONFIG_SELECTOR)) == 0) {
    598     IsZero = TRUE;
    599   }
    600 
    601   return IsZero;
    602 }
    603 
    604 /**
    605   Check if the PAD ID is Zero.
    606 
    607   @param[in]  Selector      Pointer of the PAD ID.
    608 
    609   @retval     TRUE          If the PAD ID is Zero.
    610   @retval     FALSE         If the PAD ID is not Zero.
    611 
    612 **/
    613 BOOLEAN
    614 IsZeroPadId (
    615   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector
    616   )
    617 {
    618   EFI_IPSEC_PAD_ID  *PadId;
    619   EFI_IPSEC_PAD_ID  ZeroId;
    620   BOOLEAN           IsZero;
    621 
    622   PadId   = &Selector->PadId;
    623   IsZero  = FALSE;
    624 
    625   ZeroMem (&ZeroId, sizeof (EFI_IPSEC_PAD_ID));
    626 
    627   if (CompareMem (PadId, &ZeroId, sizeof (EFI_IPSEC_PAD_ID)) == 0) {
    628     IsZero = TRUE;
    629   }
    630 
    631   return IsZero;
    632 }
    633 
    634 /**
    635   Copy Source SPD Selector to the Destination SPD Selector.
    636 
    637   @param[in, out] DstSel             Pointer of Destination SPD Selector.
    638   @param[in]      SrcSel             Pointer of Source SPD Selector.
    639   @param[in, out] Size               The size of the Destination SPD Selector. If it
    640                                      not NULL and its value less than the size of
    641                                      Source SPD Selector, the value of Source SPD
    642                                      Selector's size will be passed to caller by this
    643                                      parameter.
    644 
    645   @retval EFI_INVALID_PARAMETER  If the Destination or Source SPD Selector is NULL
    646   @retval EFI_BUFFER_TOO_SMALL   If the input Size is less than size of the Source SPD Selector.
    647   @retval EFI_SUCCESS            Copy Source SPD Selector to the Destination SPD
    648                                  Selector successfully.
    649 
    650 **/
    651 EFI_STATUS
    652 DuplicateSpdSelector (
    653   IN OUT EFI_IPSEC_CONFIG_SELECTOR    *DstSel,
    654   IN     EFI_IPSEC_CONFIG_SELECTOR    *SrcSel,
    655   IN OUT UINTN                        *Size
    656   )
    657 {
    658   EFI_IPSEC_SPD_SELECTOR  *Dst;
    659   EFI_IPSEC_SPD_SELECTOR  *Src;
    660 
    661   Dst = &DstSel->SpdSelector;
    662   Src = &SrcSel->SpdSelector;
    663 
    664   if (Dst == NULL || Src == NULL) {
    665     return EFI_INVALID_PARAMETER;
    666   }
    667 
    668   if (Size != NULL && (*Size) < SIZE_OF_SPD_SELECTOR (Src)) {
    669     *Size = SIZE_OF_SPD_SELECTOR (Src);
    670     return EFI_BUFFER_TOO_SMALL;
    671   }
    672   //
    673   // Copy the base structure of SPD selector.
    674   //
    675   CopyMem (Dst, Src, sizeof (EFI_IPSEC_SPD_SELECTOR));
    676 
    677   //
    678   // Copy the local address array of SPD selector.
    679   //
    680   Dst->LocalAddress = (EFI_IP_ADDRESS_INFO *) (Dst + 1);
    681   CopyMem (
    682     Dst->LocalAddress,
    683     Src->LocalAddress,
    684     sizeof (EFI_IP_ADDRESS_INFO) * Dst->LocalAddressCount
    685     );
    686 
    687   //
    688   // Copy the remote address array of SPD selector.
    689   //
    690   Dst->RemoteAddress = Dst->LocalAddress + Dst->LocalAddressCount;
    691   CopyMem (
    692     Dst->RemoteAddress,
    693     Src->RemoteAddress,
    694     sizeof (EFI_IP_ADDRESS_INFO) * Dst->RemoteAddressCount
    695     );
    696 
    697   return EFI_SUCCESS;
    698 }
    699 
    700 /**
    701   Copy Source SA ID to the Destination SA ID.
    702 
    703   @param[in, out] DstSel             Pointer of Destination SA ID.
    704   @param[in]      SrcSel             Pointer of Source SA ID.
    705   @param[in, out] Size               The size of the Destination SA ID. If it
    706                                      not NULL and its value less than the size of
    707                                      Source SA ID, the value of Source SA ID's size
    708                                      will be passed to caller by this parameter.
    709 
    710   @retval EFI_INVALID_PARAMETER  If the Destination or Source SA ID is NULL.
    711   @retval EFI_BUFFER_TOO_SMALL   If the input Size less than size of source SA ID.
    712   @retval EFI_SUCCESS            Copy Source SA ID  to the Destination SA ID successfully.
    713 
    714 **/
    715 EFI_STATUS
    716 DuplicateSaId (
    717   IN OUT EFI_IPSEC_CONFIG_SELECTOR    *DstSel,
    718   IN     EFI_IPSEC_CONFIG_SELECTOR    *SrcSel,
    719   IN OUT UINTN                        *Size
    720   )
    721 {
    722   EFI_IPSEC_SA_ID *Dst;
    723   EFI_IPSEC_SA_ID *Src;
    724 
    725   Dst = &DstSel->SaId;
    726   Src = &SrcSel->SaId;
    727 
    728   if (Dst == NULL || Src == NULL) {
    729     return EFI_INVALID_PARAMETER;
    730   }
    731 
    732   if (Size != NULL && *Size < sizeof (EFI_IPSEC_SA_ID)) {
    733     *Size = sizeof (EFI_IPSEC_SA_ID);
    734     return EFI_BUFFER_TOO_SMALL;
    735   }
    736 
    737   CopyMem (Dst, Src, sizeof (EFI_IPSEC_SA_ID));
    738 
    739   return EFI_SUCCESS;
    740 }
    741 
    742 /**
    743   Copy Source PAD ID to the Destination PAD ID.
    744 
    745   @param[in, out] DstSel             Pointer of Destination PAD ID.
    746   @param[in]      SrcSel             Pointer of Source PAD ID.
    747   @param[in, out] Size               The size of the Destination PAD ID. If it
    748                                      not NULL and its value less than the size of
    749                                      Source PAD ID, the value of Source PAD ID's size
    750                                      will be passed to caller by this parameter.
    751 
    752   @retval EFI_INVALID_PARAMETER  If the Destination or Source PAD ID is NULL.
    753   @retval EFI_BUFFER_TOO_SMALL   If the input Size less than size of source PAD ID .
    754   @retval EFI_SUCCESS            Copy Source PAD ID  to the Destination PAD ID successfully.
    755 
    756 **/
    757 EFI_STATUS
    758 DuplicatePadId (
    759   IN OUT EFI_IPSEC_CONFIG_SELECTOR    *DstSel,
    760   IN     EFI_IPSEC_CONFIG_SELECTOR    *SrcSel,
    761   IN OUT UINTN                        *Size
    762   )
    763 {
    764   EFI_IPSEC_PAD_ID  *Dst;
    765   EFI_IPSEC_PAD_ID  *Src;
    766 
    767   Dst = &DstSel->PadId;
    768   Src = &SrcSel->PadId;
    769 
    770   if (Dst == NULL || Src == NULL) {
    771     return EFI_INVALID_PARAMETER;
    772   }
    773 
    774   if (Size != NULL && *Size < sizeof (EFI_IPSEC_PAD_ID)) {
    775     *Size = sizeof (EFI_IPSEC_PAD_ID);
    776     return EFI_BUFFER_TOO_SMALL;
    777   }
    778 
    779   CopyMem (Dst, Src, sizeof (EFI_IPSEC_PAD_ID));
    780 
    781   return EFI_SUCCESS;
    782 }
    783 
    784 /**
    785   Fix the value of some members of SPD Selector.
    786 
    787   This function is called by IpSecCopyPolicyEntry()which copy the Policy
    788   Entry into the Variable. Since some members in SPD Selector are pointers,
    789   a physical address to relative address convertion is required before copying
    790   this SPD entry into the variable.
    791 
    792   @param[in]       Selector              Pointer of SPD Selector.
    793   @param[in, out]  Data                  Pointer of SPD Data.
    794 
    795 **/
    796 VOID
    797 FixSpdEntry (
    798   IN     EFI_IPSEC_SPD_SELECTOR            *Selector,
    799   IN OUT EFI_IPSEC_SPD_DATA                *Data
    800   )
    801 {
    802   //
    803   // It assumes that all ref buffers in SPD selector and data are
    804   // stored in the continous memory and close to the base structure.
    805   //
    806   FIX_REF_BUF_ADDR (Selector->LocalAddress, Selector);
    807   FIX_REF_BUF_ADDR (Selector->RemoteAddress, Selector);
    808 
    809   if (Data->ProcessingPolicy != NULL) {
    810     if (Data->ProcessingPolicy->TunnelOption != NULL) {
    811       FIX_REF_BUF_ADDR (Data->ProcessingPolicy->TunnelOption, Data);
    812     }
    813 
    814     FIX_REF_BUF_ADDR (Data->ProcessingPolicy, Data);
    815   }
    816 
    817 }
    818 
    819 /**
    820   Fix the value of some members of SA ID.
    821 
    822   This function is called by IpSecCopyPolicyEntry()which copy the Policy
    823   Entry into the Variable. Since some members in SA ID are pointers,
    824   a physical address to relative address conversion is required before copying
    825   this SAD into the variable.
    826 
    827   @param[in]       SaId                  Pointer of SA ID
    828   @param[in, out]  Data                  Pointer of SA Data.
    829 
    830 **/
    831 VOID
    832 FixSadEntry (
    833   IN     EFI_IPSEC_SA_ID                  *SaId,
    834   IN OUT EFI_IPSEC_SA_DATA2                *Data
    835   )
    836 {
    837   //
    838   // It assumes that all ref buffers in SAD selector and data are
    839   // stored in the continous memory and close to the base structure.
    840   //
    841   if (Data->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {
    842     FIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.AuthKey, Data);
    843   }
    844 
    845   if (SaId->Proto == EfiIPsecESP && Data->AlgoInfo.EspAlgoInfo.EncKey != NULL) {
    846     FIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.EncKey, Data);
    847   }
    848 
    849   if (Data->SpdSelector != NULL) {
    850     if (Data->SpdSelector->LocalAddress != NULL) {
    851       FIX_REF_BUF_ADDR (Data->SpdSelector->LocalAddress, Data);
    852     }
    853 
    854     FIX_REF_BUF_ADDR (Data->SpdSelector->RemoteAddress, Data);
    855     FIX_REF_BUF_ADDR (Data->SpdSelector, Data);
    856   }
    857 
    858 }
    859 
    860 /**
    861   Fix the value of some members of PAD ID.
    862 
    863   This function is called by IpSecCopyPolicyEntry()which copy the Policy
    864   Entry into the Variable. Since some members in PAD ID are pointers,
    865   a physical address to relative address conversion is required before copying
    866   this PAD into the variable.
    867 
    868   @param[in]       PadId              Pointer of PAD ID.
    869   @param[in, out]  Data               Pointer of PAD Data.
    870 
    871 **/
    872 VOID
    873 FixPadEntry (
    874   IN     EFI_IPSEC_PAD_ID                  *PadId,
    875   IN OUT EFI_IPSEC_PAD_DATA                *Data
    876   )
    877 {
    878   //
    879   // It assumes that all ref buffers in pad selector and data are
    880   // stored in the continous memory and close to the base structure.
    881   //
    882   if (Data->AuthData != NULL) {
    883     FIX_REF_BUF_ADDR (Data->AuthData, Data);
    884   }
    885 
    886   if (Data->RevocationData != NULL) {
    887     FIX_REF_BUF_ADDR (Data->RevocationData, Data);
    888   }
    889 
    890 }
    891 
    892 /**
    893   Recover the value of some members of SPD Selector.
    894 
    895   This function is corresponding to FixSpdEntry(). It recovers the value of members
    896   of SPD Selector that are fixed by FixSpdEntry().
    897 
    898   @param[in, out]  Selector              Pointer of SPD Selector.
    899   @param[in, out]  Data                  Pointer of SPD Data.
    900 
    901 **/
    902 VOID
    903 UnfixSpdEntry (
    904   IN OUT EFI_IPSEC_SPD_SELECTOR           *Selector,
    905   IN OUT EFI_IPSEC_SPD_DATA               *Data
    906   )
    907 {
    908   //
    909   // It assumes that all ref buffers in SPD selector and data are
    910   // stored in the continous memory and close to the base structure.
    911   //
    912   UNFIX_REF_BUF_ADDR (Selector->LocalAddress, Selector);
    913   UNFIX_REF_BUF_ADDR (Selector->RemoteAddress, Selector);
    914 
    915   if (Data->ProcessingPolicy != NULL) {
    916     UNFIX_REF_BUF_ADDR (Data->ProcessingPolicy, Data);
    917     if (Data->ProcessingPolicy->TunnelOption != NULL) {
    918       UNFIX_REF_BUF_ADDR (Data->ProcessingPolicy->TunnelOption, Data);
    919     }
    920   }
    921 
    922 }
    923 
    924 /**
    925   Recover the value of some members of SA ID.
    926 
    927   This function is corresponding to FixSadEntry(). It recovers the value of members
    928   of SAD ID that are fixed by FixSadEntry().
    929 
    930   @param[in, out]  SaId              Pointer of SAD ID.
    931   @param[in, out]  Data              Pointer of SAD Data.
    932 
    933 **/
    934 VOID
    935 UnfixSadEntry (
    936   IN OUT EFI_IPSEC_SA_ID                     *SaId,
    937   IN OUT EFI_IPSEC_SA_DATA2                   *Data
    938   )
    939 {
    940   //
    941   // It assumes that all ref buffers in SAD selector and data are
    942   // stored in the continous memory and close to the base structure.
    943   //
    944   if (Data->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {
    945     UNFIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.AuthKey, Data);
    946   }
    947 
    948   if (SaId->Proto == EfiIPsecESP && Data->AlgoInfo.EspAlgoInfo.EncKey != NULL) {
    949     UNFIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.EncKey, Data);
    950   }
    951 
    952   if (Data->SpdSelector != NULL) {
    953     UNFIX_REF_BUF_ADDR (Data->SpdSelector, Data);
    954     if (Data->SpdSelector->LocalAddress != NULL) {
    955       UNFIX_REF_BUF_ADDR (Data->SpdSelector->LocalAddress, Data);
    956     }
    957 
    958     UNFIX_REF_BUF_ADDR (Data->SpdSelector->RemoteAddress, Data);
    959   }
    960 
    961 }
    962 
    963 /**
    964   Recover the value of some members of PAD ID.
    965 
    966   This function is corresponding to FixPadEntry(). It recovers the value of members
    967   of PAD ID that are fixed by FixPadEntry().
    968 
    969   @param[in]       PadId              Pointer of PAD ID.
    970   @param[in, out]  Data               Pointer of PAD Data.
    971 
    972 **/
    973 VOID
    974 UnfixPadEntry (
    975   IN     EFI_IPSEC_PAD_ID                 *PadId,
    976   IN OUT EFI_IPSEC_PAD_DATA               *Data
    977   )
    978 {
    979   //
    980   // It assumes that all ref buffers in pad selector and data are
    981   // stored in the continous memory and close to the base structure.
    982   //
    983   if (Data->AuthData != NULL) {
    984     UNFIX_REF_BUF_ADDR (Data->AuthData, Data);
    985   }
    986 
    987   if (Data->RevocationData != NULL) {
    988     UNFIX_REF_BUF_ADDR (Data->RevocationData, Data);
    989   }
    990 
    991 }
    992 
    993 /**
    994   Set the security policy information for the EFI IPsec driver.
    995 
    996   The IPsec configuration data has a unique selector/identifier separately to
    997   identify a data entry.
    998 
    999   @param[in]  Selector           Pointer to an entry selector on operated
   1000                                  configuration data specified by DataType.
   1001                                  A NULL Selector causes the entire specified-type
   1002                                  configuration information to be flushed.
   1003   @param[in]  Data               The data buffer to be set. The structure
   1004                                  of the data buffer should be EFI_IPSEC_SPD_DATA.
   1005   @param[in]  Context            Pointer to one entry selector that describes
   1006                                  the expected position the new data entry will
   1007                                  be added. If Context is NULL, the new entry will
   1008                                  be appended the end of database.
   1009 
   1010   @retval EFI_INVALID_PARAMETER  One or more of the following are TRUE:
   1011                                    - Selector is not NULL and its LocalAddress
   1012                                      is NULL or its RemoteAddress is NULL.
   1013                                    - Data is not NULL and its Action is Protected
   1014                                      and its plolicy is NULL.
   1015                                    - Data is not NULL, its Action is not protected,
   1016                                      and its policy is not NULL.
   1017                                    - The Action of Data is Protected, its policy
   1018                                      mode is Tunnel, and its tunnel option is NULL.
   1019                                    - The Action of Data is protected and its policy
   1020                                      mode is not Tunnel and it tunnel option is not NULL.
   1021   @retval EFI_OUT_OF_RESOURCED  The required system resource could not be allocated.
   1022   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1023 
   1024 **/
   1025 EFI_STATUS
   1026 SetSpdEntry (
   1027   IN EFI_IPSEC_CONFIG_SELECTOR       *Selector,
   1028   IN VOID                            *Data,
   1029   IN VOID                            *Context OPTIONAL
   1030   )
   1031 {
   1032   EFI_IPSEC_SPD_SELECTOR  *SpdSel;
   1033   EFI_IPSEC_SPD_DATA      *SpdData;
   1034   EFI_IPSEC_SPD_SELECTOR  *InsertBefore;
   1035   LIST_ENTRY              *SpdList;
   1036   LIST_ENTRY              *SadList;
   1037   LIST_ENTRY              *SpdSas;
   1038   LIST_ENTRY              *EntryInsertBefore;
   1039   LIST_ENTRY              *Entry;
   1040   LIST_ENTRY              *Entry2;
   1041   LIST_ENTRY              *NextEntry;
   1042   IPSEC_SPD_ENTRY         *SpdEntry;
   1043   IPSEC_SAD_ENTRY         *SadEntry;
   1044   UINTN                   SpdEntrySize;
   1045   UINTN                   Index;
   1046 
   1047   SpdSel        = (Selector == NULL) ? NULL : &Selector->SpdSelector;
   1048   SpdData       = (Data == NULL) ? NULL : (EFI_IPSEC_SPD_DATA *) Data;
   1049   InsertBefore  = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->SpdSelector;
   1050   SpdList       = &mConfigData[IPsecConfigDataTypeSpd];
   1051 
   1052   if (SpdSel != NULL) {
   1053     if (SpdSel->LocalAddress == NULL || SpdSel->RemoteAddress == NULL) {
   1054       return EFI_INVALID_PARAMETER;
   1055     }
   1056   }
   1057 
   1058   if (SpdData != NULL) {
   1059     if ((SpdData->Action == EfiIPsecActionProtect && SpdData->ProcessingPolicy == NULL) ||
   1060         (SpdData->Action != EfiIPsecActionProtect && SpdData->ProcessingPolicy != NULL)
   1061         ) {
   1062       return EFI_INVALID_PARAMETER;
   1063     }
   1064 
   1065     if (SpdData->Action == EfiIPsecActionProtect) {
   1066       if ((SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel && SpdData->ProcessingPolicy->TunnelOption == NULL) ||
   1067           (SpdData->ProcessingPolicy->Mode != EfiIPsecTunnel && SpdData->ProcessingPolicy->TunnelOption != NULL)
   1068           ) {
   1069         return EFI_INVALID_PARAMETER;
   1070       }
   1071     }
   1072   }
   1073   //
   1074   // The default behavior is to insert the node ahead of the header.
   1075   //
   1076   EntryInsertBefore = SpdList;
   1077 
   1078   //
   1079   // Remove the existed SPD entry.
   1080   //
   1081   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SpdList) {
   1082 
   1083     SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
   1084 
   1085     if (SpdSel == NULL ||
   1086         CompareSpdSelector ((EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector, (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel)
   1087         ) {
   1088       //
   1089       // Record the existed entry position to keep the original order.
   1090       //
   1091       EntryInsertBefore = SpdEntry->List.ForwardLink;
   1092       RemoveEntryList (&SpdEntry->List);
   1093 
   1094       //
   1095       // Update the reverse ref of SAD entry in the SPD.sas list.
   1096       //
   1097       SpdSas = &SpdEntry->Data->Sas;
   1098 
   1099       //
   1100       // TODO: Deleted the related SAs.
   1101       //
   1102       NET_LIST_FOR_EACH (Entry2, SpdSas) {
   1103         SadEntry                  = IPSEC_SAD_ENTRY_FROM_SPD (Entry2);
   1104         SadEntry->Data->SpdEntry  = NULL;
   1105       }
   1106 
   1107       //
   1108       // Free the existed SPD entry
   1109       //
   1110       FreePool (SpdEntry);
   1111     }
   1112   }
   1113   //
   1114   // Return success here if only want to remove the SPD entry.
   1115   //
   1116   if (SpdData == NULL || SpdSel == NULL) {
   1117     return EFI_SUCCESS;
   1118   }
   1119   //
   1120   // Search the appointed entry position if InsertBefore is not NULL.
   1121   //
   1122   if (InsertBefore != NULL) {
   1123 
   1124     NET_LIST_FOR_EACH (Entry, SpdList) {
   1125       SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
   1126 
   1127       if (CompareSpdSelector (
   1128             (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector,
   1129             (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore
   1130             )) {
   1131         EntryInsertBefore = Entry;
   1132         break;
   1133       }
   1134     }
   1135   }
   1136 
   1137   //
   1138   // Do Padding for the different Arch.
   1139   //
   1140   SpdEntrySize  = ALIGN_VARIABLE (sizeof (IPSEC_SPD_ENTRY));
   1141   SpdEntrySize  = ALIGN_VARIABLE (SpdEntrySize + (UINTN)SIZE_OF_SPD_SELECTOR (SpdSel));
   1142   SpdEntrySize += IpSecGetSizeOfEfiSpdData (SpdData);
   1143 
   1144   SpdEntry = AllocateZeroPool (SpdEntrySize);
   1145 
   1146   if (SpdEntry == NULL) {
   1147     return EFI_OUT_OF_RESOURCES;
   1148   }
   1149   //
   1150   // Fix the address of Selector and Data buffer and copy them, which is
   1151   // continous memory and close to the base structure of SPD entry.
   1152   //
   1153   SpdEntry->Selector  = (EFI_IPSEC_SPD_SELECTOR *) ALIGN_POINTER ((SpdEntry + 1), sizeof (UINTN));
   1154   SpdEntry->Data      = (IPSEC_SPD_DATA *) ALIGN_POINTER (
   1155                                             ((UINT8 *) SpdEntry->Selector + SIZE_OF_SPD_SELECTOR (SpdSel)),
   1156                                             sizeof (UINTN)
   1157                                             );
   1158 
   1159   DuplicateSpdSelector (
   1160     (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector,
   1161     (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel,
   1162     NULL
   1163     );
   1164 
   1165   CopyMem (
   1166     SpdEntry->Data->Name,
   1167     SpdData->Name,
   1168     sizeof (SpdData->Name)
   1169     );
   1170   SpdEntry->Data->PackageFlag      = SpdData->PackageFlag;
   1171   SpdEntry->Data->TrafficDirection = SpdData->TrafficDirection;
   1172   SpdEntry->Data->Action           = SpdData->Action;
   1173 
   1174   //
   1175   // Fix the address of ProcessingPolicy and copy it if need, which is continous
   1176   // memory and close to the base structure of SAD data.
   1177   //
   1178   if (SpdData->Action != EfiIPsecActionProtect) {
   1179     SpdEntry->Data->ProcessingPolicy = NULL;
   1180   } else {
   1181     SpdEntry->Data->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ALIGN_POINTER (
   1182                                                                       SpdEntry->Data + 1,
   1183                                                                       sizeof (UINTN)
   1184                                                                       );
   1185     IpSecDuplicateProcessPolicy (SpdEntry->Data->ProcessingPolicy, SpdData->ProcessingPolicy);
   1186   }
   1187   //
   1188   // Update the sas list of the new SPD entry.
   1189   //
   1190   InitializeListHead (&SpdEntry->Data->Sas);
   1191 
   1192   SadList = &mConfigData[IPsecConfigDataTypeSad];
   1193 
   1194   NET_LIST_FOR_EACH (Entry, SadList) {
   1195     SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
   1196 
   1197     for (Index = 0; Index < SpdData->SaIdCount; Index++) {
   1198 
   1199       if (CompareSaId (
   1200             (EFI_IPSEC_CONFIG_SELECTOR *) &SpdData->SaId[Index],
   1201             (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id
   1202             )) {
   1203         if (SadEntry->Data->SpdEntry != NULL) {
   1204           RemoveEntryList (&SadEntry->BySpd);
   1205         }
   1206         InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd);
   1207         SadEntry->Data->SpdEntry = SpdEntry;
   1208       }
   1209     }
   1210   }
   1211   //
   1212   // Insert the new SPD entry.
   1213   //
   1214   InsertTailList (EntryInsertBefore, &SpdEntry->List);
   1215 
   1216   return EFI_SUCCESS;
   1217 }
   1218 
   1219 /**
   1220   Set the security association information for the EFI IPsec driver.
   1221 
   1222   The IPsec configuration data has a unique selector/identifier separately to
   1223   identify a data entry.
   1224 
   1225   @param[in]  Selector           Pointer to an entry selector on operated
   1226                                  configuration data specified by DataType.
   1227                                  A NULL Selector causes the entire specified-type
   1228                                  configuration information to be flushed.
   1229   @param[in]  Data               The data buffer to be set. The structure
   1230                                  of the data buffer should be EFI_IPSEC_SA_DATA.
   1231   @param[in]  Context            Pointer to one entry selector which describes
   1232                                  the expected position the new data entry will
   1233                                  be added. If Context is NULL,the new entry will
   1234                                  be appended the end of database.
   1235 
   1236   @retval EFI_OUT_OF_RESOURCED  The required system resource could not be allocated.
   1237   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1238 
   1239 **/
   1240 EFI_STATUS
   1241 SetSadEntry (
   1242   IN EFI_IPSEC_CONFIG_SELECTOR       *Selector,
   1243   IN VOID                            *Data,
   1244   IN VOID                            *Context OPTIONAL
   1245   )
   1246 {
   1247   IPSEC_SAD_ENTRY   *SadEntry;
   1248   IPSEC_SPD_ENTRY   *SpdEntry;
   1249   LIST_ENTRY        *Entry;
   1250   LIST_ENTRY        *NextEntry;
   1251   LIST_ENTRY        *SadList;
   1252   LIST_ENTRY        *SpdList;
   1253   EFI_IPSEC_SA_ID   *SaId;
   1254   EFI_IPSEC_SA_DATA2 *SaData;
   1255   EFI_IPSEC_SA_ID   *InsertBefore;
   1256   LIST_ENTRY        *EntryInsertBefore;
   1257   UINTN             SadEntrySize;
   1258 
   1259   SaId          = (Selector == NULL) ? NULL : &Selector->SaId;
   1260   SaData        = (Data == NULL) ? NULL : (EFI_IPSEC_SA_DATA2 *) Data;
   1261   InsertBefore  = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->SaId;
   1262   SadList       = &mConfigData[IPsecConfigDataTypeSad];
   1263 
   1264   //
   1265   // The default behavior is to insert the node ahead of the header.
   1266   //
   1267   EntryInsertBefore = SadList;
   1268 
   1269   //
   1270   // Remove the existed SAD entry.
   1271   //
   1272   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SadList) {
   1273 
   1274     SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
   1275 
   1276     if (SaId == NULL ||
   1277         CompareSaId (
   1278           (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id,
   1279           (EFI_IPSEC_CONFIG_SELECTOR *) SaId
   1280           )) {
   1281       //
   1282       // Record the existed entry position to keep the original order.
   1283       //
   1284       EntryInsertBefore = SadEntry->List.ForwardLink;
   1285 
   1286       //
   1287       // Update the related SAD.byspd field.
   1288       //
   1289       if (SadEntry->Data->SpdEntry != NULL) {
   1290         RemoveEntryList (&SadEntry->BySpd);
   1291       }
   1292 
   1293       RemoveEntryList (&SadEntry->List);
   1294       FreePool (SadEntry);
   1295     }
   1296   }
   1297   //
   1298   // Return success here if only want to remove the SAD entry
   1299   //
   1300   if (SaData == NULL || SaId == NULL) {
   1301     return EFI_SUCCESS;
   1302   }
   1303   //
   1304   // Search the appointed entry position if InsertBefore is not NULL.
   1305   //
   1306   if (InsertBefore != NULL) {
   1307 
   1308     NET_LIST_FOR_EACH (Entry, SadList) {
   1309       SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
   1310 
   1311       if (CompareSaId (
   1312            (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id,
   1313            (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore
   1314            )) {
   1315         EntryInsertBefore = Entry;
   1316         break;
   1317       }
   1318     }
   1319   }
   1320 
   1321   //
   1322   // Do Padding for different Arch.
   1323   //
   1324   SadEntrySize  = ALIGN_VARIABLE (sizeof (IPSEC_SAD_ENTRY));
   1325   SadEntrySize  = ALIGN_VARIABLE (SadEntrySize + sizeof (EFI_IPSEC_SA_ID));
   1326   SadEntrySize  = ALIGN_VARIABLE (SadEntrySize + sizeof (IPSEC_SAD_DATA));
   1327 
   1328   if (SaId->Proto == EfiIPsecAH) {
   1329     SadEntrySize += SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength;
   1330   } else {
   1331     SadEntrySize  = ALIGN_VARIABLE (SadEntrySize + SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength);
   1332     SadEntrySize += ALIGN_VARIABLE (SaData->AlgoInfo.EspAlgoInfo.EncKeyLength);
   1333   }
   1334 
   1335   if (SaData->SpdSelector != NULL) {
   1336     SadEntrySize += SadEntrySize + (UINTN)SIZE_OF_SPD_SELECTOR (SaData->SpdSelector);
   1337   }
   1338   SadEntry      = AllocateZeroPool (SadEntrySize);
   1339 
   1340   if (SadEntry == NULL) {
   1341     return EFI_OUT_OF_RESOURCES;
   1342   }
   1343   //
   1344   // Fix the address of Id and Data buffer and copy them, which is
   1345   // continous memory and close to the base structure of SAD entry.
   1346   //
   1347   SadEntry->Id    = (EFI_IPSEC_SA_ID *) ALIGN_POINTER ((SadEntry + 1), sizeof (UINTN));
   1348   SadEntry->Data  = (IPSEC_SAD_DATA *) ALIGN_POINTER ((SadEntry->Id + 1), sizeof (UINTN));
   1349 
   1350   CopyMem (SadEntry->Id, SaId, sizeof (EFI_IPSEC_SA_ID));
   1351 
   1352   SadEntry->Data->Mode                  = SaData->Mode;
   1353   SadEntry->Data->SequenceNumber        = SaData->SNCount;
   1354   SadEntry->Data->AntiReplayWindowSize  = SaData->AntiReplayWindows;
   1355 
   1356   ZeroMem (
   1357     &SadEntry->Data->AntiReplayBitmap,
   1358     sizeof (SadEntry->Data->AntiReplayBitmap)
   1359     );
   1360 
   1361   ZeroMem (
   1362     &SadEntry->Data->AlgoInfo,
   1363     sizeof (EFI_IPSEC_ALGO_INFO)
   1364     );
   1365 
   1366   SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId     = SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId;
   1367   SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength  = SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength;
   1368 
   1369   if (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) {
   1370     SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SadEntry->Data + 1), sizeof (UINTN));
   1371     CopyMem (
   1372       SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
   1373       SaData->AlgoInfo.EspAlgoInfo.AuthKey,
   1374       SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength
   1375       );
   1376   }
   1377 
   1378   if (SaId->Proto == EfiIPsecESP) {
   1379     SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId    = SaData->AlgoInfo.EspAlgoInfo.EncAlgoId;
   1380     SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength = SaData->AlgoInfo.EspAlgoInfo.EncKeyLength;
   1381 
   1382     if (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) {
   1383       SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER (
   1384                                                                ((UINT8 *) (SadEntry->Data + 1) +
   1385                                                                  SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength),
   1386                                                                  sizeof (UINTN)
   1387                                                                  );
   1388       CopyMem (
   1389         SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,
   1390         SaData->AlgoInfo.EspAlgoInfo.EncKey,
   1391         SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength
   1392         );
   1393     }
   1394   }
   1395 
   1396   CopyMem (
   1397     &SadEntry->Data->SaLifetime,
   1398     &SaData->SaLifetime,
   1399     sizeof (EFI_IPSEC_SA_LIFETIME)
   1400     );
   1401 
   1402   SadEntry->Data->PathMTU     = SaData->PathMTU;
   1403   SadEntry->Data->SpdSelector = NULL;
   1404   SadEntry->Data->ESNEnabled  = FALSE;
   1405   SadEntry->Data->ManualSet   = SaData->ManualSet;
   1406 
   1407   //
   1408   // Copy Tunnel Source/Destination Address
   1409   //
   1410   if (SaData->Mode == EfiIPsecTunnel) {
   1411     CopyMem (
   1412       &SadEntry->Data->TunnelDestAddress,
   1413       &SaData->TunnelDestinationAddress,
   1414       sizeof (EFI_IP_ADDRESS)
   1415       );
   1416     CopyMem (
   1417       &SadEntry->Data->TunnelSourceAddress,
   1418       &SaData->TunnelSourceAddress,
   1419       sizeof (EFI_IP_ADDRESS)
   1420       );
   1421   }
   1422   //
   1423   // Update the spd.sas list of the spd entry specified by SAD selector
   1424   //
   1425   SpdList = &mConfigData[IPsecConfigDataTypeSpd];
   1426 
   1427   for (Entry = SpdList->ForwardLink; Entry != SpdList && SaData->SpdSelector != NULL; Entry = Entry->ForwardLink) {
   1428 
   1429     SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
   1430     if (IsSubSpdSelector (
   1431           (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
   1432           (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
   1433           ) && SpdEntry->Data->Action == EfiIPsecActionProtect) {
   1434       SadEntry->Data->SpdEntry = SpdEntry;
   1435       SadEntry->Data->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *)((UINT8 *)SadEntry +
   1436                                                                 SadEntrySize -
   1437                                                                 (UINTN)SIZE_OF_SPD_SELECTOR (SaData->SpdSelector)
   1438                                                                 );
   1439       DuplicateSpdSelector (
   1440        (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector,
   1441        (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
   1442        NULL
   1443        );
   1444       InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd);
   1445     }
   1446   }
   1447   //
   1448   // Insert the new SAD entry.
   1449   //
   1450   InsertTailList (EntryInsertBefore, &SadEntry->List);
   1451 
   1452   return EFI_SUCCESS;
   1453 }
   1454 
   1455 /**
   1456   Set the peer authorization configuration information for the EFI IPsec driver.
   1457 
   1458   The IPsec configuration data has a unique selector/identifier separately to
   1459   identify a data entry.
   1460 
   1461   @param[in]  Selector           Pointer to an entry selector on operated
   1462                                  configuration data specified by DataType.
   1463                                  A NULL Selector causes the entire specified-type
   1464                                  configuration information to be flushed.
   1465   @param[in]  Data               The data buffer to be set. The structure
   1466                                  of the data buffer should be EFI_IPSEC_PAD_DATA.
   1467   @param[in]  Context            Pointer to one entry selector that describes
   1468                                  the expected position the new data entry will
   1469                                  be added. If Context is NULL, the new entry will
   1470                                  be appended the end of database.
   1471 
   1472   @retval EFI_OUT_OF_RESOURCES  The required system resources could not be allocated.
   1473   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1474 
   1475 **/
   1476 EFI_STATUS
   1477 SetPadEntry (
   1478   IN EFI_IPSEC_CONFIG_SELECTOR       *Selector,
   1479   IN VOID                            *Data,
   1480   IN VOID                            *Context OPTIONAL
   1481   )
   1482 {
   1483   IPSEC_PAD_ENTRY     *PadEntry;
   1484   EFI_IPSEC_PAD_ID    *PadId;
   1485   EFI_IPSEC_PAD_DATA  *PadData;
   1486   LIST_ENTRY          *PadList;
   1487   LIST_ENTRY          *Entry;
   1488   LIST_ENTRY          *NextEntry;
   1489   EFI_IPSEC_PAD_ID    *InsertBefore;
   1490   LIST_ENTRY          *EntryInsertBefore;
   1491   UINTN               PadEntrySize;
   1492 
   1493   PadId         = (Selector == NULL) ? NULL : &Selector->PadId;
   1494   PadData       = (Data == NULL) ? NULL : (EFI_IPSEC_PAD_DATA *) Data;
   1495   InsertBefore  = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->PadId;
   1496   PadList       = &mConfigData[IPsecConfigDataTypePad];
   1497 
   1498   //
   1499   // The default behavior is to insert the node ahead of the header.
   1500   //
   1501   EntryInsertBefore = PadList;
   1502 
   1503   //
   1504   // Remove the existed pad entry.
   1505   //
   1506   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, PadList) {
   1507 
   1508     PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
   1509 
   1510     if (PadId == NULL ||
   1511         ComparePadId ((EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id, (EFI_IPSEC_CONFIG_SELECTOR *) PadId)
   1512         ) {
   1513       //
   1514       // Record the existed entry position to keep the original order.
   1515       //
   1516       EntryInsertBefore = PadEntry->List.ForwardLink;
   1517       RemoveEntryList (&PadEntry->List);
   1518 
   1519       FreePool (PadEntry);
   1520     }
   1521   }
   1522   //
   1523   // Return success here if only want to remove the pad entry
   1524   //
   1525   if (PadData == NULL || PadId == NULL) {
   1526     return EFI_SUCCESS;
   1527   }
   1528   //
   1529   // Search the appointed entry position if InsertBefore is not NULL.
   1530   //
   1531   if (InsertBefore != NULL) {
   1532 
   1533     NET_LIST_FOR_EACH (Entry, PadList) {
   1534       PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
   1535 
   1536       if (ComparePadId (
   1537             (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id,
   1538             (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore
   1539             )) {
   1540         EntryInsertBefore = Entry;
   1541         break;
   1542       }
   1543     }
   1544   }
   1545 
   1546   //
   1547   // Do PADDING for different arch.
   1548   //
   1549   PadEntrySize  = ALIGN_VARIABLE (sizeof (IPSEC_PAD_ENTRY));
   1550   PadEntrySize  = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_ID));
   1551   PadEntrySize  = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_DATA));
   1552   PadEntrySize  = ALIGN_VARIABLE (PadEntrySize + (PadData->AuthData != NULL ? PadData->AuthDataSize : 0));
   1553   PadEntrySize += PadData->RevocationData != NULL ? PadData->RevocationDataSize : 0;
   1554 
   1555   PadEntry      = AllocateZeroPool (PadEntrySize);
   1556 
   1557   if (PadEntry == NULL) {
   1558     return EFI_OUT_OF_RESOURCES;
   1559   }
   1560   //
   1561   // Fix the address of Id and Data buffer and copy them, which is
   1562   // continous memory and close to the base structure of pad entry.
   1563   //
   1564   PadEntry->Id    = (EFI_IPSEC_PAD_ID *) ALIGN_POINTER ((PadEntry + 1), sizeof (UINTN));
   1565   PadEntry->Data  = (EFI_IPSEC_PAD_DATA *) ALIGN_POINTER ((PadEntry->Id + 1), sizeof (UINTN));
   1566 
   1567   CopyMem (PadEntry->Id, PadId, sizeof (EFI_IPSEC_PAD_ID));
   1568 
   1569   PadEntry->Data->AuthProtocol  = PadData->AuthProtocol;
   1570   PadEntry->Data->AuthMethod    = PadData->AuthMethod;
   1571   PadEntry->Data->IkeIdFlag     = PadData->IkeIdFlag;
   1572 
   1573   if (PadData->AuthData != NULL) {
   1574     PadEntry->Data->AuthDataSize  = PadData->AuthDataSize;
   1575     PadEntry->Data->AuthData      = (VOID *) ALIGN_POINTER (PadEntry->Data + 1, sizeof (UINTN));
   1576     CopyMem (
   1577       PadEntry->Data->AuthData,
   1578       PadData->AuthData,
   1579       PadData->AuthDataSize
   1580       );
   1581   } else {
   1582     PadEntry->Data->AuthDataSize  = 0;
   1583     PadEntry->Data->AuthData      = NULL;
   1584   }
   1585 
   1586   if (PadData->RevocationData != NULL) {
   1587     PadEntry->Data->RevocationDataSize  = PadData->RevocationDataSize;
   1588     PadEntry->Data->RevocationData      = (VOID *) ALIGN_POINTER (
   1589                                                     ((UINT8 *) (PadEntry->Data + 1) + PadData->AuthDataSize),
   1590                                                     sizeof (UINTN)
   1591                                                     );
   1592     CopyMem (
   1593       PadEntry->Data->RevocationData,
   1594       PadData->RevocationData,
   1595       PadData->RevocationDataSize
   1596       );
   1597   } else {
   1598     PadEntry->Data->RevocationDataSize  = 0;
   1599     PadEntry->Data->RevocationData      = NULL;
   1600   }
   1601   //
   1602   // Insert the new pad entry.
   1603   //
   1604   InsertTailList (EntryInsertBefore, &PadEntry->List);
   1605 
   1606   return EFI_SUCCESS;
   1607 }
   1608 
   1609 /**
   1610   This function lookup the data entry from IPsec SPD. Return the configuration
   1611   value of the specified SPD Entry.
   1612 
   1613   @param[in]      Selector      Pointer to an entry selector which is an identifier
   1614                                 of the SPD entry.
   1615   @param[in, out] DataSize      On output the size of data returned in Data.
   1616   @param[out]     Data          The buffer to return the contents of the IPsec
   1617                                 configuration data. The type of the data buffer
   1618                                 is associated with the DataType.
   1619 
   1620   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1621   @retval EFI_INVALID_PARAMETER Data is NULL and *DataSize is not zero.
   1622   @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
   1623   @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
   1624                                 updated with the size needed to complete the request.
   1625 
   1626 **/
   1627 EFI_STATUS
   1628 GetSpdEntry (
   1629   IN     EFI_IPSEC_CONFIG_SELECTOR       *Selector,
   1630   IN OUT UINTN                           *DataSize,
   1631      OUT VOID                            *Data
   1632   )
   1633 {
   1634   IPSEC_SPD_ENTRY         *SpdEntry;
   1635   IPSEC_SAD_ENTRY         *SadEntry;
   1636   EFI_IPSEC_SPD_SELECTOR  *SpdSel;
   1637   EFI_IPSEC_SPD_DATA      *SpdData;
   1638   LIST_ENTRY              *SpdList;
   1639   LIST_ENTRY              *SpdSas;
   1640   LIST_ENTRY              *Entry;
   1641   UINTN                   RequiredSize;
   1642 
   1643   SpdSel  = &Selector->SpdSelector;
   1644   SpdData = (EFI_IPSEC_SPD_DATA *) Data;
   1645   SpdList = &mConfigData[IPsecConfigDataTypeSpd];
   1646 
   1647   NET_LIST_FOR_EACH (Entry, SpdList) {
   1648     SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
   1649 
   1650     //
   1651     // Find the required SPD entry
   1652     //
   1653     if (CompareSpdSelector (
   1654           (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel,
   1655           (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
   1656           )) {
   1657 
   1658       RequiredSize = IpSecGetSizeOfSpdData (SpdEntry->Data);
   1659       if (*DataSize < RequiredSize) {
   1660         *DataSize = RequiredSize;
   1661         return EFI_BUFFER_TOO_SMALL;
   1662       }
   1663 
   1664       if (SpdData == NULL) {
   1665         return EFI_INVALID_PARAMETER;
   1666       }
   1667 
   1668       *DataSize = RequiredSize;
   1669 
   1670       //
   1671       // Extract and fill all SaId array from the SPD.sas list
   1672       //
   1673       SpdSas              = &SpdEntry->Data->Sas;
   1674       SpdData->SaIdCount  = 0;
   1675 
   1676       NET_LIST_FOR_EACH (Entry, SpdSas) {
   1677         SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry);
   1678         CopyMem (
   1679           &SpdData->SaId[SpdData->SaIdCount++],
   1680           SadEntry->Id,
   1681           sizeof (EFI_IPSEC_SA_ID)
   1682           );
   1683       }
   1684       //
   1685       // Fill the other fields in SPD data.
   1686       //
   1687       CopyMem (SpdData->Name, SpdEntry->Data->Name, sizeof (SpdData->Name));
   1688 
   1689       SpdData->PackageFlag      = SpdEntry->Data->PackageFlag;
   1690       SpdData->TrafficDirection = SpdEntry->Data->TrafficDirection;
   1691       SpdData->Action           = SpdEntry->Data->Action;
   1692 
   1693       if (SpdData->Action != EfiIPsecActionProtect) {
   1694         SpdData->ProcessingPolicy = NULL;
   1695       } else {
   1696         SpdData->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ((UINT8 *) SpdData + sizeof (EFI_IPSEC_SPD_DATA) + (SpdData->SaIdCount - 1) * sizeof (EFI_IPSEC_SA_ID));
   1697 
   1698         IpSecDuplicateProcessPolicy (
   1699           SpdData->ProcessingPolicy,
   1700           SpdEntry->Data->ProcessingPolicy
   1701           );
   1702       }
   1703 
   1704       return EFI_SUCCESS;
   1705     }
   1706   }
   1707 
   1708   return EFI_NOT_FOUND;
   1709 }
   1710 
   1711 /**
   1712   This function lookup the data entry from IPsec SAD. Return the configuration
   1713   value of the specified SAD Entry.
   1714 
   1715   @param[in]      Selector      Pointer to an entry selector which is an identifier
   1716                                 of the SAD entry.
   1717   @param[in, out] DataSize      On output, the size of data returned in Data.
   1718   @param[out]     Data          The buffer to return the contents of the IPsec
   1719                                 configuration data. The type of the data buffer
   1720                                 is associated with the DataType.
   1721 
   1722   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1723   @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
   1724   @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
   1725                                 updated with the size needed to complete the request.
   1726 
   1727 **/
   1728 EFI_STATUS
   1729 GetSadEntry (
   1730   IN     EFI_IPSEC_CONFIG_SELECTOR     *Selector,
   1731   IN OUT UINTN                         *DataSize,
   1732      OUT VOID                          *Data
   1733   )
   1734 {
   1735   IPSEC_SAD_ENTRY   *SadEntry;
   1736   LIST_ENTRY        *Entry;
   1737   LIST_ENTRY        *SadList;
   1738   EFI_IPSEC_SA_ID   *SaId;
   1739   EFI_IPSEC_SA_DATA2 *SaData;
   1740   UINTN             RequiredSize;
   1741 
   1742   SaId    = &Selector->SaId;
   1743   SaData  = (EFI_IPSEC_SA_DATA2 *) Data;
   1744   SadList = &mConfigData[IPsecConfigDataTypeSad];
   1745 
   1746   NET_LIST_FOR_EACH (Entry, SadList) {
   1747     SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
   1748 
   1749     //
   1750     // Find the required SAD entry.
   1751     //
   1752     if (CompareSaId (
   1753          (EFI_IPSEC_CONFIG_SELECTOR *) SaId,
   1754          (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id
   1755          )) {
   1756       //
   1757       // Calculate the required size of the SAD entry.
   1758       // Data Layout is follows:
   1759       // |EFI_IPSEC_SA_DATA
   1760       // |AuthKey
   1761       // |EncryptKey  (Optional)
   1762       // |SpdSelector (Optional)
   1763       //
   1764       RequiredSize  = ALIGN_VARIABLE (sizeof (EFI_IPSEC_SA_DATA2));
   1765 
   1766       if (SaId->Proto == EfiIPsecAH) {
   1767         RequiredSize  = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength);
   1768       } else {
   1769         RequiredSize  = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength);
   1770         RequiredSize  = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength);
   1771       }
   1772 
   1773       if (SadEntry->Data->SpdSelector != NULL) {
   1774         RequiredSize += SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdSelector);
   1775       }
   1776 
   1777       if (*DataSize < RequiredSize) {
   1778         *DataSize = RequiredSize;
   1779         return EFI_BUFFER_TOO_SMALL;
   1780       }
   1781 
   1782       //
   1783       // Fill the data fields of SAD entry.
   1784       //
   1785       *DataSize                 = RequiredSize;
   1786       SaData->Mode              = SadEntry->Data->Mode;
   1787       SaData->SNCount           = SadEntry->Data->SequenceNumber;
   1788       SaData->AntiReplayWindows = SadEntry->Data->AntiReplayWindowSize;
   1789 
   1790       CopyMem (
   1791         &SaData->SaLifetime,
   1792         &SadEntry->Data->SaLifetime,
   1793         sizeof (EFI_IPSEC_SA_LIFETIME)
   1794         );
   1795 
   1796       ZeroMem (
   1797         &SaData->AlgoInfo,
   1798         sizeof (EFI_IPSEC_ALGO_INFO)
   1799         );
   1800 
   1801       if (SaId->Proto == EfiIPsecAH) {
   1802         //
   1803         // Copy AH alogrithm INFO to SaData
   1804         //
   1805         SaData->AlgoInfo.AhAlgoInfo.AuthAlgoId    = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthAlgoId;
   1806         SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength;
   1807         if (SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength != 0) {
   1808           SaData->AlgoInfo.AhAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN));
   1809           CopyMem (
   1810             SaData->AlgoInfo.AhAlgoInfo.AuthKey,
   1811             SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKey,
   1812             SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength
   1813             );
   1814         }
   1815       } else if (SaId->Proto == EfiIPsecESP) {
   1816         //
   1817         // Copy ESP alogrithem INFO to SaData
   1818         //
   1819         SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId     = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId;
   1820         SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength  = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength;
   1821         if (SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) {
   1822           SaData->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN));
   1823           CopyMem (
   1824             SaData->AlgoInfo.EspAlgoInfo.AuthKey,
   1825             SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
   1826             SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength
   1827             );
   1828         }
   1829 
   1830         SaData->AlgoInfo.EspAlgoInfo.EncAlgoId    = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId;
   1831         SaData->AlgoInfo.EspAlgoInfo.EncKeyLength = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength;
   1832 
   1833         if (SaData->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) {
   1834           SaData->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER (
   1835                                                           ((UINT8 *) (SaData + 1) +
   1836                                                             SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength),
   1837                                                             sizeof (UINTN)
   1838                                                             );
   1839           CopyMem (
   1840             SaData->AlgoInfo.EspAlgoInfo.EncKey,
   1841             SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,
   1842             SaData->AlgoInfo.EspAlgoInfo.EncKeyLength
   1843             );
   1844         }
   1845       }
   1846 
   1847       SaData->PathMTU = SadEntry->Data->PathMTU;
   1848 
   1849       //
   1850       // Fill Tunnel Address if it is Tunnel Mode
   1851       //
   1852       if (SadEntry->Data->Mode == EfiIPsecTunnel) {
   1853         CopyMem (
   1854           &SaData->TunnelDestinationAddress,
   1855           &SadEntry->Data->TunnelDestAddress,
   1856           sizeof (EFI_IP_ADDRESS)
   1857           );
   1858         CopyMem (
   1859           &SaData->TunnelSourceAddress,
   1860           &SadEntry->Data->TunnelSourceAddress,
   1861           sizeof (EFI_IP_ADDRESS)
   1862           );
   1863       }
   1864       //
   1865       // Fill the spd selector field of SAD data
   1866       //
   1867       if (SadEntry->Data->SpdSelector != NULL) {
   1868 
   1869         SaData->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *) (
   1870                                 (UINT8 *)SaData +
   1871                                 RequiredSize -
   1872                                 SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdSelector)
   1873                                 );
   1874 
   1875         DuplicateSpdSelector (
   1876           (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
   1877           (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector,
   1878           NULL
   1879           );
   1880 
   1881       } else {
   1882 
   1883         SaData->SpdSelector = NULL;
   1884       }
   1885 
   1886       SaData->ManualSet = SadEntry->Data->ManualSet;
   1887 
   1888       return EFI_SUCCESS;
   1889     }
   1890   }
   1891 
   1892   return EFI_NOT_FOUND;
   1893 }
   1894 
   1895 /**
   1896   This function lookup the data entry from IPsec PAD. Return the configuration
   1897   value of the specified PAD Entry.
   1898 
   1899   @param[in]      Selector      Pointer to an entry selector which is an identifier
   1900                                 of the PAD entry.
   1901   @param[in, out] DataSize      On output the size of data returned in Data.
   1902   @param[out]     Data          The buffer to return the contents of the IPsec
   1903                                 configuration data. The type of the data buffer
   1904                                 is associated with the DataType.
   1905 
   1906   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1907   @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
   1908   @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
   1909                                 updated with the size needed to complete the request.
   1910 
   1911 **/
   1912 EFI_STATUS
   1913 GetPadEntry (
   1914   IN     EFI_IPSEC_CONFIG_SELECTOR   *Selector,
   1915   IN OUT UINTN                       *DataSize,
   1916      OUT VOID                        *Data
   1917   )
   1918 {
   1919   IPSEC_PAD_ENTRY     *PadEntry;
   1920   LIST_ENTRY          *PadList;
   1921   LIST_ENTRY          *Entry;
   1922   EFI_IPSEC_PAD_ID    *PadId;
   1923   EFI_IPSEC_PAD_DATA  *PadData;
   1924   UINTN               RequiredSize;
   1925 
   1926   PadId   = &Selector->PadId;
   1927   PadData = (EFI_IPSEC_PAD_DATA *) Data;
   1928   PadList = &mConfigData[IPsecConfigDataTypePad];
   1929 
   1930   NET_LIST_FOR_EACH (Entry, PadList) {
   1931     PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
   1932 
   1933     //
   1934     // Find the required pad entry.
   1935     //
   1936     if (ComparePadId (
   1937           (EFI_IPSEC_CONFIG_SELECTOR *) PadId,
   1938           (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id
   1939           )) {
   1940       //
   1941       // Calculate the required size of the pad entry.
   1942       //
   1943       RequiredSize  = ALIGN_VARIABLE (sizeof (EFI_IPSEC_PAD_DATA));
   1944       RequiredSize  = ALIGN_VARIABLE (RequiredSize + PadEntry->Data->AuthDataSize);
   1945       RequiredSize += PadEntry->Data->RevocationDataSize;
   1946 
   1947       if (*DataSize < RequiredSize) {
   1948         *DataSize = RequiredSize;
   1949         return EFI_BUFFER_TOO_SMALL;
   1950       }
   1951       //
   1952       // Fill the data fields of pad entry
   1953       //
   1954       *DataSize             = RequiredSize;
   1955       PadData->AuthProtocol = PadEntry->Data->AuthProtocol;
   1956       PadData->AuthMethod   = PadEntry->Data->AuthMethod;
   1957       PadData->IkeIdFlag    = PadEntry->Data->IkeIdFlag;
   1958 
   1959       //
   1960       // Copy Authentication data.
   1961       //
   1962       if (PadEntry->Data->AuthData != NULL) {
   1963 
   1964         PadData->AuthDataSize = PadEntry->Data->AuthDataSize;
   1965         PadData->AuthData     = (VOID *) ALIGN_POINTER ((PadData + 1), sizeof (UINTN));
   1966         CopyMem (
   1967           PadData->AuthData,
   1968           PadEntry->Data->AuthData,
   1969           PadData->AuthDataSize
   1970           );
   1971       } else {
   1972 
   1973         PadData->AuthDataSize = 0;
   1974         PadData->AuthData     = NULL;
   1975       }
   1976       //
   1977       // Copy Revocation Data.
   1978       //
   1979       if (PadEntry->Data->RevocationData != NULL) {
   1980 
   1981         PadData->RevocationDataSize = PadEntry->Data->RevocationDataSize;
   1982         PadData->RevocationData     = (VOID *) ALIGN_POINTER (
   1983                                                  ((UINT8 *) (PadData + 1) + PadData->AuthDataSize),
   1984                                                   sizeof (UINTN)
   1985                                                   );
   1986         CopyMem (
   1987           PadData->RevocationData,
   1988           PadEntry->Data->RevocationData,
   1989           PadData->RevocationDataSize
   1990           );
   1991       } else {
   1992 
   1993         PadData->RevocationDataSize = 0;
   1994         PadData->RevocationData     = NULL;
   1995       }
   1996 
   1997       return EFI_SUCCESS;
   1998     }
   1999   }
   2000 
   2001   return EFI_NOT_FOUND;
   2002 }
   2003 
   2004 /**
   2005   Copy Source Process Policy to the Destination Process Policy.
   2006 
   2007   @param[in]  Dst                  Pointer to the Source Process Policy.
   2008   @param[in]  Src                  Pointer to the Destination Process Policy.
   2009 
   2010 **/
   2011 VOID
   2012 IpSecDuplicateProcessPolicy (
   2013   IN EFI_IPSEC_PROCESS_POLICY            *Dst,
   2014   IN EFI_IPSEC_PROCESS_POLICY            *Src
   2015   )
   2016 {
   2017   //
   2018   // Firstly copy the structure content itself.
   2019   //
   2020   CopyMem (Dst, Src, sizeof (EFI_IPSEC_PROCESS_POLICY));
   2021 
   2022   //
   2023   // Recursively copy the tunnel option if needed.
   2024   //
   2025   if (Dst->Mode != EfiIPsecTunnel) {
   2026     ASSERT (Dst->TunnelOption == NULL);
   2027   } else {
   2028     Dst->TunnelOption = (EFI_IPSEC_TUNNEL_OPTION *) ALIGN_POINTER ((Dst + 1), sizeof (UINTN));
   2029     CopyMem (
   2030       Dst->TunnelOption,
   2031       Src->TunnelOption,
   2032       sizeof (EFI_IPSEC_TUNNEL_OPTION)
   2033       );
   2034   }
   2035 }
   2036 
   2037 /**
   2038   Calculate the a whole size of EFI_IPSEC_SPD_DATA, which includes the buffer size pointed
   2039   to by the pointer members.
   2040 
   2041   @param[in]  SpdData             Pointer to a specified EFI_IPSEC_SPD_DATA.
   2042 
   2043   @return the whole size the specified EFI_IPSEC_SPD_DATA.
   2044 
   2045 **/
   2046 UINTN
   2047 IpSecGetSizeOfEfiSpdData (
   2048   IN EFI_IPSEC_SPD_DATA               *SpdData
   2049   )
   2050 {
   2051   UINTN Size;
   2052 
   2053   Size = ALIGN_VARIABLE (sizeof (IPSEC_SPD_DATA));
   2054 
   2055   if (SpdData->Action == EfiIPsecActionProtect) {
   2056     Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_PROCESS_POLICY));
   2057 
   2058     if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) {
   2059       Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_TUNNEL_OPTION));
   2060     }
   2061   }
   2062 
   2063   return Size;
   2064 }
   2065 
   2066 /**
   2067   Calculate the a whole size of IPSEC_SPD_DATA which includes the buffer size pointed
   2068   to by the pointer members and the buffer size used by the Sa List.
   2069 
   2070   @param[in]  SpdData       Pointer to the specified IPSEC_SPD_DATA.
   2071 
   2072   @return the whole size of IPSEC_SPD_DATA.
   2073 
   2074 **/
   2075 UINTN
   2076 IpSecGetSizeOfSpdData (
   2077   IN IPSEC_SPD_DATA                   *SpdData
   2078   )
   2079 {
   2080   UINTN       Size;
   2081   LIST_ENTRY  *Link;
   2082 
   2083   Size = sizeof (EFI_IPSEC_SPD_DATA) - sizeof (EFI_IPSEC_SA_ID);
   2084 
   2085   if (SpdData->Action == EfiIPsecActionProtect) {
   2086     Size += sizeof (EFI_IPSEC_PROCESS_POLICY);
   2087 
   2088     if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) {
   2089       Size += sizeof (EFI_IPSEC_TUNNEL_OPTION);
   2090     }
   2091   }
   2092 
   2093   NET_LIST_FOR_EACH (Link, &SpdData->Sas) {
   2094     Size += sizeof (EFI_IPSEC_SA_ID);
   2095   }
   2096 
   2097   return Size;
   2098 }
   2099 
   2100 /**
   2101   Get the IPsec Variable.
   2102 
   2103   Get the all variables which start with the string contained in VaraiableName.
   2104   Since all IPsec related variable store in continual space, those kinds of
   2105   variable can be searched by the EfiGetNextVariableName. Those variables also are
   2106   returned in a continual buffer.
   2107 
   2108   @param[in]      VariableName          Pointer to a specified Variable Name.
   2109   @param[in]      VendorGuid            Pointer to a specified Vendor Guid.
   2110   @param[in]      Attributes            Point to memory location to return the attributes
   2111                                         of variable. If the point is NULL, the parameter
   2112                                         would be ignored.
   2113   @param[in, out] DataSize              As input, point to the maximum size of return
   2114                                         Data-Buffer. As output, point to the actual
   2115                                         size of the returned Data-Buffer.
   2116   @param[in]      Data                  Point to return Data-Buffer.
   2117 
   2118   @retval  EFI_ABORTED           If the Variable size which contained in the variable
   2119                                  structure doesn't match the variable size obtained
   2120                                  from the EFIGetVariable.
   2121   @retval  EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has
   2122                                  been updated with the size needed to complete the request.
   2123   @retval  EFI_SUCCESS           The function completed successfully.
   2124   @retval  others                Other errors found during the variable getting.
   2125 **/
   2126 EFI_STATUS
   2127 IpSecGetVariable (
   2128   IN     CHAR16                       *VariableName,
   2129   IN     EFI_GUID                     *VendorGuid,
   2130   IN     UINT32                       *Attributes, OPTIONAL
   2131   IN OUT UINTN                        *DataSize,
   2132   IN     VOID                         *Data
   2133   )
   2134 {
   2135   EFI_STATUS            Status;
   2136   EFI_GUID              VendorGuidI;
   2137   UINTN                 VariableNameLength;
   2138   CHAR16                *VariableNameI;
   2139   UINTN                 VariableNameISize;
   2140   UINTN                 VariableNameISizeNew;
   2141   UINTN                 VariableIndex;
   2142   UINTN                 VariableCount;
   2143   IP_SEC_VARIABLE_INFO  IpSecVariableInfo;
   2144   UINTN                 DataSizeI;
   2145 
   2146   //
   2147   // The variable name constructor is "VariableName + Info/0001/0002/... + NULL".
   2148   // So the varialbe name is like "VariableNameInfo", "VariableName0001", ...
   2149   // "VariableNameNULL".
   2150   //
   2151   VariableNameLength  = StrLen (VariableName);
   2152   VariableNameISize   = (VariableNameLength + 5) * sizeof (CHAR16);
   2153   VariableNameI       = AllocateZeroPool (VariableNameISize);
   2154   ASSERT (VariableNameI != NULL);
   2155 
   2156   //
   2157   // Construct the varible name of ipsecconfig meta data.
   2158   //
   2159   UnicodeSPrint (VariableNameI, VariableNameISize, L"%s%s", VariableName, L"Info");
   2160 
   2161   DataSizeI = sizeof (IpSecVariableInfo);
   2162 
   2163   Status = gRT->GetVariable (
   2164                   VariableNameI,
   2165                   VendorGuid,
   2166                   Attributes,
   2167                   &DataSizeI,
   2168                   &IpSecVariableInfo
   2169                   );
   2170   if (EFI_ERROR (Status)) {
   2171     goto ON_EXIT;
   2172   }
   2173 
   2174   if (*DataSize < IpSecVariableInfo.VariableSize) {
   2175     *DataSize = IpSecVariableInfo.VariableSize;
   2176     Status    = EFI_BUFFER_TOO_SMALL;
   2177     goto ON_EXIT;
   2178   }
   2179 
   2180   VariableCount     = IpSecVariableInfo.VariableCount;
   2181   VariableNameI[0]  = L'\0';
   2182 
   2183   while (VariableCount != 0) {
   2184     //
   2185     // Get the variable name one by one in the variable database.
   2186     //
   2187     VariableNameISizeNew = VariableNameISize;
   2188     Status = gRT->GetNextVariableName (
   2189                     &VariableNameISizeNew,
   2190                     VariableNameI,
   2191                     &VendorGuidI
   2192                     );
   2193     if (Status == EFI_BUFFER_TOO_SMALL) {
   2194       VariableNameI = ReallocatePool (
   2195                         VariableNameISize,
   2196                         VariableNameISizeNew,
   2197                         VariableNameI
   2198                         );
   2199       if (VariableNameI == NULL) {
   2200         Status = EFI_OUT_OF_RESOURCES;
   2201         break;
   2202       }
   2203       VariableNameISize = VariableNameISizeNew;
   2204 
   2205       Status = gRT->GetNextVariableName (
   2206                       &VariableNameISizeNew,
   2207                       VariableNameI,
   2208                       &VendorGuidI
   2209                       );
   2210     }
   2211 
   2212     if (EFI_ERROR (Status)) {
   2213       break;
   2214     }
   2215     //
   2216     // Check whether the current variable is the required "ipsecconfig".
   2217     //
   2218     if (StrnCmp (VariableNameI, VariableName, VariableNameLength) == 0 ||
   2219         CompareGuid (VendorGuid, &VendorGuidI)
   2220         ) {
   2221       //
   2222       // Parse the variable count of the current ipsecconfig data.
   2223       //
   2224       VariableIndex = StrDecimalToUintn (VariableNameI + VariableNameLength);
   2225       if (VariableIndex!= 0 && VariableIndex <= IpSecVariableInfo.VariableCount) {
   2226         //
   2227         // Get the variable size of the current ipsecconfig data.
   2228         //
   2229         DataSizeI = 0;
   2230         Status = gRT->GetVariable (
   2231                         VariableNameI,
   2232                         VendorGuid,
   2233                         Attributes,
   2234                         &DataSizeI,
   2235                         NULL
   2236                         );
   2237         ASSERT (Status == EFI_BUFFER_TOO_SMALL);
   2238         //
   2239         // Validate the variable count and variable size.
   2240         //
   2241         if (VariableIndex != IpSecVariableInfo.VariableCount) {
   2242           //
   2243           // If the varaibe is not the last one, its size should be the max
   2244           // size of the single variable.
   2245           //
   2246           if (DataSizeI != IpSecVariableInfo.SingleVariableSize) {
   2247             return EFI_ABORTED;
   2248           }
   2249         } else {
   2250           if (DataSizeI != IpSecVariableInfo.VariableSize % IpSecVariableInfo.SingleVariableSize) {
   2251             return EFI_ABORTED;
   2252           }
   2253         }
   2254         //
   2255         // Get the variable data of the current ipsecconfig data and
   2256         // store it into user buffer continously.
   2257         //
   2258         Status = gRT->GetVariable (
   2259                         VariableNameI,
   2260                         VendorGuid,
   2261                         Attributes,
   2262                         &DataSizeI,
   2263                         (UINT8 *) Data + (VariableIndex - 1) * IpSecVariableInfo.SingleVariableSize
   2264                         );
   2265         ASSERT_EFI_ERROR (Status);
   2266         VariableCount--;
   2267       }
   2268     }
   2269   }
   2270   //
   2271   // The VariableCount in "VariableNameInfo" varaible should have the correct
   2272   // numbers of variables which name starts with VariableName.
   2273   //
   2274   if (VariableCount != 0) {
   2275     Status = EFI_ABORTED;
   2276   }
   2277 
   2278 ON_EXIT:
   2279   if (VariableNameI != NULL) {
   2280     FreePool (VariableNameI);
   2281   }
   2282   return Status;
   2283 }
   2284 
   2285 /**
   2286   Set the IPsec variables.
   2287 
   2288   Set all IPsec variables which start with the specified variable name. Those variables
   2289   are set one by one.
   2290 
   2291   @param[in]  VariableName  The name of the vendor's variable. It is a
   2292                             Null-Terminated Unicode String.
   2293   @param[in]  VendorGuid    Unify identifier for vendor.
   2294   @param[in]  Attributes    Point to memory location to return the attributes of
   2295                             variable. If the point is NULL, the parameter would be ignored.
   2296   @param[in]  DataSize      The size in bytes of Data-Buffer.
   2297   @param[in]  Data          Points to the content of the variable.
   2298 
   2299   @retval  EFI_SUCCESS      The firmware successfully stored the variable and its data, as
   2300                             defined by the Attributes.
   2301   @retval  others           Storing the variables failed.
   2302 
   2303 **/
   2304 EFI_STATUS
   2305 IpSecSetVariable (
   2306   IN CHAR16                           *VariableName,
   2307   IN EFI_GUID                         *VendorGuid,
   2308   IN UINT32                           Attributes,
   2309   IN UINTN                            DataSize,
   2310   IN VOID                             *Data
   2311   )
   2312 {
   2313   EFI_STATUS            Status;
   2314   CHAR16                *VariableNameI;
   2315   UINTN                 VariableNameSize;
   2316   UINTN                 VariableIndex;
   2317   IP_SEC_VARIABLE_INFO  IpSecVariableInfo;
   2318   UINT64                MaximumVariableStorageSize;
   2319   UINT64                RemainingVariableStorageSize;
   2320   UINT64                MaximumVariableSize;
   2321 
   2322   Status = gRT->QueryVariableInfo (
   2323                   Attributes,
   2324                   &MaximumVariableStorageSize,
   2325                   &RemainingVariableStorageSize,
   2326                   &MaximumVariableSize
   2327                   );
   2328   if (EFI_ERROR (Status)) {
   2329     return Status;
   2330   }
   2331 
   2332   //
   2333   // "VariableName + Info/0001/0002/... + NULL"
   2334   //
   2335   VariableNameSize  = (StrLen (VariableName) + 5) * sizeof (CHAR16);
   2336   VariableNameI     = AllocateZeroPool (VariableNameSize);
   2337 
   2338   if (VariableNameI == NULL) {
   2339     Status = EFI_OUT_OF_RESOURCES;
   2340     goto ON_EXIT;
   2341   }
   2342   //
   2343   // Construct the variable of ipsecconfig general information. Like the total
   2344   // numbers of the Ipsecconfig variables, the total size of all ipsecconfig variables.
   2345   //
   2346   UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%s", VariableName, L"Info");
   2347   MaximumVariableSize -= VariableNameSize;
   2348 
   2349   IpSecVariableInfo.VariableCount       = (UINT32) ((DataSize + (UINTN) MaximumVariableSize - 1) / (UINTN) MaximumVariableSize);
   2350   IpSecVariableInfo.VariableSize        = (UINT32) DataSize;
   2351   IpSecVariableInfo.SingleVariableSize  = (UINT32) MaximumVariableSize;
   2352 
   2353   //
   2354   // Set the variable of ipsecconfig general information.
   2355   //
   2356   Status = gRT->SetVariable (
   2357                   VariableNameI,
   2358                   VendorGuid,
   2359                   Attributes,
   2360                   sizeof (IpSecVariableInfo),
   2361                   &IpSecVariableInfo
   2362                   );
   2363   if (EFI_ERROR (Status)) {
   2364     DEBUG ((DEBUG_ERROR, "Error set ipsecconfig meta data with %r\n", Status));
   2365     goto ON_EXIT;
   2366   }
   2367 
   2368   for (VariableIndex = 0; VariableIndex < IpSecVariableInfo.VariableCount; VariableIndex++) {
   2369     //
   2370     // Construct and set the variable of ipsecconfig data one by one.
   2371     // The index of variable name begin from 0001, and the varaible name
   2372     // likes "VariableName0001", "VaraiableName0002"....
   2373     //
   2374     UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%04d", VariableName, VariableIndex + 1);
   2375     Status = gRT->SetVariable (
   2376                     VariableNameI,
   2377                     VendorGuid,
   2378                     Attributes,
   2379                     (VariableIndex == IpSecVariableInfo.VariableCount - 1) ?
   2380                     (DataSize % (UINTN) MaximumVariableSize) :
   2381                     (UINTN) MaximumVariableSize,
   2382                     (UINT8 *) Data + VariableIndex * (UINTN) MaximumVariableSize
   2383                     );
   2384 
   2385     if (EFI_ERROR (Status)) {
   2386       DEBUG ((DEBUG_ERROR, "Error set ipsecconfig variable data with %r\n", Status));
   2387       goto ON_EXIT;
   2388     }
   2389   }
   2390 
   2391 ON_EXIT:
   2392   if (VariableNameI != NULL) {
   2393     FreePool (VariableNameI);
   2394   }
   2395 
   2396   return Status;
   2397 }
   2398 
   2399 /**
   2400   Return the configuration value for the EFI IPsec driver.
   2401 
   2402   This function lookup the data entry from IPsec database or IKEv2 configuration
   2403   information. The expected data type and unique identification are described in
   2404   DataType and Selector parameters.
   2405 
   2406   @param[in]      This          Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
   2407   @param[in]      DataType      The type of data to retrieve.
   2408   @param[in]      Selector      Pointer to an entry selector that is an identifier of the IPsec
   2409                                 configuration data entry.
   2410   @param[in, out] DataSize      On output the size of data returned in Data.
   2411   @param[out]     Data          The buffer to return the contents of the IPsec configuration data.
   2412                                 The type of the data buffer associated with the DataType.
   2413 
   2414   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   2415   @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
   2416                                 - This is NULL.
   2417                                 - Selector is NULL.
   2418                                 - DataSize is NULL.
   2419                                 - Data is NULL and *DataSize is not zero
   2420   @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
   2421   @retval EFI_UNSUPPORTED       The specified DataType is not supported.
   2422   @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
   2423                                 updated with the size needed to complete the request.
   2424 
   2425 **/
   2426 EFI_STATUS
   2427 EFIAPI
   2428 EfiIpSecConfigGetData (
   2429   IN     EFI_IPSEC_CONFIG_PROTOCOL    *This,
   2430   IN     EFI_IPSEC_CONFIG_DATA_TYPE   DataType,
   2431   IN     EFI_IPSEC_CONFIG_SELECTOR    *Selector,
   2432   IN OUT UINTN                        *DataSize,
   2433      OUT VOID                         *Data
   2434   )
   2435 {
   2436   if (This == NULL || Selector == NULL || DataSize == NULL) {
   2437     return EFI_INVALID_PARAMETER;
   2438   }
   2439 
   2440   if (*DataSize != 0 && Data == NULL) {
   2441     return EFI_INVALID_PARAMETER;
   2442   }
   2443 
   2444   if (DataType >= IPsecConfigDataTypeMaximum) {
   2445     return EFI_UNSUPPORTED;
   2446   }
   2447 
   2448   return mGetPolicyEntry[DataType](Selector, DataSize, Data);
   2449 }
   2450 
   2451 /**
   2452   Set the security association, security policy and peer authorization configuration
   2453   information for the EFI IPsec driver.
   2454 
   2455   This function is used to set the IPsec configuration information of type DataType for
   2456   the EFI IPsec driver.
   2457   The IPsec configuration data has a unique selector/identifier separately to identify
   2458   a data entry. The selector structure depends on DataType's definition.
   2459   Using SetData() with a Data of NULL causes the IPsec configuration data entry identified
   2460   by DataType and Selector to be deleted.
   2461 
   2462   @param[in] This               Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
   2463   @param[in] DataType           The type of data to be set.
   2464   @param[in] Selector           Pointer to an entry selector on operated configuration data
   2465                                 specified by DataType. A NULL Selector causes the entire
   2466                                 specified-type configuration information to be flushed.
   2467   @param[in] Data               The data buffer to be set. The structure of the data buffer is
   2468                                 associated with the DataType.
   2469   @param[in] InsertBefore       Pointer to one entry selector which describes the expected
   2470                                 position the new data entry will be added. If InsertBefore is NULL,
   2471                                 the new entry will be appended to the end of the database.
   2472 
   2473   @retval EFI_SUCCESS           The specified configuration entry data was set successfully.
   2474   @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
   2475                                 - This is NULL.
   2476   @retval EFI_UNSUPPORTED       The specified DataType is not supported.
   2477   @retval EFI_OUT_OF_RESOURCED  The required system resource could not be allocated.
   2478 
   2479 **/
   2480 EFI_STATUS
   2481 EFIAPI
   2482 EfiIpSecConfigSetData (
   2483   IN EFI_IPSEC_CONFIG_PROTOCOL        *This,
   2484   IN EFI_IPSEC_CONFIG_DATA_TYPE       DataType,
   2485   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector,
   2486   IN VOID                             *Data,
   2487   IN EFI_IPSEC_CONFIG_SELECTOR        *InsertBefore OPTIONAL
   2488   )
   2489 {
   2490   EFI_STATUS  Status;
   2491 
   2492   if (This == NULL) {
   2493     return EFI_INVALID_PARAMETER;
   2494   }
   2495 
   2496   if (DataType >= IPsecConfigDataTypeMaximum) {
   2497     return EFI_UNSUPPORTED;
   2498   }
   2499 
   2500   Status = mSetPolicyEntry[DataType](Selector, Data, InsertBefore);
   2501 
   2502   if (!EFI_ERROR (Status) && !mSetBySelf) {
   2503     //
   2504     // Save the updated config data into variable.
   2505     //
   2506     IpSecConfigSave ();
   2507   }
   2508 
   2509   return Status;
   2510 }
   2511 
   2512 /**
   2513   Enumerates the current selector for IPsec configuration data entry.
   2514 
   2515   This function is called multiple times to retrieve the entry Selector in IPsec
   2516   configuration database. On each call to GetNextSelector(), the next entry
   2517   Selector are retrieved into the output interface.
   2518 
   2519   If the entire IPsec configuration database has been iterated, the error
   2520   EFI_NOT_FOUND is returned.
   2521   If the Selector buffer is too small for the next Selector copy, an
   2522   EFI_BUFFER_TOO_SMALL error is returned, and SelectorSize is updated to reflect
   2523   the size of buffer needed.
   2524 
   2525   On the initial call to GetNextSelector() to start the IPsec configuration database
   2526   search, a pointer to the buffer with all zero value is passed in Selector. Calls
   2527   to SetData() between calls to GetNextSelector may produce unpredictable results.
   2528 
   2529   @param[in]      This          Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
   2530   @param[in]      DataType      The type of IPsec configuration data to retrieve.
   2531   @param[in, out] SelectorSize  The size of the Selector buffer.
   2532   @param[in, out] Selector      On input, supplies the pointer to last Selector that was
   2533                                 returned by GetNextSelector().
   2534                                 On output, returns one copy of the current entry Selector
   2535                                 of a given DataType.
   2536 
   2537   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   2538   @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
   2539                                 - This is NULL.
   2540                                 - SelectorSize is NULL.
   2541                                 - Selector is NULL.
   2542   @retval EFI_NOT_FOUND         The next configuration data entry was not found.
   2543   @retval EFI_UNSUPPORTED       The specified DataType is not supported.
   2544   @retval EFI_BUFFER_TOO_SMALL  The SelectorSize is too small for the result. This parameter
   2545                                 has been updated with the size needed to complete the search
   2546                                 request.
   2547 
   2548 **/
   2549 EFI_STATUS
   2550 EFIAPI
   2551 EfiIpSecConfigGetNextSelector (
   2552   IN     EFI_IPSEC_CONFIG_PROTOCOL    *This,
   2553   IN     EFI_IPSEC_CONFIG_DATA_TYPE   DataType,
   2554   IN OUT UINTN                        *SelectorSize,
   2555   IN OUT EFI_IPSEC_CONFIG_SELECTOR    *Selector
   2556   )
   2557 {
   2558   LIST_ENTRY                *Link;
   2559   IPSEC_COMMON_POLICY_ENTRY *CommonEntry;
   2560   BOOLEAN                   IsFound;
   2561 
   2562   if (This == NULL || Selector == NULL || SelectorSize == NULL) {
   2563     return EFI_INVALID_PARAMETER;
   2564   }
   2565 
   2566   if (DataType >= IPsecConfigDataTypeMaximum) {
   2567     return EFI_UNSUPPORTED;
   2568   }
   2569 
   2570   IsFound = FALSE;
   2571 
   2572   NET_LIST_FOR_EACH (Link, &mConfigData[DataType]) {
   2573     CommonEntry = BASE_CR (Link, IPSEC_COMMON_POLICY_ENTRY, List);
   2574 
   2575     if (IsFound || (BOOLEAN)(mIsZeroSelector[DataType](Selector))) {
   2576       //
   2577       // If found the appointed entry, then duplicate the next one and return,
   2578       // or if the appointed entry is zero, then return the first one directly.
   2579       //
   2580       return mDuplicateSelector[DataType](Selector, CommonEntry->Selector, SelectorSize);
   2581     } else {
   2582       //
   2583       // Set the flag if find the appointed entry.
   2584       //
   2585       IsFound = mCompareSelector[DataType](Selector, CommonEntry->Selector);
   2586     }
   2587   }
   2588 
   2589   return EFI_NOT_FOUND;
   2590 }
   2591 
   2592 /**
   2593   Register an event that is to be signaled whenever a configuration process on the
   2594   specified IPsec configuration information is done.
   2595 
   2596   The register function is not surpport now and always returns EFI_UNSUPPORTED.
   2597 
   2598   @param[in] This               Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
   2599   @param[in] DataType           The type of data to be registered the event for.
   2600   @param[in] Event              The event to be registered.
   2601 
   2602   @retval EFI_SUCCESS           The event is registered successfully.
   2603   @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
   2604   @retval EFI_ACCESS_DENIED     The Event is already registered for the DataType.
   2605   @retval EFI_UNSUPPORTED       The notify registration is unsupported, or the specified
   2606                                 DataType is not supported.
   2607 
   2608 **/
   2609 EFI_STATUS
   2610 EFIAPI
   2611 EfiIpSecConfigRegisterNotify (
   2612   IN EFI_IPSEC_CONFIG_PROTOCOL        *This,
   2613   IN EFI_IPSEC_CONFIG_DATA_TYPE       DataType,
   2614   IN EFI_EVENT                        Event
   2615   )
   2616 {
   2617   return EFI_UNSUPPORTED;
   2618 }
   2619 
   2620 /**
   2621   Remove the specified event that was previously registered on the specified IPsec
   2622   configuration data.
   2623 
   2624   This function is not support now and alwasy return EFI_UNSUPPORTED.
   2625 
   2626   @param[in] This               Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
   2627   @param[in] DataType           The configuration data type to remove the registered event for.
   2628   @param[in] Event              The event to be unregistered.
   2629 
   2630   @retval EFI_SUCCESS           The event was removed successfully.
   2631   @retval EFI_NOT_FOUND         The Event specified by DataType could not be found in the
   2632                                 database.
   2633   @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
   2634   @retval EFI_UNSUPPORTED       The notify registration is unsupported, or the specified
   2635                                 DataType is not supported.
   2636 
   2637 **/
   2638 EFI_STATUS
   2639 EFIAPI
   2640 EfiIpSecConfigUnregisterNotify (
   2641   IN EFI_IPSEC_CONFIG_PROTOCOL        *This,
   2642   IN EFI_IPSEC_CONFIG_DATA_TYPE       DataType,
   2643   IN EFI_EVENT                        Event
   2644   )
   2645 {
   2646   return EFI_UNSUPPORTED;
   2647 }
   2648 
   2649 /**
   2650   Copy whole data in specified EFI_SIPEC_CONFIG_SELECTOR and the Data to a buffer.
   2651 
   2652   This function is a caller defined function, and it is called by the IpSecVisitConfigData().
   2653   The orignal caller is IpSecConfigSave(), which calls the IpsecVisitConfigData() to
   2654   copy all types of IPsec Config datas into one buffer and store this buffer into firmware in
   2655   the form of several variables.
   2656 
   2657   @param[in]      Type              A specified IPSEC_CONFIG_DATA_TYPE.
   2658   @param[in]      Selector          Points to a EFI_IPSEC_CONFIG_SELECTOR to be copied
   2659                                     to the buffer.
   2660   @param[in]      Data              Points to data to be copied to the buffer. The
   2661                                     Data type is related to the Type.
   2662   @param[in]      SelectorSize      The size of the Selector.
   2663   @param[in]      DataSize          The size of the Data.
   2664   @param[in, out] Buffer            The buffer to store the Selector and Data.
   2665 
   2666   @retval EFI_SUCCESS            Copy the Selector and Data to a buffer successfully.
   2667   @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated.
   2668 
   2669 **/
   2670 EFI_STATUS
   2671 IpSecCopyPolicyEntry (
   2672   IN     EFI_IPSEC_CONFIG_DATA_TYPE   Type,
   2673   IN     EFI_IPSEC_CONFIG_SELECTOR    *Selector,
   2674   IN     VOID                         *Data,
   2675   IN     UINTN                        SelectorSize,
   2676   IN     UINTN                        DataSize,
   2677   IN OUT IPSEC_VARIABLE_BUFFER        *Buffer
   2678   )
   2679 {
   2680   IPSEC_VAR_ITEM_HEADER SelectorHeader;
   2681   IPSEC_VAR_ITEM_HEADER DataHeader;
   2682   UINTN                 EntrySize;
   2683   UINT8                 *TempPoint;
   2684 
   2685   if (Type == IPsecConfigDataTypeSad) {
   2686     //
   2687     // Don't save automatically-generated SA entry into variable.
   2688     //
   2689     if (((EFI_IPSEC_SA_DATA2 *) Data)->ManualSet == FALSE) {
   2690       return EFI_SUCCESS;
   2691     }
   2692   }
   2693   //
   2694   // Increase the capacity size of the buffer if needed.
   2695   //
   2696   EntrySize  = ALIGN_VARIABLE (sizeof (SelectorHeader));
   2697   EntrySize  = ALIGN_VARIABLE (EntrySize + SelectorSize);
   2698   EntrySize  = ALIGN_VARIABLE (EntrySize + sizeof (SelectorHeader));
   2699   EntrySize  = ALIGN_VARIABLE (EntrySize + DataSize);
   2700 
   2701   //EntrySize = SelectorSize + DataSize + 2 * sizeof (SelectorHeader);
   2702   if (Buffer->Capacity - Buffer->Size < EntrySize) {
   2703     //
   2704     // Calculate the required buffer
   2705     //
   2706     Buffer->Capacity += EntrySize;
   2707     TempPoint         = AllocatePool (Buffer->Capacity);
   2708 
   2709     if (TempPoint == NULL) {
   2710       return EFI_OUT_OF_RESOURCES;
   2711     }
   2712     //
   2713     // Copy the old Buffer to new buffer and free the old one.
   2714     //
   2715     CopyMem (TempPoint, Buffer->Ptr, Buffer->Size);
   2716     FreePool (Buffer->Ptr);
   2717 
   2718     Buffer->Ptr       =  TempPoint;
   2719   }
   2720 
   2721   mFixPolicyEntry[Type](Selector, Data);
   2722 
   2723   //
   2724   // Fill the selector header and copy it into buffer.
   2725   //
   2726   SelectorHeader.Type = (UINT8) (Type | IPSEC_VAR_ITEM_HEADER_LOGO_BIT);
   2727   SelectorHeader.Size = (UINT16) SelectorSize;
   2728 
   2729   CopyMem (
   2730     Buffer->Ptr + Buffer->Size,
   2731     &SelectorHeader,
   2732     sizeof (SelectorHeader)
   2733     );
   2734   Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + sizeof (SelectorHeader));
   2735 
   2736   //
   2737   // Copy the selector into buffer.
   2738   //
   2739   CopyMem (
   2740     Buffer->Ptr + Buffer->Size,
   2741     Selector,
   2742     SelectorSize
   2743     );
   2744   Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + SelectorSize);
   2745 
   2746   //
   2747   // Fill the data header and copy it into buffer.
   2748   //
   2749   DataHeader.Type = (UINT8) Type;
   2750   DataHeader.Size = (UINT16) DataSize;
   2751 
   2752   CopyMem (
   2753     Buffer->Ptr + Buffer->Size,
   2754     &DataHeader,
   2755     sizeof (DataHeader)
   2756     );
   2757   Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + sizeof (DataHeader));
   2758   //
   2759   // Copy the data into buffer.
   2760   //
   2761   CopyMem (
   2762     Buffer->Ptr + Buffer->Size,
   2763     Data,
   2764     DataSize
   2765     );
   2766   Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + DataSize);
   2767 
   2768   mUnfixPolicyEntry[Type](Selector, Data);
   2769 
   2770   return EFI_SUCCESS;
   2771 }
   2772 
   2773 /**
   2774   Visit all IPsec Configurations of specified Type and call the caller defined
   2775   interface.
   2776 
   2777   @param[in]  DataType          The specified IPsec Config Data Type.
   2778   @param[in]  Routine           The function defined by the caller.
   2779   @param[in]  Context           The data passed to the Routine.
   2780 
   2781   @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated
   2782   @retval EFI_SUCCESS            This function completed successfully.
   2783 
   2784 **/
   2785 EFI_STATUS
   2786 IpSecVisitConfigData (
   2787   IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
   2788   IN IPSEC_COPY_POLICY_ENTRY    Routine,
   2789   IN VOID                       *Context
   2790   )
   2791 {
   2792   EFI_STATUS                GetNextStatus;
   2793   EFI_STATUS                GetDataStatus;
   2794   EFI_STATUS                RoutineStatus;
   2795   EFI_IPSEC_CONFIG_SELECTOR *Selector;
   2796   VOID                      *Data;
   2797   UINTN                     SelectorSize;
   2798   UINTN                     DataSize;
   2799   UINTN                     SelectorBufferSize;
   2800   UINTN                     DataBufferSize;
   2801   BOOLEAN                   FirstGetNext;
   2802 
   2803   FirstGetNext        = TRUE;
   2804   DataBufferSize      = 0;
   2805   Data                = NULL;
   2806   SelectorBufferSize  = sizeof (EFI_IPSEC_CONFIG_SELECTOR);
   2807   Selector            = AllocateZeroPool (SelectorBufferSize);
   2808 
   2809   if (Selector == NULL) {
   2810     return EFI_OUT_OF_RESOURCES;
   2811   }
   2812 
   2813   while (TRUE) {
   2814     //
   2815     // Get the real size of the selector.
   2816     //
   2817     SelectorSize = SelectorBufferSize;
   2818     GetNextStatus = EfiIpSecConfigGetNextSelector (
   2819                       &mIpSecConfigInstance,
   2820                       DataType,
   2821                       &SelectorSize,
   2822                       Selector
   2823                       );
   2824     if (GetNextStatus == EFI_BUFFER_TOO_SMALL) {
   2825       FreePool (Selector);
   2826       SelectorBufferSize = SelectorSize;
   2827       //
   2828       // Allocate zero pool for the first selector, while store the last
   2829       // selector content for the other selectors.
   2830       //
   2831       if (FirstGetNext) {
   2832         Selector = AllocateZeroPool (SelectorBufferSize);
   2833       } else {
   2834         Selector = AllocateCopyPool (SelectorBufferSize, Selector);
   2835       }
   2836 
   2837       if (Selector == NULL) {
   2838         return EFI_OUT_OF_RESOURCES;
   2839       }
   2840       //
   2841       // Get the content of the selector.
   2842       //
   2843       GetNextStatus = EfiIpSecConfigGetNextSelector (
   2844                         &mIpSecConfigInstance,
   2845                         DataType,
   2846                         &SelectorSize,
   2847                         Selector
   2848                         );
   2849     }
   2850 
   2851     if (EFI_ERROR (GetNextStatus)) {
   2852       break;
   2853     }
   2854 
   2855     FirstGetNext = FALSE;
   2856 
   2857     //
   2858     // Get the real size of the policy entry according to the selector.
   2859     //
   2860     DataSize = DataBufferSize;
   2861     GetDataStatus = EfiIpSecConfigGetData (
   2862                       &mIpSecConfigInstance,
   2863                       DataType,
   2864                       Selector,
   2865                       &DataSize,
   2866                       Data
   2867                       );
   2868     if (GetDataStatus == EFI_BUFFER_TOO_SMALL) {
   2869       if (Data != NULL) {
   2870         FreePool (Data);
   2871       }
   2872 
   2873       DataBufferSize  = DataSize;
   2874       Data            = AllocateZeroPool (DataBufferSize);
   2875 
   2876       if (Data == NULL) {
   2877         return EFI_OUT_OF_RESOURCES;
   2878       }
   2879       //
   2880       // Get the content of the policy entry according to the selector.
   2881       //
   2882       GetDataStatus = EfiIpSecConfigGetData (
   2883                         &mIpSecConfigInstance,
   2884                         DataType,
   2885                         Selector,
   2886                         &DataSize,
   2887                         Data
   2888                         );
   2889     }
   2890 
   2891     if (EFI_ERROR (GetDataStatus)) {
   2892       break;
   2893     }
   2894     //
   2895     // Prepare the buffer of updated policy entry, which is stored in
   2896     // the continous memory, and then save into variable later.
   2897     //
   2898     RoutineStatus = Routine (
   2899                       DataType,
   2900                       Selector,
   2901                       Data,
   2902                       SelectorSize,
   2903                       DataSize,
   2904                       Context
   2905                       );
   2906     if (EFI_ERROR (RoutineStatus)) {
   2907       break;
   2908     }
   2909   }
   2910 
   2911   if (Data != NULL) {
   2912     FreePool (Data);
   2913   }
   2914 
   2915   if (Selector != NULL) {
   2916     FreePool (Selector);
   2917   }
   2918 
   2919   return EFI_SUCCESS;
   2920 }
   2921 
   2922 /**
   2923   This function is the subfunction of  EFIIpSecConfigSetData.
   2924 
   2925   This function call IpSecSetVaraible to set the IPsec Configuration into the firmware.
   2926 
   2927   @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated.
   2928   @retval EFI_SUCCESS            Saved the configration successfully.
   2929   @retval Others                 Other errors were found while obtaining the variable.
   2930 
   2931 **/
   2932 EFI_STATUS
   2933 IpSecConfigSave (
   2934   VOID
   2935   )
   2936 {
   2937   IPSEC_VARIABLE_BUFFER       Buffer;
   2938   EFI_STATUS                  Status;
   2939   EFI_IPSEC_CONFIG_DATA_TYPE  Type;
   2940 
   2941   Buffer.Size     = 0;
   2942   Buffer.Capacity = IPSEC_DEFAULT_VARIABLE_SIZE;
   2943   Buffer.Ptr      = AllocateZeroPool (Buffer.Capacity);
   2944 
   2945   if (Buffer.Ptr == NULL) {
   2946     return EFI_OUT_OF_RESOURCES;
   2947   }
   2948   //
   2949   // For each policy database, prepare the contious buffer to save into variable.
   2950   //
   2951   for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) {
   2952     IpSecVisitConfigData (
   2953       Type,
   2954       (IPSEC_COPY_POLICY_ENTRY) IpSecCopyPolicyEntry,
   2955       &Buffer
   2956       );
   2957   }
   2958   //
   2959   // Save the updated policy database into variable.
   2960   //
   2961   Status = IpSecSetVariable (
   2962              IPSECCONFIG_VARIABLE_NAME,
   2963              &gEfiIpSecConfigProtocolGuid,
   2964              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
   2965              Buffer.Size,
   2966              Buffer.Ptr
   2967              );
   2968 
   2969   FreePool (Buffer.Ptr);
   2970 
   2971   return Status;
   2972 }
   2973 
   2974 /**
   2975   Get the all IPSec configuration variables and store those variables
   2976   to the internal data structure.
   2977 
   2978   This founction is called by IpSecConfigInitialize() which is to intialize the
   2979   IPsecConfiguration Protocol.
   2980 
   2981   @param[in]  Private            Point to IPSEC_PRIVATE_DATA.
   2982 
   2983   @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated
   2984   @retval EFI_SUCCESS            Restore the IPsec Configuration successfully.
   2985   @retval  others                Other errors is found while obtaining the variable.
   2986 
   2987 **/
   2988 EFI_STATUS
   2989 IpSecConfigRestore (
   2990   IN IPSEC_PRIVATE_DATA           *Private
   2991   )
   2992 {
   2993   EFI_STATUS                  Status;
   2994   UINTN                       BufferSize;
   2995   UINT8                       *Buffer;
   2996   IPSEC_VAR_ITEM_HEADER       *Header;
   2997   UINT8                       *Ptr;
   2998   EFI_IPSEC_CONFIG_SELECTOR   *Selector;
   2999   EFI_IPSEC_CONFIG_DATA_TYPE  Type;
   3000   VOID                        *Data;
   3001   UINT8                       Value;
   3002   UINTN                       Size;
   3003 
   3004   Value       = 0;
   3005   Size        = sizeof (Value);
   3006   BufferSize  = 0;
   3007   Buffer      = NULL;
   3008 
   3009   Status = gRT->GetVariable (
   3010                   IPSECCONFIG_STATUS_NAME,
   3011                   &gEfiIpSecConfigProtocolGuid,
   3012                   NULL,
   3013                   &Size,
   3014                   &Value
   3015              );
   3016 
   3017   if (!EFI_ERROR (Status) && Value == IPSEC_STATUS_ENABLED) {
   3018     Private->IpSec.DisabledFlag = FALSE;
   3019   }
   3020   //
   3021   // Get the real size of policy database in variable.
   3022   //
   3023   Status = IpSecGetVariable (
   3024              IPSECCONFIG_VARIABLE_NAME,
   3025              &gEfiIpSecConfigProtocolGuid,
   3026              NULL,
   3027              &BufferSize,
   3028              Buffer
   3029              );
   3030   if (Status == EFI_BUFFER_TOO_SMALL) {
   3031 
   3032     Buffer = AllocateZeroPool (BufferSize);
   3033     if (Buffer == NULL) {
   3034       return EFI_OUT_OF_RESOURCES;
   3035     }
   3036     //
   3037     // Get the content of policy database in variable.
   3038     //
   3039     Status = IpSecGetVariable (
   3040                IPSECCONFIG_VARIABLE_NAME,
   3041                &gEfiIpSecConfigProtocolGuid,
   3042                NULL,
   3043                &BufferSize,
   3044                Buffer
   3045                );
   3046     if (EFI_ERROR (Status)) {
   3047       FreePool (Buffer);
   3048       return Status;
   3049     }
   3050 
   3051     for (Ptr = Buffer; Ptr < Buffer + BufferSize;) {
   3052 
   3053       Header  = (IPSEC_VAR_ITEM_HEADER *) Ptr;
   3054       Type    = (EFI_IPSEC_CONFIG_DATA_TYPE) (Header->Type & IPSEC_VAR_ITEM_HEADER_CONTENT_BIT);
   3055       ASSERT (((Header->Type & 0x80) == IPSEC_VAR_ITEM_HEADER_LOGO_BIT) && (Type < IPsecConfigDataTypeMaximum));
   3056 
   3057       Selector  = (EFI_IPSEC_CONFIG_SELECTOR *) ALIGN_POINTER (Header + 1, sizeof (UINTN));
   3058       Header    = (IPSEC_VAR_ITEM_HEADER *) ALIGN_POINTER (
   3059                                               (UINT8 *) Selector + Header->Size,
   3060                                               sizeof (UINTN)
   3061                                               );
   3062       ASSERT (Header->Type == Type);
   3063 
   3064       Data = ALIGN_POINTER (Header + 1, sizeof (UINTN));
   3065 
   3066       mUnfixPolicyEntry[Type](Selector, Data);
   3067 
   3068       //
   3069       // Update each policy entry according to the content in variable.
   3070       //
   3071       mSetBySelf = TRUE;
   3072       Status = EfiIpSecConfigSetData (
   3073                  &Private->IpSecConfig,
   3074                  Type,
   3075                  Selector,
   3076                  Data,
   3077                  NULL
   3078                  );
   3079       mSetBySelf = FALSE;
   3080 
   3081       if (EFI_ERROR (Status)) {
   3082         FreePool (Buffer);
   3083         return Status;
   3084       }
   3085 
   3086       Ptr =  ALIGN_POINTER ((UINT8 *) Data + Header->Size, sizeof (UINTN));
   3087     }
   3088 
   3089     FreePool (Buffer);
   3090   }
   3091 
   3092   return EFI_SUCCESS;
   3093 }
   3094 
   3095 /**
   3096   Install and Initialize IPsecConfig protocol
   3097 
   3098   @param[in, out]  Private   Pointer to IPSEC_PRIVATE_DATA. After this function finish,
   3099                              the pointer of IPsecConfig Protocol implementation will copy
   3100                              into its IPsecConfig member.
   3101 
   3102   @retval     EFI_SUCCESS    Initialized the IPsecConfig Protocol successfully.
   3103   @retval     Others         Initializing the IPsecConfig Protocol failed.
   3104 **/
   3105 EFI_STATUS
   3106 IpSecConfigInitialize (
   3107   IN OUT IPSEC_PRIVATE_DATA        *Private
   3108   )
   3109 {
   3110   EFI_IPSEC_CONFIG_DATA_TYPE  Type;
   3111 
   3112   CopyMem (
   3113     &Private->IpSecConfig,
   3114     &mIpSecConfigInstance,
   3115     sizeof (EFI_IPSEC_CONFIG_PROTOCOL)
   3116     );
   3117 
   3118   //
   3119   // Initialize the list head of policy database.
   3120   //
   3121   for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) {
   3122     InitializeListHead (&mConfigData[Type]);
   3123   }
   3124   //
   3125   // Restore the content of policy database according to the variable.
   3126   //
   3127   IpSecConfigRestore (Private);
   3128 
   3129   return gBS->InstallMultipleProtocolInterfaces (
   3130                 &Private->Handle,
   3131                 &gEfiIpSecConfigProtocolGuid,
   3132                 &Private->IpSecConfig,
   3133                 NULL
   3134                 );
   3135 }
   3136