Home | History | Annotate | Download | only in IpSecDxe
      1 /** @file
      2   The implementation of IPSEC_CONFIG_PROTOCOL.
      3 
      4   Copyright (c) 2009 - 2016, 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 and RemoteAddress 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 and RemoteAddress 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 and RemoteAddress fields in the two Spdselectors.
    433   // First, SpdSel1->LocalAddress to SpdSel2->RemoteAddress && Compare
    434   // SpdSel1->RemoteAddress to SpdSel2->LocalAddress. 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                                    - SadEntry requied to be set into new SpdEntry's Sas has
   1022                                      been found but it is invalid.
   1023   @retval EFI_OUT_OF_RESOURCED  The required system resource could not be allocated.
   1024   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1025 
   1026 **/
   1027 EFI_STATUS
   1028 SetSpdEntry (
   1029   IN EFI_IPSEC_CONFIG_SELECTOR       *Selector,
   1030   IN VOID                            *Data,
   1031   IN VOID                            *Context OPTIONAL
   1032   )
   1033 {
   1034   EFI_IPSEC_SPD_SELECTOR  *SpdSel;
   1035   EFI_IPSEC_SPD_DATA      *SpdData;
   1036   EFI_IPSEC_SPD_SELECTOR  *InsertBefore;
   1037   LIST_ENTRY              *SpdList;
   1038   LIST_ENTRY              *SadList;
   1039   LIST_ENTRY              *SpdSas;
   1040   LIST_ENTRY              *EntryInsertBefore;
   1041   LIST_ENTRY              *Entry;
   1042   LIST_ENTRY              *Entry2;
   1043   LIST_ENTRY              *NextEntry;
   1044   LIST_ENTRY              *NextEntry2;
   1045   IPSEC_SPD_ENTRY         *SpdEntry;
   1046   IPSEC_SAD_ENTRY         *SadEntry;
   1047   UINTN                   SpdEntrySize;
   1048   UINTN                   Index;
   1049 
   1050   SpdSel        = (Selector == NULL) ? NULL : &Selector->SpdSelector;
   1051   SpdData       = (Data == NULL) ? NULL : (EFI_IPSEC_SPD_DATA *) Data;
   1052   InsertBefore  = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->SpdSelector;
   1053   SpdList       = &mConfigData[IPsecConfigDataTypeSpd];
   1054 
   1055   if (SpdSel != NULL) {
   1056     if (SpdSel->LocalAddress == NULL || SpdSel->RemoteAddress == NULL) {
   1057       return EFI_INVALID_PARAMETER;
   1058     }
   1059   }
   1060 
   1061   if (SpdData != NULL) {
   1062     if ((SpdData->Action == EfiIPsecActionProtect && SpdData->ProcessingPolicy == NULL) ||
   1063         (SpdData->Action != EfiIPsecActionProtect && SpdData->ProcessingPolicy != NULL)
   1064         ) {
   1065       return EFI_INVALID_PARAMETER;
   1066     }
   1067 
   1068     if (SpdData->Action == EfiIPsecActionProtect) {
   1069       if ((SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel && SpdData->ProcessingPolicy->TunnelOption == NULL) ||
   1070           (SpdData->ProcessingPolicy->Mode != EfiIPsecTunnel && SpdData->ProcessingPolicy->TunnelOption != NULL)
   1071           ) {
   1072         return EFI_INVALID_PARAMETER;
   1073       }
   1074     }
   1075   }
   1076   //
   1077   // The default behavior is to insert the node ahead of the header.
   1078   //
   1079   EntryInsertBefore = SpdList;
   1080 
   1081   //
   1082   // Remove the existed SPD entry.
   1083   //
   1084   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SpdList) {
   1085 
   1086     SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
   1087 
   1088     if (SpdSel == NULL ||
   1089         CompareSpdSelector ((EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector, (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel)
   1090         ) {
   1091       //
   1092       // Record the existed entry position to keep the original order.
   1093       //
   1094       EntryInsertBefore = SpdEntry->List.ForwardLink;
   1095       RemoveEntryList (&SpdEntry->List);
   1096 
   1097       //
   1098       // Update the reverse ref of SAD entry in the SPD.sas list.
   1099       //
   1100       SpdSas = &SpdEntry->Data->Sas;
   1101 
   1102       //
   1103       // Remove the related SAs from Sas(SadEntry->BySpd). If the SA entry is established by
   1104       // IKE, remove from mConfigData list(SadEntry->List) and then free it directly since its
   1105       // SpdEntry will be freed later.
   1106       //
   1107       NET_LIST_FOR_EACH_SAFE (Entry2, NextEntry2, SpdSas) {
   1108         SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry2);
   1109 
   1110         if (SadEntry->Data->SpdEntry != NULL) {
   1111           RemoveEntryList (&SadEntry->BySpd);
   1112           SadEntry->Data->SpdEntry = NULL;
   1113         }
   1114 
   1115         if (!(SadEntry->Data->ManualSet)) {
   1116           RemoveEntryList (&SadEntry->List);
   1117           FreePool (SadEntry);
   1118         }
   1119       }
   1120 
   1121       //
   1122       // Free the existed SPD entry
   1123       //
   1124       FreePool (SpdEntry);
   1125     }
   1126   }
   1127   //
   1128   // Return success here if only want to remove the SPD entry.
   1129   //
   1130   if (SpdData == NULL || SpdSel == NULL) {
   1131     return EFI_SUCCESS;
   1132   }
   1133   //
   1134   // Search the appointed entry position if InsertBefore is not NULL.
   1135   //
   1136   if (InsertBefore != NULL) {
   1137 
   1138     NET_LIST_FOR_EACH (Entry, SpdList) {
   1139       SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
   1140 
   1141       if (CompareSpdSelector (
   1142             (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector,
   1143             (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore
   1144             )) {
   1145         EntryInsertBefore = Entry;
   1146         break;
   1147       }
   1148     }
   1149   }
   1150 
   1151   //
   1152   // Do Padding for the different Arch.
   1153   //
   1154   SpdEntrySize  = ALIGN_VARIABLE (sizeof (IPSEC_SPD_ENTRY));
   1155   SpdEntrySize  = ALIGN_VARIABLE (SpdEntrySize + (UINTN)SIZE_OF_SPD_SELECTOR (SpdSel));
   1156   SpdEntrySize += IpSecGetSizeOfEfiSpdData (SpdData);
   1157 
   1158   SpdEntry = AllocateZeroPool (SpdEntrySize);
   1159 
   1160   if (SpdEntry == NULL) {
   1161     return EFI_OUT_OF_RESOURCES;
   1162   }
   1163   //
   1164   // Fix the address of Selector and Data buffer and copy them, which is
   1165   // continous memory and close to the base structure of SPD entry.
   1166   //
   1167   SpdEntry->Selector  = (EFI_IPSEC_SPD_SELECTOR *) ALIGN_POINTER ((SpdEntry + 1), sizeof (UINTN));
   1168   SpdEntry->Data      = (IPSEC_SPD_DATA *) ALIGN_POINTER (
   1169                                             ((UINT8 *) SpdEntry->Selector + SIZE_OF_SPD_SELECTOR (SpdSel)),
   1170                                             sizeof (UINTN)
   1171                                             );
   1172 
   1173   DuplicateSpdSelector (
   1174     (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector,
   1175     (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel,
   1176     NULL
   1177     );
   1178 
   1179   CopyMem (
   1180     SpdEntry->Data->Name,
   1181     SpdData->Name,
   1182     sizeof (SpdData->Name)
   1183     );
   1184   SpdEntry->Data->PackageFlag      = SpdData->PackageFlag;
   1185   SpdEntry->Data->TrafficDirection = SpdData->TrafficDirection;
   1186   SpdEntry->Data->Action           = SpdData->Action;
   1187 
   1188   //
   1189   // Fix the address of ProcessingPolicy and copy it if need, which is continous
   1190   // memory and close to the base structure of SAD data.
   1191   //
   1192   if (SpdData->Action != EfiIPsecActionProtect) {
   1193     SpdEntry->Data->ProcessingPolicy = NULL;
   1194   } else {
   1195     SpdEntry->Data->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ALIGN_POINTER (
   1196                                                                       SpdEntry->Data + 1,
   1197                                                                       sizeof (UINTN)
   1198                                                                       );
   1199     IpSecDuplicateProcessPolicy (SpdEntry->Data->ProcessingPolicy, SpdData->ProcessingPolicy);
   1200   }
   1201   //
   1202   // Update the sas list of the new SPD entry.
   1203   //
   1204   InitializeListHead (&SpdEntry->Data->Sas);
   1205 
   1206   SadList = &mConfigData[IPsecConfigDataTypeSad];
   1207 
   1208   NET_LIST_FOR_EACH (Entry, SadList) {
   1209     SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
   1210 
   1211       for (Index = 0; Index < SpdData->SaIdCount; Index++) {
   1212         if (CompareSaId (
   1213               (EFI_IPSEC_CONFIG_SELECTOR *) &SpdData->SaId[Index],
   1214               (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id
   1215               )) {
   1216           //
   1217           // Check whether the found SadEntry is vaild.
   1218           //
   1219           if (IsSubSpdSelector (
   1220                 (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector,
   1221                 (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
   1222                 )) {
   1223             if (SadEntry->Data->SpdEntry != NULL) {
   1224               RemoveEntryList (&SadEntry->BySpd);
   1225             }
   1226             InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd);
   1227             SadEntry->Data->SpdEntry = SpdEntry;
   1228           } else {
   1229             return EFI_INVALID_PARAMETER;
   1230           }
   1231         }
   1232       }
   1233   }
   1234 
   1235   //
   1236   // Insert the new SPD entry.
   1237   //
   1238   InsertTailList (EntryInsertBefore, &SpdEntry->List);
   1239 
   1240   return EFI_SUCCESS;
   1241 }
   1242 
   1243 /**
   1244   Set the security association information for the EFI IPsec driver.
   1245 
   1246   The IPsec configuration data has a unique selector/identifier separately to
   1247   identify a data entry.
   1248 
   1249   @param[in]  Selector           Pointer to an entry selector on operated
   1250                                  configuration data specified by DataType.
   1251                                  A NULL Selector causes the entire specified-type
   1252                                  configuration information to be flushed.
   1253   @param[in]  Data               The data buffer to be set. The structure
   1254                                  of the data buffer should be EFI_IPSEC_SA_DATA.
   1255   @param[in]  Context            Pointer to one entry selector which describes
   1256                                  the expected position the new data entry will
   1257                                  be added. If Context is NULL,the new entry will
   1258                                  be appended the end of database.
   1259 
   1260   @retval EFI_OUT_OF_RESOURCED  The required system resource could not be allocated.
   1261   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1262 
   1263 **/
   1264 EFI_STATUS
   1265 SetSadEntry (
   1266   IN EFI_IPSEC_CONFIG_SELECTOR       *Selector,
   1267   IN VOID                            *Data,
   1268   IN VOID                            *Context OPTIONAL
   1269   )
   1270 {
   1271   IPSEC_SAD_ENTRY   *SadEntry;
   1272   IPSEC_SPD_ENTRY   *SpdEntry;
   1273   LIST_ENTRY        *Entry;
   1274   LIST_ENTRY        *NextEntry;
   1275   LIST_ENTRY        *SadList;
   1276   LIST_ENTRY        *SpdList;
   1277   EFI_IPSEC_SA_ID   *SaId;
   1278   EFI_IPSEC_SA_DATA2 *SaData;
   1279   EFI_IPSEC_SA_ID   *InsertBefore;
   1280   LIST_ENTRY        *EntryInsertBefore;
   1281   UINTN             SadEntrySize;
   1282 
   1283   SaId          = (Selector == NULL) ? NULL : &Selector->SaId;
   1284   SaData        = (Data == NULL) ? NULL : (EFI_IPSEC_SA_DATA2 *) Data;
   1285   InsertBefore  = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->SaId;
   1286   SadList       = &mConfigData[IPsecConfigDataTypeSad];
   1287 
   1288   //
   1289   // The default behavior is to insert the node ahead of the header.
   1290   //
   1291   EntryInsertBefore = SadList;
   1292 
   1293   //
   1294   // Remove the existed SAD entry.
   1295   //
   1296   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SadList) {
   1297 
   1298     SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
   1299 
   1300     if (SaId == NULL ||
   1301         CompareSaId (
   1302           (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id,
   1303           (EFI_IPSEC_CONFIG_SELECTOR *) SaId
   1304           )) {
   1305       //
   1306       // Record the existed entry position to keep the original order.
   1307       //
   1308       EntryInsertBefore = SadEntry->List.ForwardLink;
   1309 
   1310       //
   1311       // Update the related SAD.byspd field.
   1312       //
   1313       if (SadEntry->Data->SpdEntry != NULL) {
   1314         RemoveEntryList (&SadEntry->BySpd);
   1315       }
   1316 
   1317       RemoveEntryList (&SadEntry->List);
   1318       FreePool (SadEntry);
   1319     }
   1320   }
   1321   //
   1322   // Return success here if only want to remove the SAD entry
   1323   //
   1324   if (SaData == NULL || SaId == NULL) {
   1325     return EFI_SUCCESS;
   1326   }
   1327   //
   1328   // Search the appointed entry position if InsertBefore is not NULL.
   1329   //
   1330   if (InsertBefore != NULL) {
   1331 
   1332     NET_LIST_FOR_EACH (Entry, SadList) {
   1333       SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
   1334 
   1335       if (CompareSaId (
   1336            (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id,
   1337            (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore
   1338            )) {
   1339         EntryInsertBefore = Entry;
   1340         break;
   1341       }
   1342     }
   1343   }
   1344 
   1345   //
   1346   // Do Padding for different Arch.
   1347   //
   1348   SadEntrySize  = ALIGN_VARIABLE (sizeof (IPSEC_SAD_ENTRY));
   1349   SadEntrySize  = ALIGN_VARIABLE (SadEntrySize + sizeof (EFI_IPSEC_SA_ID));
   1350   SadEntrySize  = ALIGN_VARIABLE (SadEntrySize + sizeof (IPSEC_SAD_DATA));
   1351 
   1352   if (SaId->Proto == EfiIPsecAH) {
   1353     SadEntrySize += SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength;
   1354   } else {
   1355     SadEntrySize  = ALIGN_VARIABLE (SadEntrySize + SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength);
   1356     SadEntrySize += ALIGN_VARIABLE (SaData->AlgoInfo.EspAlgoInfo.EncKeyLength);
   1357   }
   1358 
   1359   if (SaData->SpdSelector != NULL) {
   1360     SadEntrySize += SadEntrySize + (UINTN)SIZE_OF_SPD_SELECTOR (SaData->SpdSelector);
   1361   }
   1362   SadEntry      = AllocateZeroPool (SadEntrySize);
   1363 
   1364   if (SadEntry == NULL) {
   1365     return EFI_OUT_OF_RESOURCES;
   1366   }
   1367   //
   1368   // Fix the address of Id and Data buffer and copy them, which is
   1369   // continous memory and close to the base structure of SAD entry.
   1370   //
   1371   SadEntry->Id    = (EFI_IPSEC_SA_ID *) ALIGN_POINTER ((SadEntry + 1), sizeof (UINTN));
   1372   SadEntry->Data  = (IPSEC_SAD_DATA *) ALIGN_POINTER ((SadEntry->Id + 1), sizeof (UINTN));
   1373 
   1374   CopyMem (SadEntry->Id, SaId, sizeof (EFI_IPSEC_SA_ID));
   1375 
   1376   SadEntry->Data->Mode                  = SaData->Mode;
   1377   SadEntry->Data->SequenceNumber        = SaData->SNCount;
   1378   SadEntry->Data->AntiReplayWindowSize  = SaData->AntiReplayWindows;
   1379 
   1380   ZeroMem (
   1381     &SadEntry->Data->AntiReplayBitmap,
   1382     sizeof (SadEntry->Data->AntiReplayBitmap)
   1383     );
   1384 
   1385   ZeroMem (
   1386     &SadEntry->Data->AlgoInfo,
   1387     sizeof (EFI_IPSEC_ALGO_INFO)
   1388     );
   1389 
   1390   SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId     = SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId;
   1391   SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength  = SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength;
   1392 
   1393   if (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) {
   1394     SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SadEntry->Data + 1), sizeof (UINTN));
   1395     CopyMem (
   1396       SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
   1397       SaData->AlgoInfo.EspAlgoInfo.AuthKey,
   1398       SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength
   1399       );
   1400   }
   1401 
   1402   if (SaId->Proto == EfiIPsecESP) {
   1403     SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId    = SaData->AlgoInfo.EspAlgoInfo.EncAlgoId;
   1404     SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength = SaData->AlgoInfo.EspAlgoInfo.EncKeyLength;
   1405 
   1406     if (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) {
   1407       SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER (
   1408                                                                ((UINT8 *) (SadEntry->Data + 1) +
   1409                                                                  SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength),
   1410                                                                  sizeof (UINTN)
   1411                                                                  );
   1412       CopyMem (
   1413         SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,
   1414         SaData->AlgoInfo.EspAlgoInfo.EncKey,
   1415         SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength
   1416         );
   1417     }
   1418   }
   1419 
   1420   CopyMem (
   1421     &SadEntry->Data->SaLifetime,
   1422     &SaData->SaLifetime,
   1423     sizeof (EFI_IPSEC_SA_LIFETIME)
   1424     );
   1425 
   1426   SadEntry->Data->PathMTU     = SaData->PathMTU;
   1427   SadEntry->Data->SpdSelector = NULL;
   1428   SadEntry->Data->ESNEnabled  = FALSE;
   1429   SadEntry->Data->ManualSet   = SaData->ManualSet;
   1430 
   1431   //
   1432   // Copy Tunnel Source/Destination Address
   1433   //
   1434   if (SaData->Mode == EfiIPsecTunnel) {
   1435     CopyMem (
   1436       &SadEntry->Data->TunnelDestAddress,
   1437       &SaData->TunnelDestinationAddress,
   1438       sizeof (EFI_IP_ADDRESS)
   1439       );
   1440     CopyMem (
   1441       &SadEntry->Data->TunnelSourceAddress,
   1442       &SaData->TunnelSourceAddress,
   1443       sizeof (EFI_IP_ADDRESS)
   1444       );
   1445   }
   1446   //
   1447   // Update the spd.sas list of the spd entry specified by SAD selector
   1448   //
   1449   SpdList = &mConfigData[IPsecConfigDataTypeSpd];
   1450 
   1451   for (Entry = SpdList->ForwardLink; Entry != SpdList && SaData->SpdSelector != NULL; Entry = Entry->ForwardLink) {
   1452 
   1453     SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
   1454     if (IsSubSpdSelector (
   1455           (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
   1456           (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
   1457           ) && SpdEntry->Data->Action == EfiIPsecActionProtect) {
   1458       SadEntry->Data->SpdEntry = SpdEntry;
   1459       SadEntry->Data->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *)((UINT8 *)SadEntry +
   1460                                                                 SadEntrySize -
   1461                                                                 (UINTN)SIZE_OF_SPD_SELECTOR (SaData->SpdSelector)
   1462                                                                 );
   1463       DuplicateSpdSelector (
   1464        (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector,
   1465        (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
   1466        NULL
   1467        );
   1468       InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd);
   1469     }
   1470   }
   1471   //
   1472   // Insert the new SAD entry.
   1473   //
   1474   InsertTailList (EntryInsertBefore, &SadEntry->List);
   1475 
   1476   return EFI_SUCCESS;
   1477 }
   1478 
   1479 /**
   1480   Set the peer authorization configuration information for the EFI IPsec driver.
   1481 
   1482   The IPsec configuration data has a unique selector/identifier separately to
   1483   identify a data entry.
   1484 
   1485   @param[in]  Selector           Pointer to an entry selector on operated
   1486                                  configuration data specified by DataType.
   1487                                  A NULL Selector causes the entire specified-type
   1488                                  configuration information to be flushed.
   1489   @param[in]  Data               The data buffer to be set. The structure
   1490                                  of the data buffer should be EFI_IPSEC_PAD_DATA.
   1491   @param[in]  Context            Pointer to one entry selector that describes
   1492                                  the expected position the new data entry will
   1493                                  be added. If Context is NULL, the new entry will
   1494                                  be appended the end of database.
   1495 
   1496   @retval EFI_OUT_OF_RESOURCES  The required system resources could not be allocated.
   1497   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1498 
   1499 **/
   1500 EFI_STATUS
   1501 SetPadEntry (
   1502   IN EFI_IPSEC_CONFIG_SELECTOR       *Selector,
   1503   IN VOID                            *Data,
   1504   IN VOID                            *Context OPTIONAL
   1505   )
   1506 {
   1507   IPSEC_PAD_ENTRY     *PadEntry;
   1508   EFI_IPSEC_PAD_ID    *PadId;
   1509   EFI_IPSEC_PAD_DATA  *PadData;
   1510   LIST_ENTRY          *PadList;
   1511   LIST_ENTRY          *Entry;
   1512   LIST_ENTRY          *NextEntry;
   1513   EFI_IPSEC_PAD_ID    *InsertBefore;
   1514   LIST_ENTRY          *EntryInsertBefore;
   1515   UINTN               PadEntrySize;
   1516 
   1517   PadId         = (Selector == NULL) ? NULL : &Selector->PadId;
   1518   PadData       = (Data == NULL) ? NULL : (EFI_IPSEC_PAD_DATA *) Data;
   1519   InsertBefore  = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->PadId;
   1520   PadList       = &mConfigData[IPsecConfigDataTypePad];
   1521 
   1522   //
   1523   // The default behavior is to insert the node ahead of the header.
   1524   //
   1525   EntryInsertBefore = PadList;
   1526 
   1527   //
   1528   // Remove the existed pad entry.
   1529   //
   1530   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, PadList) {
   1531 
   1532     PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
   1533 
   1534     if (PadId == NULL ||
   1535         ComparePadId ((EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id, (EFI_IPSEC_CONFIG_SELECTOR *) PadId)
   1536         ) {
   1537       //
   1538       // Record the existed entry position to keep the original order.
   1539       //
   1540       EntryInsertBefore = PadEntry->List.ForwardLink;
   1541       RemoveEntryList (&PadEntry->List);
   1542 
   1543       FreePool (PadEntry);
   1544     }
   1545   }
   1546   //
   1547   // Return success here if only want to remove the pad entry
   1548   //
   1549   if (PadData == NULL || PadId == NULL) {
   1550     return EFI_SUCCESS;
   1551   }
   1552   //
   1553   // Search the appointed entry position if InsertBefore is not NULL.
   1554   //
   1555   if (InsertBefore != NULL) {
   1556 
   1557     NET_LIST_FOR_EACH (Entry, PadList) {
   1558       PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
   1559 
   1560       if (ComparePadId (
   1561             (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id,
   1562             (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore
   1563             )) {
   1564         EntryInsertBefore = Entry;
   1565         break;
   1566       }
   1567     }
   1568   }
   1569 
   1570   //
   1571   // Do PADDING for different arch.
   1572   //
   1573   PadEntrySize  = ALIGN_VARIABLE (sizeof (IPSEC_PAD_ENTRY));
   1574   PadEntrySize  = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_ID));
   1575   PadEntrySize  = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_DATA));
   1576   PadEntrySize  = ALIGN_VARIABLE (PadEntrySize + (PadData->AuthData != NULL ? PadData->AuthDataSize : 0));
   1577   PadEntrySize += PadData->RevocationData != NULL ? PadData->RevocationDataSize : 0;
   1578 
   1579   PadEntry      = AllocateZeroPool (PadEntrySize);
   1580 
   1581   if (PadEntry == NULL) {
   1582     return EFI_OUT_OF_RESOURCES;
   1583   }
   1584   //
   1585   // Fix the address of Id and Data buffer and copy them, which is
   1586   // continous memory and close to the base structure of pad entry.
   1587   //
   1588   PadEntry->Id    = (EFI_IPSEC_PAD_ID *) ALIGN_POINTER ((PadEntry + 1), sizeof (UINTN));
   1589   PadEntry->Data  = (EFI_IPSEC_PAD_DATA *) ALIGN_POINTER ((PadEntry->Id + 1), sizeof (UINTN));
   1590 
   1591   CopyMem (PadEntry->Id, PadId, sizeof (EFI_IPSEC_PAD_ID));
   1592 
   1593   PadEntry->Data->AuthProtocol  = PadData->AuthProtocol;
   1594   PadEntry->Data->AuthMethod    = PadData->AuthMethod;
   1595   PadEntry->Data->IkeIdFlag     = PadData->IkeIdFlag;
   1596 
   1597   if (PadData->AuthData != NULL) {
   1598     PadEntry->Data->AuthDataSize  = PadData->AuthDataSize;
   1599     PadEntry->Data->AuthData      = (VOID *) ALIGN_POINTER (PadEntry->Data + 1, sizeof (UINTN));
   1600     CopyMem (
   1601       PadEntry->Data->AuthData,
   1602       PadData->AuthData,
   1603       PadData->AuthDataSize
   1604       );
   1605   } else {
   1606     PadEntry->Data->AuthDataSize  = 0;
   1607     PadEntry->Data->AuthData      = NULL;
   1608   }
   1609 
   1610   if (PadData->RevocationData != NULL) {
   1611     PadEntry->Data->RevocationDataSize  = PadData->RevocationDataSize;
   1612     PadEntry->Data->RevocationData      = (VOID *) ALIGN_POINTER (
   1613                                                     ((UINT8 *) (PadEntry->Data + 1) + PadData->AuthDataSize),
   1614                                                     sizeof (UINTN)
   1615                                                     );
   1616     CopyMem (
   1617       PadEntry->Data->RevocationData,
   1618       PadData->RevocationData,
   1619       PadData->RevocationDataSize
   1620       );
   1621   } else {
   1622     PadEntry->Data->RevocationDataSize  = 0;
   1623     PadEntry->Data->RevocationData      = NULL;
   1624   }
   1625   //
   1626   // Insert the new pad entry.
   1627   //
   1628   InsertTailList (EntryInsertBefore, &PadEntry->List);
   1629 
   1630   return EFI_SUCCESS;
   1631 }
   1632 
   1633 /**
   1634   This function lookup the data entry from IPsec SPD. Return the configuration
   1635   value of the specified SPD Entry.
   1636 
   1637   @param[in]      Selector      Pointer to an entry selector which is an identifier
   1638                                 of the SPD entry.
   1639   @param[in, out] DataSize      On output the size of data returned in Data.
   1640   @param[out]     Data          The buffer to return the contents of the IPsec
   1641                                 configuration data. The type of the data buffer
   1642                                 is associated with the DataType.
   1643 
   1644   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1645   @retval EFI_INVALID_PARAMETER Data is NULL and *DataSize is not zero.
   1646   @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
   1647   @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
   1648                                 updated with the size needed to complete the request.
   1649 
   1650 **/
   1651 EFI_STATUS
   1652 GetSpdEntry (
   1653   IN     EFI_IPSEC_CONFIG_SELECTOR       *Selector,
   1654   IN OUT UINTN                           *DataSize,
   1655      OUT VOID                            *Data
   1656   )
   1657 {
   1658   IPSEC_SPD_ENTRY         *SpdEntry;
   1659   IPSEC_SAD_ENTRY         *SadEntry;
   1660   EFI_IPSEC_SPD_SELECTOR  *SpdSel;
   1661   EFI_IPSEC_SPD_DATA      *SpdData;
   1662   LIST_ENTRY              *SpdList;
   1663   LIST_ENTRY              *SpdSas;
   1664   LIST_ENTRY              *Entry;
   1665   UINTN                   RequiredSize;
   1666 
   1667   SpdSel  = &Selector->SpdSelector;
   1668   SpdData = (EFI_IPSEC_SPD_DATA *) Data;
   1669   SpdList = &mConfigData[IPsecConfigDataTypeSpd];
   1670 
   1671   NET_LIST_FOR_EACH (Entry, SpdList) {
   1672     SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
   1673 
   1674     //
   1675     // Find the required SPD entry
   1676     //
   1677     if (CompareSpdSelector (
   1678           (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel,
   1679           (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
   1680           )) {
   1681 
   1682       RequiredSize = IpSecGetSizeOfSpdData (SpdEntry->Data);
   1683       if (*DataSize < RequiredSize) {
   1684         *DataSize = RequiredSize;
   1685         return EFI_BUFFER_TOO_SMALL;
   1686       }
   1687 
   1688       if (SpdData == NULL) {
   1689         return EFI_INVALID_PARAMETER;
   1690       }
   1691 
   1692       *DataSize = RequiredSize;
   1693 
   1694       //
   1695       // Extract and fill all SaId array from the SPD.sas list
   1696       //
   1697       SpdSas              = &SpdEntry->Data->Sas;
   1698       SpdData->SaIdCount  = 0;
   1699 
   1700       NET_LIST_FOR_EACH (Entry, SpdSas) {
   1701         SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry);
   1702         CopyMem (
   1703           &SpdData->SaId[SpdData->SaIdCount++],
   1704           SadEntry->Id,
   1705           sizeof (EFI_IPSEC_SA_ID)
   1706           );
   1707       }
   1708       //
   1709       // Fill the other fields in SPD data.
   1710       //
   1711       CopyMem (SpdData->Name, SpdEntry->Data->Name, sizeof (SpdData->Name));
   1712 
   1713       SpdData->PackageFlag      = SpdEntry->Data->PackageFlag;
   1714       SpdData->TrafficDirection = SpdEntry->Data->TrafficDirection;
   1715       SpdData->Action           = SpdEntry->Data->Action;
   1716 
   1717       if (SpdData->Action != EfiIPsecActionProtect) {
   1718         SpdData->ProcessingPolicy = NULL;
   1719       } else {
   1720         SpdData->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ((UINT8 *) SpdData + sizeof (EFI_IPSEC_SPD_DATA) + (SpdData->SaIdCount - 1) * sizeof (EFI_IPSEC_SA_ID));
   1721 
   1722         IpSecDuplicateProcessPolicy (
   1723           SpdData->ProcessingPolicy,
   1724           SpdEntry->Data->ProcessingPolicy
   1725           );
   1726       }
   1727 
   1728       return EFI_SUCCESS;
   1729     }
   1730   }
   1731 
   1732   return EFI_NOT_FOUND;
   1733 }
   1734 
   1735 /**
   1736   This function lookup the data entry from IPsec SAD. Return the configuration
   1737   value of the specified SAD Entry.
   1738 
   1739   @param[in]      Selector      Pointer to an entry selector which is an identifier
   1740                                 of the SAD entry.
   1741   @param[in, out] DataSize      On output, the size of data returned in Data.
   1742   @param[out]     Data          The buffer to return the contents of the IPsec
   1743                                 configuration data. The type of the data buffer
   1744                                 is associated with the DataType.
   1745 
   1746   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1747   @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
   1748   @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
   1749                                 updated with the size needed to complete the request.
   1750 
   1751 **/
   1752 EFI_STATUS
   1753 GetSadEntry (
   1754   IN     EFI_IPSEC_CONFIG_SELECTOR     *Selector,
   1755   IN OUT UINTN                         *DataSize,
   1756      OUT VOID                          *Data
   1757   )
   1758 {
   1759   IPSEC_SAD_ENTRY   *SadEntry;
   1760   LIST_ENTRY        *Entry;
   1761   LIST_ENTRY        *SadList;
   1762   EFI_IPSEC_SA_ID   *SaId;
   1763   EFI_IPSEC_SA_DATA2 *SaData;
   1764   UINTN             RequiredSize;
   1765 
   1766   SaId    = &Selector->SaId;
   1767   SaData  = (EFI_IPSEC_SA_DATA2 *) Data;
   1768   SadList = &mConfigData[IPsecConfigDataTypeSad];
   1769 
   1770   NET_LIST_FOR_EACH (Entry, SadList) {
   1771     SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
   1772 
   1773     //
   1774     // Find the required SAD entry.
   1775     //
   1776     if (CompareSaId (
   1777          (EFI_IPSEC_CONFIG_SELECTOR *) SaId,
   1778          (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id
   1779          )) {
   1780       //
   1781       // Calculate the required size of the SAD entry.
   1782       // Data Layout is follows:
   1783       // |EFI_IPSEC_SA_DATA
   1784       // |AuthKey
   1785       // |EncryptKey  (Optional)
   1786       // |SpdSelector (Optional)
   1787       //
   1788       RequiredSize  = ALIGN_VARIABLE (sizeof (EFI_IPSEC_SA_DATA2));
   1789 
   1790       if (SaId->Proto == EfiIPsecAH) {
   1791         RequiredSize  = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength);
   1792       } else {
   1793         RequiredSize  = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength);
   1794         RequiredSize  = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength);
   1795       }
   1796 
   1797       if (SadEntry->Data->SpdSelector != NULL) {
   1798         RequiredSize += SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdSelector);
   1799       }
   1800 
   1801       if (*DataSize < RequiredSize) {
   1802         *DataSize = RequiredSize;
   1803         return EFI_BUFFER_TOO_SMALL;
   1804       }
   1805 
   1806       //
   1807       // Fill the data fields of SAD entry.
   1808       //
   1809       *DataSize                 = RequiredSize;
   1810       SaData->Mode              = SadEntry->Data->Mode;
   1811       SaData->SNCount           = SadEntry->Data->SequenceNumber;
   1812       SaData->AntiReplayWindows = SadEntry->Data->AntiReplayWindowSize;
   1813 
   1814       CopyMem (
   1815         &SaData->SaLifetime,
   1816         &SadEntry->Data->SaLifetime,
   1817         sizeof (EFI_IPSEC_SA_LIFETIME)
   1818         );
   1819 
   1820       ZeroMem (
   1821         &SaData->AlgoInfo,
   1822         sizeof (EFI_IPSEC_ALGO_INFO)
   1823         );
   1824 
   1825       if (SaId->Proto == EfiIPsecAH) {
   1826         //
   1827         // Copy AH alogrithm INFO to SaData
   1828         //
   1829         SaData->AlgoInfo.AhAlgoInfo.AuthAlgoId    = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthAlgoId;
   1830         SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength;
   1831         if (SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength != 0) {
   1832           SaData->AlgoInfo.AhAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN));
   1833           CopyMem (
   1834             SaData->AlgoInfo.AhAlgoInfo.AuthKey,
   1835             SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKey,
   1836             SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength
   1837             );
   1838         }
   1839       } else if (SaId->Proto == EfiIPsecESP) {
   1840         //
   1841         // Copy ESP alogrithem INFO to SaData
   1842         //
   1843         SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId     = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId;
   1844         SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength  = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength;
   1845         if (SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) {
   1846           SaData->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN));
   1847           CopyMem (
   1848             SaData->AlgoInfo.EspAlgoInfo.AuthKey,
   1849             SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
   1850             SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength
   1851             );
   1852         }
   1853 
   1854         SaData->AlgoInfo.EspAlgoInfo.EncAlgoId    = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId;
   1855         SaData->AlgoInfo.EspAlgoInfo.EncKeyLength = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength;
   1856 
   1857         if (SaData->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) {
   1858           SaData->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER (
   1859                                                           ((UINT8 *) (SaData + 1) +
   1860                                                             SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength),
   1861                                                             sizeof (UINTN)
   1862                                                             );
   1863           CopyMem (
   1864             SaData->AlgoInfo.EspAlgoInfo.EncKey,
   1865             SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,
   1866             SaData->AlgoInfo.EspAlgoInfo.EncKeyLength
   1867             );
   1868         }
   1869       }
   1870 
   1871       SaData->PathMTU = SadEntry->Data->PathMTU;
   1872 
   1873       //
   1874       // Fill Tunnel Address if it is Tunnel Mode
   1875       //
   1876       if (SadEntry->Data->Mode == EfiIPsecTunnel) {
   1877         CopyMem (
   1878           &SaData->TunnelDestinationAddress,
   1879           &SadEntry->Data->TunnelDestAddress,
   1880           sizeof (EFI_IP_ADDRESS)
   1881           );
   1882         CopyMem (
   1883           &SaData->TunnelSourceAddress,
   1884           &SadEntry->Data->TunnelSourceAddress,
   1885           sizeof (EFI_IP_ADDRESS)
   1886           );
   1887       }
   1888       //
   1889       // Fill the spd selector field of SAD data
   1890       //
   1891       if (SadEntry->Data->SpdSelector != NULL) {
   1892 
   1893         SaData->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *) (
   1894                                 (UINT8 *)SaData +
   1895                                 RequiredSize -
   1896                                 SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdSelector)
   1897                                 );
   1898 
   1899         DuplicateSpdSelector (
   1900           (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
   1901           (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector,
   1902           NULL
   1903           );
   1904 
   1905       } else {
   1906 
   1907         SaData->SpdSelector = NULL;
   1908       }
   1909 
   1910       SaData->ManualSet = SadEntry->Data->ManualSet;
   1911 
   1912       return EFI_SUCCESS;
   1913     }
   1914   }
   1915 
   1916   return EFI_NOT_FOUND;
   1917 }
   1918 
   1919 /**
   1920   This function lookup the data entry from IPsec PAD. Return the configuration
   1921   value of the specified PAD Entry.
   1922 
   1923   @param[in]      Selector      Pointer to an entry selector which is an identifier
   1924                                 of the PAD entry.
   1925   @param[in, out] DataSize      On output the size of data returned in Data.
   1926   @param[out]     Data          The buffer to return the contents of the IPsec
   1927                                 configuration data. The type of the data buffer
   1928                                 is associated with the DataType.
   1929 
   1930   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   1931   @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
   1932   @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
   1933                                 updated with the size needed to complete the request.
   1934 
   1935 **/
   1936 EFI_STATUS
   1937 GetPadEntry (
   1938   IN     EFI_IPSEC_CONFIG_SELECTOR   *Selector,
   1939   IN OUT UINTN                       *DataSize,
   1940      OUT VOID                        *Data
   1941   )
   1942 {
   1943   IPSEC_PAD_ENTRY     *PadEntry;
   1944   LIST_ENTRY          *PadList;
   1945   LIST_ENTRY          *Entry;
   1946   EFI_IPSEC_PAD_ID    *PadId;
   1947   EFI_IPSEC_PAD_DATA  *PadData;
   1948   UINTN               RequiredSize;
   1949 
   1950   PadId   = &Selector->PadId;
   1951   PadData = (EFI_IPSEC_PAD_DATA *) Data;
   1952   PadList = &mConfigData[IPsecConfigDataTypePad];
   1953 
   1954   NET_LIST_FOR_EACH (Entry, PadList) {
   1955     PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
   1956 
   1957     //
   1958     // Find the required pad entry.
   1959     //
   1960     if (ComparePadId (
   1961           (EFI_IPSEC_CONFIG_SELECTOR *) PadId,
   1962           (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id
   1963           )) {
   1964       //
   1965       // Calculate the required size of the pad entry.
   1966       //
   1967       RequiredSize  = ALIGN_VARIABLE (sizeof (EFI_IPSEC_PAD_DATA));
   1968       RequiredSize  = ALIGN_VARIABLE (RequiredSize + PadEntry->Data->AuthDataSize);
   1969       RequiredSize += PadEntry->Data->RevocationDataSize;
   1970 
   1971       if (*DataSize < RequiredSize) {
   1972         *DataSize = RequiredSize;
   1973         return EFI_BUFFER_TOO_SMALL;
   1974       }
   1975       //
   1976       // Fill the data fields of pad entry
   1977       //
   1978       *DataSize             = RequiredSize;
   1979       PadData->AuthProtocol = PadEntry->Data->AuthProtocol;
   1980       PadData->AuthMethod   = PadEntry->Data->AuthMethod;
   1981       PadData->IkeIdFlag    = PadEntry->Data->IkeIdFlag;
   1982 
   1983       //
   1984       // Copy Authentication data.
   1985       //
   1986       if (PadEntry->Data->AuthData != NULL) {
   1987 
   1988         PadData->AuthDataSize = PadEntry->Data->AuthDataSize;
   1989         PadData->AuthData     = (VOID *) ALIGN_POINTER ((PadData + 1), sizeof (UINTN));
   1990         CopyMem (
   1991           PadData->AuthData,
   1992           PadEntry->Data->AuthData,
   1993           PadData->AuthDataSize
   1994           );
   1995       } else {
   1996 
   1997         PadData->AuthDataSize = 0;
   1998         PadData->AuthData     = NULL;
   1999       }
   2000       //
   2001       // Copy Revocation Data.
   2002       //
   2003       if (PadEntry->Data->RevocationData != NULL) {
   2004 
   2005         PadData->RevocationDataSize = PadEntry->Data->RevocationDataSize;
   2006         PadData->RevocationData     = (VOID *) ALIGN_POINTER (
   2007                                                  ((UINT8 *) (PadData + 1) + PadData->AuthDataSize),
   2008                                                   sizeof (UINTN)
   2009                                                   );
   2010         CopyMem (
   2011           PadData->RevocationData,
   2012           PadEntry->Data->RevocationData,
   2013           PadData->RevocationDataSize
   2014           );
   2015       } else {
   2016 
   2017         PadData->RevocationDataSize = 0;
   2018         PadData->RevocationData     = NULL;
   2019       }
   2020 
   2021       return EFI_SUCCESS;
   2022     }
   2023   }
   2024 
   2025   return EFI_NOT_FOUND;
   2026 }
   2027 
   2028 /**
   2029   Copy Source Process Policy to the Destination Process Policy.
   2030 
   2031   @param[in]  Dst                  Pointer to the Source Process Policy.
   2032   @param[in]  Src                  Pointer to the Destination Process Policy.
   2033 
   2034 **/
   2035 VOID
   2036 IpSecDuplicateProcessPolicy (
   2037   IN EFI_IPSEC_PROCESS_POLICY            *Dst,
   2038   IN EFI_IPSEC_PROCESS_POLICY            *Src
   2039   )
   2040 {
   2041   //
   2042   // Firstly copy the structure content itself.
   2043   //
   2044   CopyMem (Dst, Src, sizeof (EFI_IPSEC_PROCESS_POLICY));
   2045 
   2046   //
   2047   // Recursively copy the tunnel option if needed.
   2048   //
   2049   if (Dst->Mode != EfiIPsecTunnel) {
   2050     ASSERT (Dst->TunnelOption == NULL);
   2051   } else {
   2052     Dst->TunnelOption = (EFI_IPSEC_TUNNEL_OPTION *) ALIGN_POINTER ((Dst + 1), sizeof (UINTN));
   2053     CopyMem (
   2054       Dst->TunnelOption,
   2055       Src->TunnelOption,
   2056       sizeof (EFI_IPSEC_TUNNEL_OPTION)
   2057       );
   2058   }
   2059 }
   2060 
   2061 /**
   2062   Calculate the a whole size of EFI_IPSEC_SPD_DATA, which includes the buffer size pointed
   2063   to by the pointer members.
   2064 
   2065   @param[in]  SpdData             Pointer to a specified EFI_IPSEC_SPD_DATA.
   2066 
   2067   @return the whole size the specified EFI_IPSEC_SPD_DATA.
   2068 
   2069 **/
   2070 UINTN
   2071 IpSecGetSizeOfEfiSpdData (
   2072   IN EFI_IPSEC_SPD_DATA               *SpdData
   2073   )
   2074 {
   2075   UINTN Size;
   2076 
   2077   Size = ALIGN_VARIABLE (sizeof (IPSEC_SPD_DATA));
   2078 
   2079   if (SpdData->Action == EfiIPsecActionProtect) {
   2080     Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_PROCESS_POLICY));
   2081 
   2082     if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) {
   2083       Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_TUNNEL_OPTION));
   2084     }
   2085   }
   2086 
   2087   return Size;
   2088 }
   2089 
   2090 /**
   2091   Calculate the a whole size of IPSEC_SPD_DATA which includes the buffer size pointed
   2092   to by the pointer members and the buffer size used by the Sa List.
   2093 
   2094   @param[in]  SpdData       Pointer to the specified IPSEC_SPD_DATA.
   2095 
   2096   @return the whole size of IPSEC_SPD_DATA.
   2097 
   2098 **/
   2099 UINTN
   2100 IpSecGetSizeOfSpdData (
   2101   IN IPSEC_SPD_DATA                   *SpdData
   2102   )
   2103 {
   2104   UINTN       Size;
   2105   LIST_ENTRY  *Link;
   2106 
   2107   Size = sizeof (EFI_IPSEC_SPD_DATA) - sizeof (EFI_IPSEC_SA_ID);
   2108 
   2109   if (SpdData->Action == EfiIPsecActionProtect) {
   2110     Size += sizeof (EFI_IPSEC_PROCESS_POLICY);
   2111 
   2112     if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) {
   2113       Size += sizeof (EFI_IPSEC_TUNNEL_OPTION);
   2114     }
   2115   }
   2116 
   2117   NET_LIST_FOR_EACH (Link, &SpdData->Sas) {
   2118     Size += sizeof (EFI_IPSEC_SA_ID);
   2119   }
   2120 
   2121   return Size;
   2122 }
   2123 
   2124 /**
   2125   Get the IPsec Variable.
   2126 
   2127   Get the all variables which start with the string contained in VaraiableName.
   2128   Since all IPsec related variable store in continual space, those kinds of
   2129   variable can be searched by the EfiGetNextVariableName. Those variables also are
   2130   returned in a continual buffer.
   2131 
   2132   @param[in]      VariableName          Pointer to a specified Variable Name.
   2133   @param[in]      VendorGuid            Pointer to a specified Vendor Guid.
   2134   @param[in]      Attributes            Point to memory location to return the attributes
   2135                                         of variable. If the point is NULL, the parameter
   2136                                         would be ignored.
   2137   @param[in, out] DataSize              As input, point to the maximum size of return
   2138                                         Data-Buffer. As output, point to the actual
   2139                                         size of the returned Data-Buffer.
   2140   @param[in]      Data                  Point to return Data-Buffer.
   2141 
   2142   @retval  EFI_ABORTED           If the Variable size which contained in the variable
   2143                                  structure doesn't match the variable size obtained
   2144                                  from the EFIGetVariable.
   2145   @retval  EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has
   2146                                  been updated with the size needed to complete the request.
   2147   @retval  EFI_SUCCESS           The function completed successfully.
   2148   @retval  others                Other errors found during the variable getting.
   2149 **/
   2150 EFI_STATUS
   2151 IpSecGetVariable (
   2152   IN     CHAR16                       *VariableName,
   2153   IN     EFI_GUID                     *VendorGuid,
   2154   IN     UINT32                       *Attributes, OPTIONAL
   2155   IN OUT UINTN                        *DataSize,
   2156   IN     VOID                         *Data
   2157   )
   2158 {
   2159   EFI_STATUS            Status;
   2160   EFI_GUID              VendorGuidI;
   2161   UINTN                 VariableNameLength;
   2162   CHAR16                *VariableNameI;
   2163   UINTN                 VariableNameISize;
   2164   UINTN                 VariableNameISizeNew;
   2165   UINTN                 VariableIndex;
   2166   UINTN                 VariableCount;
   2167   IP_SEC_VARIABLE_INFO  IpSecVariableInfo;
   2168   UINTN                 DataSizeI;
   2169 
   2170   //
   2171   // The variable name constructor is "VariableName + Info/0001/0002/... + NULL".
   2172   // So the varialbe name is like "VariableNameInfo", "VariableName0001", ...
   2173   // "VariableNameNULL".
   2174   //
   2175   VariableNameLength  = StrLen (VariableName);
   2176   VariableNameISize   = (VariableNameLength + 5) * sizeof (CHAR16);
   2177   VariableNameI       = AllocateZeroPool (VariableNameISize);
   2178   if (VariableNameI == NULL) {
   2179     Status = EFI_OUT_OF_RESOURCES;
   2180     goto ON_EXIT;
   2181   }
   2182 
   2183   //
   2184   // Construct the varible name of ipsecconfig meta data.
   2185   //
   2186   UnicodeSPrint (VariableNameI, VariableNameISize, L"%s%s", VariableName, L"Info");
   2187 
   2188   DataSizeI = sizeof (IpSecVariableInfo);
   2189 
   2190   Status = gRT->GetVariable (
   2191                   VariableNameI,
   2192                   VendorGuid,
   2193                   Attributes,
   2194                   &DataSizeI,
   2195                   &IpSecVariableInfo
   2196                   );
   2197   if (EFI_ERROR (Status)) {
   2198     goto ON_EXIT;
   2199   }
   2200 
   2201   if (*DataSize < IpSecVariableInfo.VariableSize) {
   2202     *DataSize = IpSecVariableInfo.VariableSize;
   2203     Status    = EFI_BUFFER_TOO_SMALL;
   2204     goto ON_EXIT;
   2205   }
   2206 
   2207   VariableCount     = IpSecVariableInfo.VariableCount;
   2208   VariableNameI[0]  = L'\0';
   2209 
   2210   while (VariableCount != 0) {
   2211     //
   2212     // Get the variable name one by one in the variable database.
   2213     //
   2214     VariableNameISizeNew = VariableNameISize;
   2215     Status = gRT->GetNextVariableName (
   2216                     &VariableNameISizeNew,
   2217                     VariableNameI,
   2218                     &VendorGuidI
   2219                     );
   2220     if (Status == EFI_BUFFER_TOO_SMALL) {
   2221       VariableNameI = ReallocatePool (
   2222                         VariableNameISize,
   2223                         VariableNameISizeNew,
   2224                         VariableNameI
   2225                         );
   2226       if (VariableNameI == NULL) {
   2227         Status = EFI_OUT_OF_RESOURCES;
   2228         break;
   2229       }
   2230       VariableNameISize = VariableNameISizeNew;
   2231 
   2232       Status = gRT->GetNextVariableName (
   2233                       &VariableNameISizeNew,
   2234                       VariableNameI,
   2235                       &VendorGuidI
   2236                       );
   2237     }
   2238 
   2239     if (EFI_ERROR (Status)) {
   2240       break;
   2241     }
   2242     //
   2243     // Check whether the current variable is the required "ipsecconfig".
   2244     //
   2245     if (StrnCmp (VariableNameI, VariableName, VariableNameLength) == 0 ||
   2246         CompareGuid (VendorGuid, &VendorGuidI)
   2247         ) {
   2248       //
   2249       // Parse the variable count of the current ipsecconfig data.
   2250       //
   2251       VariableIndex = StrDecimalToUintn (VariableNameI + VariableNameLength);
   2252       if (VariableIndex!= 0 && VariableIndex <= IpSecVariableInfo.VariableCount) {
   2253         //
   2254         // Get the variable size of the current ipsecconfig data.
   2255         //
   2256         DataSizeI = 0;
   2257         Status = gRT->GetVariable (
   2258                         VariableNameI,
   2259                         VendorGuid,
   2260                         Attributes,
   2261                         &DataSizeI,
   2262                         NULL
   2263                         );
   2264         ASSERT (Status == EFI_BUFFER_TOO_SMALL);
   2265         //
   2266         // Validate the variable count and variable size.
   2267         //
   2268         if (VariableIndex != IpSecVariableInfo.VariableCount) {
   2269           //
   2270           // If the varaibe is not the last one, its size should be the max
   2271           // size of the single variable.
   2272           //
   2273           if (DataSizeI != IpSecVariableInfo.SingleVariableSize) {
   2274             return EFI_ABORTED;
   2275           }
   2276         } else {
   2277           if (DataSizeI != IpSecVariableInfo.VariableSize % IpSecVariableInfo.SingleVariableSize) {
   2278             return EFI_ABORTED;
   2279           }
   2280         }
   2281         //
   2282         // Get the variable data of the current ipsecconfig data and
   2283         // store it into user buffer continously.
   2284         //
   2285         Status = gRT->GetVariable (
   2286                         VariableNameI,
   2287                         VendorGuid,
   2288                         Attributes,
   2289                         &DataSizeI,
   2290                         (UINT8 *) Data + (VariableIndex - 1) * IpSecVariableInfo.SingleVariableSize
   2291                         );
   2292         ASSERT_EFI_ERROR (Status);
   2293         VariableCount--;
   2294       }
   2295     }
   2296   }
   2297   //
   2298   // The VariableCount in "VariableNameInfo" varaible should have the correct
   2299   // numbers of variables which name starts with VariableName.
   2300   //
   2301   if (VariableCount != 0) {
   2302     Status = EFI_ABORTED;
   2303   }
   2304 
   2305 ON_EXIT:
   2306   if (VariableNameI != NULL) {
   2307     FreePool (VariableNameI);
   2308   }
   2309   return Status;
   2310 }
   2311 
   2312 /**
   2313   Set the IPsec variables.
   2314 
   2315   Set all IPsec variables which start with the specified variable name. Those variables
   2316   are set one by one.
   2317 
   2318   @param[in]  VariableName  The name of the vendor's variable. It is a
   2319                             Null-Terminated Unicode String.
   2320   @param[in]  VendorGuid    Unify identifier for vendor.
   2321   @param[in]  Attributes    Point to memory location to return the attributes of
   2322                             variable. If the point is NULL, the parameter would be ignored.
   2323   @param[in]  DataSize      The size in bytes of Data-Buffer.
   2324   @param[in]  Data          Points to the content of the variable.
   2325 
   2326   @retval  EFI_SUCCESS      The firmware successfully stored the variable and its data, as
   2327                             defined by the Attributes.
   2328   @retval  others           Storing the variables failed.
   2329 
   2330 **/
   2331 EFI_STATUS
   2332 IpSecSetVariable (
   2333   IN CHAR16                           *VariableName,
   2334   IN EFI_GUID                         *VendorGuid,
   2335   IN UINT32                           Attributes,
   2336   IN UINTN                            DataSize,
   2337   IN VOID                             *Data
   2338   )
   2339 {
   2340   EFI_STATUS            Status;
   2341   CHAR16                *VariableNameI;
   2342   UINTN                 VariableNameSize;
   2343   UINTN                 VariableIndex;
   2344   IP_SEC_VARIABLE_INFO  IpSecVariableInfo;
   2345   UINT64                MaximumVariableStorageSize;
   2346   UINT64                RemainingVariableStorageSize;
   2347   UINT64                MaximumVariableSize;
   2348 
   2349   Status = gRT->QueryVariableInfo (
   2350                   Attributes,
   2351                   &MaximumVariableStorageSize,
   2352                   &RemainingVariableStorageSize,
   2353                   &MaximumVariableSize
   2354                   );
   2355   if (EFI_ERROR (Status)) {
   2356     return Status;
   2357   }
   2358 
   2359   //
   2360   // "VariableName + Info/0001/0002/... + NULL"
   2361   //
   2362   VariableNameSize  = (StrLen (VariableName) + 5) * sizeof (CHAR16);
   2363   VariableNameI     = AllocateZeroPool (VariableNameSize);
   2364 
   2365   if (VariableNameI == NULL) {
   2366     Status = EFI_OUT_OF_RESOURCES;
   2367     goto ON_EXIT;
   2368   }
   2369   //
   2370   // Construct the variable of ipsecconfig general information. Like the total
   2371   // numbers of the Ipsecconfig variables, the total size of all ipsecconfig variables.
   2372   //
   2373   UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%s", VariableName, L"Info");
   2374   MaximumVariableSize -= VariableNameSize;
   2375 
   2376   IpSecVariableInfo.VariableCount       = (UINT32) ((DataSize + (UINTN) MaximumVariableSize - 1) / (UINTN) MaximumVariableSize);
   2377   IpSecVariableInfo.VariableSize        = (UINT32) DataSize;
   2378   IpSecVariableInfo.SingleVariableSize  = (UINT32) MaximumVariableSize;
   2379 
   2380   //
   2381   // Set the variable of ipsecconfig general information.
   2382   //
   2383   Status = gRT->SetVariable (
   2384                   VariableNameI,
   2385                   VendorGuid,
   2386                   Attributes,
   2387                   sizeof (IpSecVariableInfo),
   2388                   &IpSecVariableInfo
   2389                   );
   2390   if (EFI_ERROR (Status)) {
   2391     DEBUG ((DEBUG_ERROR, "Error set ipsecconfig meta data with %r\n", Status));
   2392     goto ON_EXIT;
   2393   }
   2394 
   2395   for (VariableIndex = 0; VariableIndex < IpSecVariableInfo.VariableCount; VariableIndex++) {
   2396     //
   2397     // Construct and set the variable of ipsecconfig data one by one.
   2398     // The index of variable name begin from 0001, and the varaible name
   2399     // likes "VariableName0001", "VaraiableName0002"....
   2400     //
   2401     UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%04d", VariableName, VariableIndex + 1);
   2402     Status = gRT->SetVariable (
   2403                     VariableNameI,
   2404                     VendorGuid,
   2405                     Attributes,
   2406                     (VariableIndex == IpSecVariableInfo.VariableCount - 1) ?
   2407                     (DataSize % (UINTN) MaximumVariableSize) :
   2408                     (UINTN) MaximumVariableSize,
   2409                     (UINT8 *) Data + VariableIndex * (UINTN) MaximumVariableSize
   2410                     );
   2411 
   2412     if (EFI_ERROR (Status)) {
   2413       DEBUG ((DEBUG_ERROR, "Error set ipsecconfig variable data with %r\n", Status));
   2414       goto ON_EXIT;
   2415     }
   2416   }
   2417 
   2418 ON_EXIT:
   2419   if (VariableNameI != NULL) {
   2420     FreePool (VariableNameI);
   2421   }
   2422 
   2423   return Status;
   2424 }
   2425 
   2426 /**
   2427   Return the configuration value for the EFI IPsec driver.
   2428 
   2429   This function lookup the data entry from IPsec database or IKEv2 configuration
   2430   information. The expected data type and unique identification are described in
   2431   DataType and Selector parameters.
   2432 
   2433   @param[in]      This          Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
   2434   @param[in]      DataType      The type of data to retrieve.
   2435   @param[in]      Selector      Pointer to an entry selector that is an identifier of the IPsec
   2436                                 configuration data entry.
   2437   @param[in, out] DataSize      On output the size of data returned in Data.
   2438   @param[out]     Data          The buffer to return the contents of the IPsec configuration data.
   2439                                 The type of the data buffer associated with the DataType.
   2440 
   2441   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   2442   @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
   2443                                 - This is NULL.
   2444                                 - Selector is NULL.
   2445                                 - DataSize is NULL.
   2446                                 - Data is NULL and *DataSize is not zero
   2447   @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
   2448   @retval EFI_UNSUPPORTED       The specified DataType is not supported.
   2449   @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
   2450                                 updated with the size needed to complete the request.
   2451 
   2452 **/
   2453 EFI_STATUS
   2454 EFIAPI
   2455 EfiIpSecConfigGetData (
   2456   IN     EFI_IPSEC_CONFIG_PROTOCOL    *This,
   2457   IN     EFI_IPSEC_CONFIG_DATA_TYPE   DataType,
   2458   IN     EFI_IPSEC_CONFIG_SELECTOR    *Selector,
   2459   IN OUT UINTN                        *DataSize,
   2460      OUT VOID                         *Data
   2461   )
   2462 {
   2463   if (This == NULL || Selector == NULL || DataSize == NULL) {
   2464     return EFI_INVALID_PARAMETER;
   2465   }
   2466 
   2467   if (*DataSize != 0 && Data == NULL) {
   2468     return EFI_INVALID_PARAMETER;
   2469   }
   2470 
   2471   if (DataType >= IPsecConfigDataTypeMaximum) {
   2472     return EFI_UNSUPPORTED;
   2473   }
   2474 
   2475   return mGetPolicyEntry[DataType](Selector, DataSize, Data);
   2476 }
   2477 
   2478 /**
   2479   Set the security association, security policy and peer authorization configuration
   2480   information for the EFI IPsec driver.
   2481 
   2482   This function is used to set the IPsec configuration information of type DataType for
   2483   the EFI IPsec driver.
   2484   The IPsec configuration data has a unique selector/identifier separately to identify
   2485   a data entry. The selector structure depends on DataType's definition.
   2486   Using SetData() with a Data of NULL causes the IPsec configuration data entry identified
   2487   by DataType and Selector to be deleted.
   2488 
   2489   @param[in] This               Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
   2490   @param[in] DataType           The type of data to be set.
   2491   @param[in] Selector           Pointer to an entry selector on operated configuration data
   2492                                 specified by DataType. A NULL Selector causes the entire
   2493                                 specified-type configuration information to be flushed.
   2494   @param[in] Data               The data buffer to be set. The structure of the data buffer is
   2495                                 associated with the DataType.
   2496   @param[in] InsertBefore       Pointer to one entry selector which describes the expected
   2497                                 position the new data entry will be added. If InsertBefore is NULL,
   2498                                 the new entry will be appended to the end of the database.
   2499 
   2500   @retval EFI_SUCCESS           The specified configuration entry data was set successfully.
   2501   @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
   2502                                 - This is NULL.
   2503   @retval EFI_UNSUPPORTED       The specified DataType is not supported.
   2504   @retval EFI_OUT_OF_RESOURCED  The required system resource could not be allocated.
   2505 
   2506 **/
   2507 EFI_STATUS
   2508 EFIAPI
   2509 EfiIpSecConfigSetData (
   2510   IN EFI_IPSEC_CONFIG_PROTOCOL        *This,
   2511   IN EFI_IPSEC_CONFIG_DATA_TYPE       DataType,
   2512   IN EFI_IPSEC_CONFIG_SELECTOR        *Selector,
   2513   IN VOID                             *Data,
   2514   IN EFI_IPSEC_CONFIG_SELECTOR        *InsertBefore OPTIONAL
   2515   )
   2516 {
   2517   EFI_STATUS  Status;
   2518 
   2519   if (This == NULL) {
   2520     return EFI_INVALID_PARAMETER;
   2521   }
   2522 
   2523   if (DataType >= IPsecConfigDataTypeMaximum) {
   2524     return EFI_UNSUPPORTED;
   2525   }
   2526 
   2527   Status = mSetPolicyEntry[DataType](Selector, Data, InsertBefore);
   2528 
   2529   if (!EFI_ERROR (Status) && !mSetBySelf) {
   2530     //
   2531     // Save the updated config data into variable.
   2532     //
   2533     IpSecConfigSave ();
   2534   }
   2535 
   2536   return Status;
   2537 }
   2538 
   2539 /**
   2540   Enumerates the current selector for IPsec configuration data entry.
   2541 
   2542   This function is called multiple times to retrieve the entry Selector in IPsec
   2543   configuration database. On each call to GetNextSelector(), the next entry
   2544   Selector are retrieved into the output interface.
   2545 
   2546   If the entire IPsec configuration database has been iterated, the error
   2547   EFI_NOT_FOUND is returned.
   2548   If the Selector buffer is too small for the next Selector copy, an
   2549   EFI_BUFFER_TOO_SMALL error is returned, and SelectorSize is updated to reflect
   2550   the size of buffer needed.
   2551 
   2552   On the initial call to GetNextSelector() to start the IPsec configuration database
   2553   search, a pointer to the buffer with all zero value is passed in Selector. Calls
   2554   to SetData() between calls to GetNextSelector may produce unpredictable results.
   2555 
   2556   @param[in]      This          Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
   2557   @param[in]      DataType      The type of IPsec configuration data to retrieve.
   2558   @param[in, out] SelectorSize  The size of the Selector buffer.
   2559   @param[in, out] Selector      On input, supplies the pointer to last Selector that was
   2560                                 returned by GetNextSelector().
   2561                                 On output, returns one copy of the current entry Selector
   2562                                 of a given DataType.
   2563 
   2564   @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
   2565   @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
   2566                                 - This is NULL.
   2567                                 - SelectorSize is NULL.
   2568                                 - Selector is NULL.
   2569   @retval EFI_NOT_FOUND         The next configuration data entry was not found.
   2570   @retval EFI_UNSUPPORTED       The specified DataType is not supported.
   2571   @retval EFI_BUFFER_TOO_SMALL  The SelectorSize is too small for the result. This parameter
   2572                                 has been updated with the size needed to complete the search
   2573                                 request.
   2574 
   2575 **/
   2576 EFI_STATUS
   2577 EFIAPI
   2578 EfiIpSecConfigGetNextSelector (
   2579   IN     EFI_IPSEC_CONFIG_PROTOCOL    *This,
   2580   IN     EFI_IPSEC_CONFIG_DATA_TYPE   DataType,
   2581   IN OUT UINTN                        *SelectorSize,
   2582   IN OUT EFI_IPSEC_CONFIG_SELECTOR    *Selector
   2583   )
   2584 {
   2585   LIST_ENTRY                *Link;
   2586   IPSEC_COMMON_POLICY_ENTRY *CommonEntry;
   2587   BOOLEAN                   IsFound;
   2588 
   2589   if (This == NULL || Selector == NULL || SelectorSize == NULL) {
   2590     return EFI_INVALID_PARAMETER;
   2591   }
   2592 
   2593   if (DataType >= IPsecConfigDataTypeMaximum) {
   2594     return EFI_UNSUPPORTED;
   2595   }
   2596 
   2597   IsFound = FALSE;
   2598 
   2599   NET_LIST_FOR_EACH (Link, &mConfigData[DataType]) {
   2600     CommonEntry = BASE_CR (Link, IPSEC_COMMON_POLICY_ENTRY, List);
   2601 
   2602     if (IsFound || (BOOLEAN)(mIsZeroSelector[DataType](Selector))) {
   2603       //
   2604       // If found the appointed entry, then duplicate the next one and return,
   2605       // or if the appointed entry is zero, then return the first one directly.
   2606       //
   2607       return mDuplicateSelector[DataType](Selector, CommonEntry->Selector, SelectorSize);
   2608     } else {
   2609       //
   2610       // Set the flag if find the appointed entry.
   2611       //
   2612       IsFound = mCompareSelector[DataType](Selector, CommonEntry->Selector);
   2613     }
   2614   }
   2615 
   2616   return EFI_NOT_FOUND;
   2617 }
   2618 
   2619 /**
   2620   Register an event that is to be signaled whenever a configuration process on the
   2621   specified IPsec configuration information is done.
   2622 
   2623   The register function is not surpport now and always returns EFI_UNSUPPORTED.
   2624 
   2625   @param[in] This               Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
   2626   @param[in] DataType           The type of data to be registered the event for.
   2627   @param[in] Event              The event to be registered.
   2628 
   2629   @retval EFI_SUCCESS           The event is registered successfully.
   2630   @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
   2631   @retval EFI_ACCESS_DENIED     The Event is already registered for the DataType.
   2632   @retval EFI_UNSUPPORTED       The notify registration is unsupported, or the specified
   2633                                 DataType is not supported.
   2634 
   2635 **/
   2636 EFI_STATUS
   2637 EFIAPI
   2638 EfiIpSecConfigRegisterNotify (
   2639   IN EFI_IPSEC_CONFIG_PROTOCOL        *This,
   2640   IN EFI_IPSEC_CONFIG_DATA_TYPE       DataType,
   2641   IN EFI_EVENT                        Event
   2642   )
   2643 {
   2644   return EFI_UNSUPPORTED;
   2645 }
   2646 
   2647 /**
   2648   Remove the specified event that was previously registered on the specified IPsec
   2649   configuration data.
   2650 
   2651   This function is not support now and alwasy return EFI_UNSUPPORTED.
   2652 
   2653   @param[in] This               Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
   2654   @param[in] DataType           The configuration data type to remove the registered event for.
   2655   @param[in] Event              The event to be unregistered.
   2656 
   2657   @retval EFI_SUCCESS           The event was removed successfully.
   2658   @retval EFI_NOT_FOUND         The Event specified by DataType could not be found in the
   2659                                 database.
   2660   @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
   2661   @retval EFI_UNSUPPORTED       The notify registration is unsupported, or the specified
   2662                                 DataType is not supported.
   2663 
   2664 **/
   2665 EFI_STATUS
   2666 EFIAPI
   2667 EfiIpSecConfigUnregisterNotify (
   2668   IN EFI_IPSEC_CONFIG_PROTOCOL        *This,
   2669   IN EFI_IPSEC_CONFIG_DATA_TYPE       DataType,
   2670   IN EFI_EVENT                        Event
   2671   )
   2672 {
   2673   return EFI_UNSUPPORTED;
   2674 }
   2675 
   2676 /**
   2677   Copy whole data in specified EFI_SIPEC_CONFIG_SELECTOR and the Data to a buffer.
   2678 
   2679   This function is a caller defined function, and it is called by the IpSecVisitConfigData().
   2680   The orignal caller is IpSecConfigSave(), which calls the IpsecVisitConfigData() to
   2681   copy all types of IPsec Config datas into one buffer and store this buffer into firmware in
   2682   the form of several variables.
   2683 
   2684   @param[in]      Type              A specified IPSEC_CONFIG_DATA_TYPE.
   2685   @param[in]      Selector          Points to a EFI_IPSEC_CONFIG_SELECTOR to be copied
   2686                                     to the buffer.
   2687   @param[in]      Data              Points to data to be copied to the buffer. The
   2688                                     Data type is related to the Type.
   2689   @param[in]      SelectorSize      The size of the Selector.
   2690   @param[in]      DataSize          The size of the Data.
   2691   @param[in, out] Buffer            The buffer to store the Selector and Data.
   2692 
   2693   @retval EFI_SUCCESS            Copy the Selector and Data to a buffer successfully.
   2694   @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated.
   2695 
   2696 **/
   2697 EFI_STATUS
   2698 IpSecCopyPolicyEntry (
   2699   IN     EFI_IPSEC_CONFIG_DATA_TYPE   Type,
   2700   IN     EFI_IPSEC_CONFIG_SELECTOR    *Selector,
   2701   IN     VOID                         *Data,
   2702   IN     UINTN                        SelectorSize,
   2703   IN     UINTN                        DataSize,
   2704   IN OUT IPSEC_VARIABLE_BUFFER        *Buffer
   2705   )
   2706 {
   2707   IPSEC_VAR_ITEM_HEADER SelectorHeader;
   2708   IPSEC_VAR_ITEM_HEADER DataHeader;
   2709   UINTN                 EntrySize;
   2710   UINT8                 *TempPoint;
   2711 
   2712   if (Type == IPsecConfigDataTypeSad) {
   2713     //
   2714     // Don't save automatically-generated SA entry into variable.
   2715     //
   2716     if (((EFI_IPSEC_SA_DATA2 *) Data)->ManualSet == FALSE) {
   2717       return EFI_SUCCESS;
   2718     }
   2719   }
   2720   //
   2721   // Increase the capacity size of the buffer if needed.
   2722   //
   2723   EntrySize  = ALIGN_VARIABLE (sizeof (SelectorHeader));
   2724   EntrySize  = ALIGN_VARIABLE (EntrySize + SelectorSize);
   2725   EntrySize  = ALIGN_VARIABLE (EntrySize + sizeof (SelectorHeader));
   2726   EntrySize  = ALIGN_VARIABLE (EntrySize + DataSize);
   2727 
   2728   //EntrySize = SelectorSize + DataSize + 2 * sizeof (SelectorHeader);
   2729   if (Buffer->Capacity - Buffer->Size < EntrySize) {
   2730     //
   2731     // Calculate the required buffer
   2732     //
   2733     Buffer->Capacity += EntrySize;
   2734     TempPoint         = AllocatePool (Buffer->Capacity);
   2735 
   2736     if (TempPoint == NULL) {
   2737       return EFI_OUT_OF_RESOURCES;
   2738     }
   2739     //
   2740     // Copy the old Buffer to new buffer and free the old one.
   2741     //
   2742     CopyMem (TempPoint, Buffer->Ptr, Buffer->Size);
   2743     FreePool (Buffer->Ptr);
   2744 
   2745     Buffer->Ptr       =  TempPoint;
   2746   }
   2747 
   2748   mFixPolicyEntry[Type](Selector, Data);
   2749 
   2750   //
   2751   // Fill the selector header and copy it into buffer.
   2752   //
   2753   SelectorHeader.Type = (UINT8) (Type | IPSEC_VAR_ITEM_HEADER_LOGO_BIT);
   2754   SelectorHeader.Size = (UINT16) SelectorSize;
   2755 
   2756   CopyMem (
   2757     Buffer->Ptr + Buffer->Size,
   2758     &SelectorHeader,
   2759     sizeof (SelectorHeader)
   2760     );
   2761   Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + sizeof (SelectorHeader));
   2762 
   2763   //
   2764   // Copy the selector into buffer.
   2765   //
   2766   CopyMem (
   2767     Buffer->Ptr + Buffer->Size,
   2768     Selector,
   2769     SelectorSize
   2770     );
   2771   Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + SelectorSize);
   2772 
   2773   //
   2774   // Fill the data header and copy it into buffer.
   2775   //
   2776   DataHeader.Type = (UINT8) Type;
   2777   DataHeader.Size = (UINT16) DataSize;
   2778 
   2779   CopyMem (
   2780     Buffer->Ptr + Buffer->Size,
   2781     &DataHeader,
   2782     sizeof (DataHeader)
   2783     );
   2784   Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + sizeof (DataHeader));
   2785   //
   2786   // Copy the data into buffer.
   2787   //
   2788   CopyMem (
   2789     Buffer->Ptr + Buffer->Size,
   2790     Data,
   2791     DataSize
   2792     );
   2793   Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + DataSize);
   2794 
   2795   mUnfixPolicyEntry[Type](Selector, Data);
   2796 
   2797   return EFI_SUCCESS;
   2798 }
   2799 
   2800 /**
   2801   Visit all IPsec Configurations of specified Type and call the caller defined
   2802   interface.
   2803 
   2804   @param[in]  DataType          The specified IPsec Config Data Type.
   2805   @param[in]  Routine           The function defined by the caller.
   2806   @param[in]  Context           The data passed to the Routine.
   2807 
   2808   @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated
   2809   @retval EFI_SUCCESS            This function completed successfully.
   2810 
   2811 **/
   2812 EFI_STATUS
   2813 IpSecVisitConfigData (
   2814   IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
   2815   IN IPSEC_COPY_POLICY_ENTRY    Routine,
   2816   IN VOID                       *Context
   2817   )
   2818 {
   2819   EFI_STATUS                GetNextStatus;
   2820   EFI_STATUS                GetDataStatus;
   2821   EFI_STATUS                RoutineStatus;
   2822   EFI_IPSEC_CONFIG_SELECTOR *Selector;
   2823   VOID                      *Data;
   2824   UINTN                     SelectorSize;
   2825   UINTN                     DataSize;
   2826   UINTN                     SelectorBufferSize;
   2827   UINTN                     DataBufferSize;
   2828   BOOLEAN                   FirstGetNext;
   2829 
   2830   FirstGetNext        = TRUE;
   2831   DataBufferSize      = 0;
   2832   Data                = NULL;
   2833   SelectorBufferSize  = sizeof (EFI_IPSEC_CONFIG_SELECTOR);
   2834   Selector            = AllocateZeroPool (SelectorBufferSize);
   2835 
   2836   if (Selector == NULL) {
   2837     return EFI_OUT_OF_RESOURCES;
   2838   }
   2839 
   2840   while (TRUE) {
   2841     //
   2842     // Get the real size of the selector.
   2843     //
   2844     SelectorSize = SelectorBufferSize;
   2845     GetNextStatus = EfiIpSecConfigGetNextSelector (
   2846                       &mIpSecConfigInstance,
   2847                       DataType,
   2848                       &SelectorSize,
   2849                       Selector
   2850                       );
   2851     if (GetNextStatus == EFI_BUFFER_TOO_SMALL) {
   2852       FreePool (Selector);
   2853       SelectorBufferSize = SelectorSize;
   2854       //
   2855       // Allocate zero pool for the first selector, while store the last
   2856       // selector content for the other selectors.
   2857       //
   2858       if (FirstGetNext) {
   2859         Selector = AllocateZeroPool (SelectorBufferSize);
   2860       } else {
   2861         Selector = AllocateCopyPool (SelectorBufferSize, Selector);
   2862       }
   2863 
   2864       if (Selector == NULL) {
   2865         return EFI_OUT_OF_RESOURCES;
   2866       }
   2867       //
   2868       // Get the content of the selector.
   2869       //
   2870       GetNextStatus = EfiIpSecConfigGetNextSelector (
   2871                         &mIpSecConfigInstance,
   2872                         DataType,
   2873                         &SelectorSize,
   2874                         Selector
   2875                         );
   2876     }
   2877 
   2878     if (EFI_ERROR (GetNextStatus)) {
   2879       break;
   2880     }
   2881 
   2882     FirstGetNext = FALSE;
   2883 
   2884     //
   2885     // Get the real size of the policy entry according to the selector.
   2886     //
   2887     DataSize = DataBufferSize;
   2888     GetDataStatus = EfiIpSecConfigGetData (
   2889                       &mIpSecConfigInstance,
   2890                       DataType,
   2891                       Selector,
   2892                       &DataSize,
   2893                       Data
   2894                       );
   2895     if (GetDataStatus == EFI_BUFFER_TOO_SMALL) {
   2896       if (Data != NULL) {
   2897         FreePool (Data);
   2898       }
   2899 
   2900       DataBufferSize  = DataSize;
   2901       Data            = AllocateZeroPool (DataBufferSize);
   2902 
   2903       if (Data == NULL) {
   2904         return EFI_OUT_OF_RESOURCES;
   2905       }
   2906       //
   2907       // Get the content of the policy entry according to the selector.
   2908       //
   2909       GetDataStatus = EfiIpSecConfigGetData (
   2910                         &mIpSecConfigInstance,
   2911                         DataType,
   2912                         Selector,
   2913                         &DataSize,
   2914                         Data
   2915                         );
   2916     }
   2917 
   2918     if (EFI_ERROR (GetDataStatus)) {
   2919       break;
   2920     }
   2921     //
   2922     // Prepare the buffer of updated policy entry, which is stored in
   2923     // the continous memory, and then save into variable later.
   2924     //
   2925     RoutineStatus = Routine (
   2926                       DataType,
   2927                       Selector,
   2928                       Data,
   2929                       SelectorSize,
   2930                       DataSize,
   2931                       Context
   2932                       );
   2933     if (EFI_ERROR (RoutineStatus)) {
   2934       break;
   2935     }
   2936   }
   2937 
   2938   if (Data != NULL) {
   2939     FreePool (Data);
   2940   }
   2941 
   2942   if (Selector != NULL) {
   2943     FreePool (Selector);
   2944   }
   2945 
   2946   return EFI_SUCCESS;
   2947 }
   2948 
   2949 /**
   2950   This function is the subfunction of  EFIIpSecConfigSetData.
   2951 
   2952   This function call IpSecSetVaraible to set the IPsec Configuration into the firmware.
   2953 
   2954   @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated.
   2955   @retval EFI_SUCCESS            Saved the configration successfully.
   2956   @retval Others                 Other errors were found while obtaining the variable.
   2957 
   2958 **/
   2959 EFI_STATUS
   2960 IpSecConfigSave (
   2961   VOID
   2962   )
   2963 {
   2964   IPSEC_VARIABLE_BUFFER       Buffer;
   2965   EFI_STATUS                  Status;
   2966   EFI_IPSEC_CONFIG_DATA_TYPE  Type;
   2967 
   2968   Buffer.Size     = 0;
   2969   Buffer.Capacity = IPSEC_DEFAULT_VARIABLE_SIZE;
   2970   Buffer.Ptr      = AllocateZeroPool (Buffer.Capacity);
   2971 
   2972   if (Buffer.Ptr == NULL) {
   2973     return EFI_OUT_OF_RESOURCES;
   2974   }
   2975   //
   2976   // For each policy database, prepare the contious buffer to save into variable.
   2977   //
   2978   for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) {
   2979     IpSecVisitConfigData (
   2980       Type,
   2981       (IPSEC_COPY_POLICY_ENTRY) IpSecCopyPolicyEntry,
   2982       &Buffer
   2983       );
   2984   }
   2985   //
   2986   // Save the updated policy database into variable.
   2987   //
   2988   Status = IpSecSetVariable (
   2989              IPSECCONFIG_VARIABLE_NAME,
   2990              &gEfiIpSecConfigProtocolGuid,
   2991              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
   2992              Buffer.Size,
   2993              Buffer.Ptr
   2994              );
   2995 
   2996   FreePool (Buffer.Ptr);
   2997 
   2998   return Status;
   2999 }
   3000 
   3001 /**
   3002   Get the all IPSec configuration variables and store those variables
   3003   to the internal data structure.
   3004 
   3005   This founction is called by IpSecConfigInitialize() which is to intialize the
   3006   IPsecConfiguration Protocol.
   3007 
   3008   @param[in]  Private            Point to IPSEC_PRIVATE_DATA.
   3009 
   3010   @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated
   3011   @retval EFI_SUCCESS            Restore the IPsec Configuration successfully.
   3012   @retval  others                Other errors is found while obtaining the variable.
   3013 
   3014 **/
   3015 EFI_STATUS
   3016 IpSecConfigRestore (
   3017   IN IPSEC_PRIVATE_DATA           *Private
   3018   )
   3019 {
   3020   EFI_STATUS                  Status;
   3021   UINTN                       BufferSize;
   3022   UINT8                       *Buffer;
   3023   IPSEC_VAR_ITEM_HEADER       *Header;
   3024   UINT8                       *Ptr;
   3025   EFI_IPSEC_CONFIG_SELECTOR   *Selector;
   3026   EFI_IPSEC_CONFIG_DATA_TYPE  Type;
   3027   VOID                        *Data;
   3028   UINT8                       Value;
   3029   UINTN                       Size;
   3030 
   3031   Value       = 0;
   3032   Size        = sizeof (Value);
   3033   BufferSize  = 0;
   3034   Buffer      = NULL;
   3035 
   3036   Status = gRT->GetVariable (
   3037                   IPSECCONFIG_STATUS_NAME,
   3038                   &gEfiIpSecConfigProtocolGuid,
   3039                   NULL,
   3040                   &Size,
   3041                   &Value
   3042              );
   3043 
   3044   if (!EFI_ERROR (Status) && Value == IPSEC_STATUS_ENABLED) {
   3045     Private->IpSec.DisabledFlag = FALSE;
   3046   }
   3047   //
   3048   // Get the real size of policy database in variable.
   3049   //
   3050   Status = IpSecGetVariable (
   3051              IPSECCONFIG_VARIABLE_NAME,
   3052              &gEfiIpSecConfigProtocolGuid,
   3053              NULL,
   3054              &BufferSize,
   3055              Buffer
   3056              );
   3057   if (Status == EFI_BUFFER_TOO_SMALL) {
   3058 
   3059     Buffer = AllocateZeroPool (BufferSize);
   3060     if (Buffer == NULL) {
   3061       return EFI_OUT_OF_RESOURCES;
   3062     }
   3063     //
   3064     // Get the content of policy database in variable.
   3065     //
   3066     Status = IpSecGetVariable (
   3067                IPSECCONFIG_VARIABLE_NAME,
   3068                &gEfiIpSecConfigProtocolGuid,
   3069                NULL,
   3070                &BufferSize,
   3071                Buffer
   3072                );
   3073     if (EFI_ERROR (Status)) {
   3074       FreePool (Buffer);
   3075       return Status;
   3076     }
   3077 
   3078     for (Ptr = Buffer; Ptr < Buffer + BufferSize;) {
   3079 
   3080       Header  = (IPSEC_VAR_ITEM_HEADER *) Ptr;
   3081       Type    = (EFI_IPSEC_CONFIG_DATA_TYPE) (Header->Type & IPSEC_VAR_ITEM_HEADER_CONTENT_BIT);
   3082       ASSERT (((Header->Type & 0x80) == IPSEC_VAR_ITEM_HEADER_LOGO_BIT) && (Type < IPsecConfigDataTypeMaximum));
   3083 
   3084       Selector  = (EFI_IPSEC_CONFIG_SELECTOR *) ALIGN_POINTER (Header + 1, sizeof (UINTN));
   3085       Header    = (IPSEC_VAR_ITEM_HEADER *) ALIGN_POINTER (
   3086                                               (UINT8 *) Selector + Header->Size,
   3087                                               sizeof (UINTN)
   3088                                               );
   3089       ASSERT (Header->Type == Type);
   3090 
   3091       Data = ALIGN_POINTER (Header + 1, sizeof (UINTN));
   3092 
   3093       mUnfixPolicyEntry[Type](Selector, Data);
   3094 
   3095       //
   3096       // Update each policy entry according to the content in variable.
   3097       //
   3098       mSetBySelf = TRUE;
   3099       Status = EfiIpSecConfigSetData (
   3100                  &Private->IpSecConfig,
   3101                  Type,
   3102                  Selector,
   3103                  Data,
   3104                  NULL
   3105                  );
   3106       mSetBySelf = FALSE;
   3107 
   3108       if (EFI_ERROR (Status)) {
   3109         FreePool (Buffer);
   3110         return Status;
   3111       }
   3112 
   3113       Ptr =  ALIGN_POINTER ((UINT8 *) Data + Header->Size, sizeof (UINTN));
   3114     }
   3115 
   3116     FreePool (Buffer);
   3117   }
   3118 
   3119   return EFI_SUCCESS;
   3120 }
   3121 
   3122 /**
   3123   Install and Initialize IPsecConfig protocol
   3124 
   3125   @param[in, out]  Private   Pointer to IPSEC_PRIVATE_DATA. After this function finish,
   3126                              the pointer of IPsecConfig Protocol implementation will copy
   3127                              into its IPsecConfig member.
   3128 
   3129   @retval     EFI_SUCCESS    Initialized the IPsecConfig Protocol successfully.
   3130   @retval     Others         Initializing the IPsecConfig Protocol failed.
   3131 **/
   3132 EFI_STATUS
   3133 IpSecConfigInitialize (
   3134   IN OUT IPSEC_PRIVATE_DATA        *Private
   3135   )
   3136 {
   3137   EFI_IPSEC_CONFIG_DATA_TYPE  Type;
   3138 
   3139   CopyMem (
   3140     &Private->IpSecConfig,
   3141     &mIpSecConfigInstance,
   3142     sizeof (EFI_IPSEC_CONFIG_PROTOCOL)
   3143     );
   3144 
   3145   //
   3146   // Initialize the list head of policy database.
   3147   //
   3148   for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) {
   3149     InitializeListHead (&mConfigData[Type]);
   3150   }
   3151   //
   3152   // Restore the content of policy database according to the variable.
   3153   //
   3154   IpSecConfigRestore (Private);
   3155 
   3156   return gBS->InstallMultipleProtocolInterfaces (
   3157                 &Private->Handle,
   3158                 &gEfiIpSecConfigProtocolGuid,
   3159                 &Private->IpSecConfig,
   3160                 NULL
   3161                 );
   3162 }
   3163