1/** @file
2  Implementation for iSCSI Boot Firmware Table publication.
3
4Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution.  The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "IScsiImpl.h"
16
17BOOLEAN mIbftInstalled = FALSE;
18UINTN   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**/
27VOID
28IScsiInitIbfTableHeader (
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**/
52VOID
53IScsiInitControlSection (
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**/
91VOID
92IScsiAddHeapItem (
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**/
114VOID
115IScsiFillInitiatorSection (
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**/
171VOID
172IScsiMapV4ToV6Addr (
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**/
198UINT16
199IScsiGetNICPciLocation (
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**/
251VOID
252IScsiFillNICAndTargetSections (
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**/
427VOID
428IScsiPublishIbft (
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  EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp;
440  EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt;
441  EFI_ACPI_DESCRIPTION_HEADER                   *Xsdt;
442
443  Rsdt = NULL;
444  Xsdt = NULL;
445
446  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);
447  if (EFI_ERROR (Status)) {
448    return ;
449  }
450
451
452  //
453  // Find ACPI table RSD_PTR from system table
454  //
455  Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **) &Rsdp);
456  if (EFI_ERROR (Status)) {
457    Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **) &Rsdp);
458  }
459
460  if (EFI_ERROR (Status) || (Rsdp == NULL)) {
461    return ;
462  } else if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION && Rsdp->XsdtAddress != 0) {
463    Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;
464  } else if (Rsdp->RsdtAddress != 0) {
465    Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;
466  }
467
468  if ((Xsdt == NULL) && (Rsdt == NULL)) {
469    return ;
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  if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) {
510    IScsiInitIbfTableHeader (Table, Xsdt->OemId, &Xsdt->OemTableId);
511  } else {
512    IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId);
513  }
514
515  IScsiInitControlSection (Table, HandleCount);
516  IScsiFillInitiatorSection (Table, &Heap, HandleBuffer[0]);
517  IScsiFillNICAndTargetSections (Table, &Heap, HandleCount, HandleBuffer);
518
519  Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length);
520  Table->Checksum = Checksum;
521
522  FreePool (HandleBuffer);
523
524  //
525  // Install or update the iBFT table.
526  //
527  Status = AcpiTableProtocol->InstallAcpiTable (
528                                AcpiTableProtocol,
529                                Table,
530                                Table->Length,
531                                &mTableKey
532                                );
533  if (EFI_ERROR(Status)) {
534    return;
535  }
536
537  mIbftInstalled = TRUE;
538  FreePool (Table);
539}
540