Home | History | Annotate | Download | only in IScsiDxe
      1 /** @file
      2   Implementation for iSCSI Boot Firmware Table publication.
      3 
      4 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "IScsiImpl.h"
     16 
     17 BOOLEAN mIbftInstalled = FALSE;
     18 UINTN   mTableKey;
     19 
     20 /**
     21   Initialize the header of the iSCSI Boot Firmware Table.
     22 
     23   @param[out]  Header     The header of the iSCSI Boot Firmware Table.
     24   @param[in]   OemId      The OEM ID.
     25   @param[in]   OemTableId The OEM table ID for the iBFT.
     26 **/
     27 VOID
     28 IScsiInitIbfTableHeader (
     29   OUT EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER   *Header,
     30   IN  UINT8                                       *OemId,
     31   IN  UINT64                                      *OemTableId
     32   )
     33 {
     34   ZeroMem (Header, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER));
     35 
     36   Header->Signature = EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE;
     37   Header->Length    = IBFT_HEAP_OFFSET;
     38   Header->Revision  = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_REVISION;
     39   Header->Checksum  = 0;
     40 
     41   CopyMem (Header->OemId, OemId, sizeof (Header->OemId));
     42   CopyMem (&Header->OemTableId, OemTableId, sizeof (UINT64));
     43 }
     44 
     45 /**
     46   Initialize the control section of the iSCSI Boot Firmware Table.
     47 
     48   @param[in]  Table       The ACPI table.
     49   @param[in]  HandleCount The number of the handles associated with iSCSI sessions, it's
     50                           equal to the number of iSCSI sessions.
     51 **/
     52 VOID
     53 IScsiInitControlSection (
     54   IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER  *Table,
     55   IN UINTN                                      HandleCount
     56   )
     57 {
     58   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE  *Control;
     59   UINTN                                                 NumOffset;
     60 
     61   Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
     62 
     63   ZeroMem (Control, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE));
     64 
     65   Control->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_ID;
     66   Control->Header.Version     = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_VERSION;
     67   Control->Header.Length      = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE);
     68 
     69   //
     70   // Each session occupies two offsets, one for the NIC section,
     71   // the other for the Target section.
     72   //
     73   NumOffset = 2 * HandleCount;
     74   if (NumOffset > 4) {
     75     //
     76     // Need expand the control section if more than 2 NIC/Target sections
     77     // exist.
     78     //
     79     Control->Header.Length = (UINT16) (Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));
     80   }
     81 }
     82 
     83 /**
     84   Add one item into the heap.
     85 
     86   @param[in, out]  Heap  On input, the current address of the heap; On output, the address of
     87                          the heap after the item is added.
     88   @param[in]       Data  The data to add into the heap.
     89   @param[in]       Len   Length of the Data in byte.
     90 **/
     91 VOID
     92 IScsiAddHeapItem (
     93   IN OUT UINT8  **Heap,
     94   IN     VOID   *Data,
     95   IN     UINTN  Len
     96   )
     97 {
     98   //
     99   // Add one byte for the NULL delimiter.
    100   //
    101   *Heap -= Len + 1;
    102 
    103   CopyMem (*Heap, Data, Len);
    104   *(*Heap + Len) = 0;
    105 }
    106 
    107 /**
    108   Fill the Initiator section of the iSCSI Boot Firmware Table.
    109 
    110   @param[in]       Table    The ACPI table.
    111   @param[in, out]  Heap     The heap.
    112   @param[in]       Handle   The handle associated with the iSCSI session.
    113 **/
    114 VOID
    115 IScsiFillInitiatorSection (
    116   IN     EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER  *Table,
    117   IN OUT UINT8                                      **Heap,
    118   IN     EFI_HANDLE                                 Handle
    119   )
    120 {
    121   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE    *Control;
    122   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE  *Initiator;
    123   ISCSI_DRIVER_DATA                                       *DriverData;
    124   ISCSI_SESSION                                           *Session;
    125   ISCSI_PRIVATE_PROTOCOL                                  *IScsiIdentifier;
    126   EFI_STATUS                                              Status;
    127 
    128   Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
    129 
    130   //
    131   // Initiator section immediately follows the control section.
    132   //
    133   Initiator = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *) ((UINT8 *) Control + IBFT_ROUNDUP (Control->Header.Length));
    134 
    135   Control->InitiatorOffset = (UINT16) ((UINTN) Initiator - (UINTN) Table);
    136 
    137   ZeroMem (Initiator, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE));
    138 
    139   Initiator->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_ID;
    140   Initiator->Header.Version     = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_VERSION;
    141   Initiator->Header.Length      = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE);
    142   Initiator->Header.Flags       = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BLOCK_VALID | EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BOOT_SELECTED;
    143 
    144   //
    145   // Get the identifier from the handle.
    146   //
    147   Status = gBS->HandleProtocol (Handle, &gEfiCallerIdGuid, (VOID **) &IScsiIdentifier);
    148   if (EFI_ERROR (Status)) {
    149     ASSERT (FALSE);
    150     return ;
    151   }
    152 
    153   DriverData  = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
    154   Session     = &DriverData->Session;
    155 
    156   //
    157   // Fill the iSCSI Initiator Name into the heap.
    158   //
    159   IScsiAddHeapItem (Heap, Session->InitiatorName, Session->InitiatorNameLength - 1);
    160 
    161   Initiator->IScsiNameLength  = (UINT16) (Session->InitiatorNameLength - 1);
    162   Initiator->IScsiNameOffset  = (UINT16) ((UINTN) *Heap - (UINTN) Table);
    163 }
    164 
    165 /**
    166   Map the v4 IP address into v6 IP address.
    167 
    168   @param[in]   V4 The v4 IP address.
    169   @param[out]  V6 The v6 IP address.
    170 **/
    171 VOID
    172 IScsiMapV4ToV6Addr (
    173   IN  EFI_IPv4_ADDRESS *V4,
    174   OUT EFI_IPv6_ADDRESS *V6
    175   )
    176 {
    177   UINTN Index;
    178 
    179   ZeroMem (V6, sizeof (EFI_IPv6_ADDRESS));
    180 
    181   V6->Addr[10]  = 0xff;
    182   V6->Addr[11]  = 0xff;
    183 
    184   for (Index = 0; Index < 4; Index++) {
    185     V6->Addr[12 + Index] = V4->Addr[Index];
    186   }
    187 }
    188 
    189 /**
    190   Get the NIC's PCI location and return it according to the composited
    191   format defined in iSCSI Boot Firmware Table.
    192 
    193   @param[in]  Controller  The handle of the controller.
    194 
    195   @return UINT16          The composited representation of the NIC PCI location.
    196   @retval 0               Other errors as indicated.
    197 **/
    198 UINT16
    199 IScsiGetNICPciLocation (
    200   IN EFI_HANDLE  Controller
    201   )
    202 {
    203   EFI_STATUS                Status;
    204   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    205   EFI_HANDLE                PciIoHandle;
    206   EFI_PCI_IO_PROTOCOL       *PciIo;
    207   UINTN                     Segment;
    208   UINTN                     Bus;
    209   UINTN                     Device;
    210   UINTN                     Function;
    211 
    212   Status = gBS->HandleProtocol (
    213                   Controller,
    214                   &gEfiDevicePathProtocolGuid,
    215                   (VOID **)&DevicePath
    216                   );
    217   if (EFI_ERROR (Status)) {
    218     return 0;
    219   }
    220 
    221   Status = gBS->LocateDevicePath (
    222                   &gEfiPciIoProtocolGuid,
    223                   &DevicePath,
    224                   &PciIoHandle
    225                   );
    226   if (EFI_ERROR (Status)) {
    227     return 0;
    228   }
    229 
    230   Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo);
    231   if (EFI_ERROR (Status)) {
    232     return 0;
    233   }
    234 
    235   Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
    236   if (EFI_ERROR (Status)) {
    237     return 0;
    238   }
    239 
    240   return (UINT16) ((Bus << 8) | (Device << 3) | Function);
    241 }
    242 
    243 /**
    244   Fill the NIC and target sections in iSCSI Boot Firmware Table.
    245 
    246   @param[in]       Table       The buffer of the ACPI table.
    247   @param[in, out]  Heap        The heap buffer used to store the variable length parameters such as iSCSI name.
    248   @param[in]       HandleCount Count The number of handles having iSCSI private protocol installed.
    249   @param[in]       Handles     The handle buffer.
    250 **/
    251 VOID
    252 IScsiFillNICAndTargetSections (
    253   IN     EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER  *Table,
    254   IN OUT UINT8                                      **Heap,
    255   IN     UINTN                                      HandleCount,
    256   IN     EFI_HANDLE                                 *Handles
    257   )
    258 {
    259   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE  *Control;
    260   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE      *Nic;
    261   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE   *Target;
    262   ISCSI_DRIVER_DATA                                     *DriverData;
    263   ISCSI_SESSION_CONFIG_DATA                             *SessionConfigData;
    264   ISCSI_CHAP_AUTH_CONFIG_NVDATA                         *AuthConfig;
    265   UINT16                                                *SectionOffset;
    266   UINTN                                                 Index;
    267   UINT16                                                Length;
    268   EFI_MAC_ADDRESS                                       MacAddress;
    269   UINTN                                                 HwAddressSize;
    270   ISCSI_PRIVATE_PROTOCOL                                *IScsiIdentifier;
    271   EFI_STATUS                                            Status;
    272 
    273   //
    274   // Get the offset of the first Nic and Target section.
    275   //
    276   Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
    277   Nic     = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Table +
    278           Control->InitiatorOffset + IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE)));
    279   Target  = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
    280           IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
    281 
    282   SectionOffset = &Control->NIC0Offset;
    283 
    284   for (Index = 0; Index < HandleCount; Index++) {
    285     Status = gBS->HandleProtocol (Handles[Index], &gEfiCallerIdGuid, (VOID **)&IScsiIdentifier);
    286     if (EFI_ERROR (Status)) {
    287       ASSERT (FALSE);
    288       return ;
    289     }
    290 
    291     DriverData        = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
    292     SessionConfigData = &DriverData->Session.ConfigData;
    293     AuthConfig        = &DriverData->Session.AuthData.AuthConfig;
    294 
    295     //
    296     // Fill the Nic section.
    297     //
    298     ZeroMem (Nic, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE));
    299 
    300     Nic->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_ID;
    301     Nic->Header.Version     = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_VERSION;
    302     Nic->Header.Length      = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE);
    303     Nic->Header.Index       = (UINT8) Index;
    304     Nic->Header.Flags       = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BLOCK_VALID |
    305                             EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BOOT_SELECTED |
    306                             EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_GLOBAL;
    307 
    308     //
    309     // Get the subnet mask prefix length.
    310     //
    311     Nic->SubnetMaskPrefixLength = IScsiGetSubnetMaskPrefixLength (&SessionConfigData->NvData.SubnetMask);
    312 
    313     if (SessionConfigData->NvData.InitiatorInfoFromDhcp) {
    314       Nic->Origin = IpPrefixOriginDhcp;
    315     } else {
    316       Nic->Origin = IpPrefixOriginManual;
    317     }
    318     //
    319     // Map the various v4 addresses into v6 addresses.
    320     //
    321     IScsiMapV4ToV6Addr (&SessionConfigData->NvData.LocalIp, &Nic->Ip);
    322     IScsiMapV4ToV6Addr (&SessionConfigData->NvData.Gateway, &Nic->Gateway);
    323     IScsiMapV4ToV6Addr (&SessionConfigData->PrimaryDns, &Nic->PrimaryDns);
    324     IScsiMapV4ToV6Addr (&SessionConfigData->SecondaryDns, &Nic->SecondaryDns);
    325     IScsiMapV4ToV6Addr (&SessionConfigData->DhcpServer, &Nic->DhcpServer);
    326 
    327     Nic->VLanTag = NetLibGetVlanId (DriverData->Controller);
    328 
    329     Status = NetLibGetMacAddress (DriverData->Controller, &MacAddress, &HwAddressSize);
    330     ASSERT (Status == EFI_SUCCESS);
    331     CopyMem (Nic->Mac, MacAddress.Addr, sizeof (Nic->Mac));
    332 
    333     //
    334     // Get the PCI location of the Nic.
    335     //
    336     Nic->PciLocation  = IScsiGetNICPciLocation (DriverData->Controller);
    337 
    338     *SectionOffset    = (UINT16) ((UINTN) Nic - (UINTN) Table);
    339     SectionOffset++;
    340 
    341     //
    342     // Fill the Target section.
    343     //
    344     ZeroMem (Target, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE));
    345 
    346     Target->Header.StructureId  = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID;
    347     Target->Header.Version      = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION;
    348     Target->Header.Length       = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE);
    349     Target->Header.Index        = (UINT8) Index;
    350     Target->Header.Flags        = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BLOCK_VALID | EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BOOT_SELECTED;
    351     Target->Port                = SessionConfigData->NvData.TargetPort;
    352     Target->NicIndex            = (UINT8) Index;
    353 
    354     if (AuthConfig->CHAPType == ISCSI_CHAP_NONE) {
    355       Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_NO_CHAP;
    356     } if (AuthConfig->CHAPType == ISCSI_CHAP_UNI) {
    357       Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_CHAP;
    358     } else if (AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL) {
    359       Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP;
    360     }
    361 
    362     IScsiMapV4ToV6Addr (&SessionConfigData->NvData.TargetIp, &Target->Ip);
    363     CopyMem (Target->BootLun, SessionConfigData->NvData.BootLun, sizeof (Target->BootLun));
    364 
    365     //
    366     // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.
    367     //
    368     Length = (UINT16) AsciiStrLen (SessionConfigData->NvData.TargetName);
    369     IScsiAddHeapItem (Heap, SessionConfigData->NvData.TargetName, Length);
    370 
    371     Target->IScsiNameLength = Length;
    372     Target->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
    373 
    374     if (Target->CHAPType != EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_NO_CHAP) {
    375       //
    376       // CHAP Name
    377       //
    378       Length = (UINT16) AsciiStrLen (AuthConfig->CHAPName);
    379       IScsiAddHeapItem (Heap, AuthConfig->CHAPName, Length);
    380       Target->CHAPNameLength  = Length;
    381       Target->CHAPNameOffset  = (UINT16) ((UINTN) *Heap - (UINTN) Table);
    382 
    383       //
    384       // CHAP Secret
    385       //
    386       Length = (UINT16) AsciiStrLen (AuthConfig->CHAPSecret);
    387       IScsiAddHeapItem (Heap, AuthConfig->CHAPSecret, Length);
    388       Target->CHAPSecretLength  = Length;
    389       Target->CHAPSecretOffset  = (UINT16) ((UINTN) *Heap - (UINTN) Table);
    390 
    391       if (Target->CHAPType == EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP) {
    392         //
    393         // Reverse CHAP Name
    394         //
    395         Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPName);
    396         IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPName, Length);
    397         Target->ReverseCHAPNameLength = Length;
    398         Target->ReverseCHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
    399 
    400         //
    401         // Reverse CHAP Secret
    402         //
    403         Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPSecret);
    404         IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPSecret, Length);
    405         Target->ReverseCHAPSecretLength = Length;
    406         Target->ReverseCHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
    407       }
    408     }
    409 
    410     *SectionOffset = (UINT16) ((UINTN) Target - (UINTN) Table);
    411     SectionOffset++;
    412 
    413     //
    414     // Advance to the next NIC/Target pair
    415     //
    416     Nic    = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Target +
    417            IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE)));
    418     Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
    419            IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
    420   }
    421 }
    422 
    423 /**
    424   Publish and remove the iSCSI Boot Firmware Table according to the iSCSI
    425   session status.
    426 **/
    427 VOID
    428 IScsiPublishIbft (
    429   VOID
    430   )
    431 {
    432   EFI_STATUS                                Status;
    433   EFI_ACPI_TABLE_PROTOCOL                   *AcpiTableProtocol;
    434   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table;
    435   UINTN                                     HandleCount;
    436   EFI_HANDLE                                *HandleBuffer;
    437   UINT8                                     *Heap;
    438   UINT8                                     Checksum;
    439   UINTN                                         Index;
    440   EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp;
    441   EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt;
    442 
    443   Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);
    444   if (EFI_ERROR (Status)) {
    445     return ;
    446   }
    447 
    448 
    449   //
    450   // Find ACPI table RSD_PTR from system table
    451   //
    452   for (Index = 0, Rsdp = NULL; Index < gST->NumberOfTableEntries; Index++) {
    453     if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid) ||
    454       CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid) ||
    455       CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpiTableGuid)
    456       ) {
    457       //
    458       // A match was found.
    459       //
    460       Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) gST->ConfigurationTable[Index].VendorTable;
    461       break;
    462     }
    463   }
    464 
    465   if (Rsdp == NULL) {
    466     return ;
    467   } else {
    468     Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;
    469   }
    470 
    471 
    472   if (mIbftInstalled) {
    473     Status = AcpiTableProtocol->UninstallAcpiTable (
    474                                   AcpiTableProtocol,
    475                                   mTableKey
    476                                   );
    477     if (EFI_ERROR (Status)) {
    478       return ;
    479     }
    480     mIbftInstalled = FALSE;
    481   }
    482 
    483   //
    484   // Get all iSCSI private protocols.
    485   //
    486   Status = gBS->LocateHandleBuffer (
    487                   ByProtocol,
    488                   &gEfiCallerIdGuid,
    489                   NULL,
    490                   &HandleCount,
    491                   &HandleBuffer
    492                   );
    493   if (EFI_ERROR (Status)) {
    494     return ;
    495   }
    496   //
    497   // Allocate 4k bytes to hold the ACPI table.
    498   //
    499   Table = AllocateZeroPool (IBFT_MAX_SIZE);
    500   if (Table == NULL) {
    501     return ;
    502   }
    503 
    504   Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;
    505 
    506   //
    507   // Fill in the various section of the iSCSI Boot Firmware Table.
    508   //
    509   IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId);
    510   IScsiInitControlSection (Table, HandleCount);
    511   IScsiFillInitiatorSection (Table, &Heap, HandleBuffer[0]);
    512   IScsiFillNICAndTargetSections (Table, &Heap, HandleCount, HandleBuffer);
    513 
    514   Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length);
    515   Table->Checksum = Checksum;
    516 
    517   FreePool (HandleBuffer);
    518 
    519   //
    520   // Install or update the iBFT table.
    521   //
    522   Status = AcpiTableProtocol->InstallAcpiTable (
    523                                 AcpiTableProtocol,
    524                                 Table,
    525                                 Table->Length,
    526                                 &mTableKey
    527                                 );
    528   if (EFI_ERROR(Status)) {
    529     return;
    530   }
    531 
    532   mIbftInstalled = TRUE;
    533   FreePool (Table);
    534 }
    535