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