]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/IScsiIbft.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiIbft.c
1 /** @file
2 Implementation for iSCSI Boot Firmware Table publication.
3
4 Copyright (c) 2004 - 2018, 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 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 }