• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
IScsiInitIbfTableHeader(OUT EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER * Header,IN UINT8 * OemId,IN UINT64 * OemTableId)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
IScsiInitControlSection(IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER * Table,IN UINTN HandleCount)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
IScsiAddHeapItem(IN OUT UINT8 ** Heap,IN VOID * Data,IN UINTN Len)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
IScsiFillInitiatorSection(IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER * Table,IN OUT UINT8 ** Heap,IN EFI_HANDLE Handle)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
IScsiMapV4ToV6Addr(IN EFI_IPv4_ADDRESS * V4,OUT EFI_IPv6_ADDRESS * V6)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
IScsiGetNICPciLocation(IN EFI_HANDLE Controller)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
IScsiFillNICAndTargetSections(IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER * Table,IN OUT UINT8 ** Heap,IN UINTN HandleCount,IN EFI_HANDLE * Handles)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
IScsiPublishIbft(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