]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IScsiDxe/IScsiIbft.c
1. Add EFI_COMPONENT_NAME2_PROTOCOL.GetControllerName() support.
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiIbft.c
CommitLineData
4c5a5e0c 1/** @file\r
2 Implementation for iSCSI Boot Firmware Table publication.\r
3\r
75dce340 4Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
4c5a5e0c 5This 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 @param[in] OemId The OEM ID.\r
25 @param[in] OemTableId The OEM table ID for the iBFT.\r
26\r
27**/\r
28VOID\r
29IScsiInitIbfTableHeader (\r
30 OUT EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Header,\r
31 IN UINT8 *OemId,\r
32 IN UINT64 *OemTableId\r
33 )\r
34{\r
35 Header->Signature = EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE;\r
36 Header->Length = IBFT_HEAP_OFFSET;\r
37 Header->Revision = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_REVISION;\r
38 Header->Checksum = 0;\r
39\r
40 CopyMem (Header->OemId, OemId, sizeof (Header->OemId));\r
41 CopyMem (&Header->OemTableId, OemTableId, sizeof (UINT64));\r
42}\r
43\r
44\r
45/**\r
46 Initialize the control section of the iSCSI Boot Firmware Table.\r
47\r
48 @param[in] Table The ACPI table.\r
49\r
50**/\r
51VOID\r
52IScsiInitControlSection (\r
53 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table\r
54 )\r
55{\r
56 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;\r
57 UINTN NumOffset;\r
58\r
59 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);\r
60\r
61 Control->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_ID;\r
62 Control->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_VERSION;\r
63 Control->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE);\r
64\r
65 //\r
66 // If in multipathing mode, enable the Boot Failover Flag.\r
67 // If in single path mode, disable it. Mix-model is not allowed.\r
68 //\r
69 // BUGBUG: if Boot Failover Flag is set to 1, the OS installer cannot\r
70 // find the iSCSI mapped disk. So still keep not set for single path mode.\r
71 //\r
72 if (mPrivate->EnableMpio) {\r
73 Control->Header.Flags = 0;\r
74 NumOffset = 2 * (mPrivate->MpioCount - mPrivate->Krb5MpioCount);\r
75 } else {\r
76 NumOffset = 2 * mPrivate->ValidSinglePathCount;\r
77 }\r
78\r
79 //\r
80 // Each attempt occupies two offsets: one for the NIC section;\r
81 // the other for the Target section.\r
82 //\r
83 if (NumOffset > 4) {\r
84 //\r
85 // Need expand the control section if more than 2 NIC/Target attempts\r
86 // exist.\r
87 //\r
88 Control->Header.Length = (UINT16) (Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));\r
89 }\r
90}\r
91\r
92\r
93/**\r
94 Add one item into the heap.\r
95\r
96 @param[in, out] Heap On input, the current address of the heap. On output, the address of\r
97 the heap after the item is added.\r
98 @param[in] Data The data to add into the heap.\r
99 @param[in] Len Length of the Data in byte.\r
100\r
101**/\r
102VOID\r
103IScsiAddHeapItem (\r
104 IN OUT UINT8 **Heap,\r
105 IN VOID *Data,\r
106 IN UINTN Len\r
107 )\r
108{\r
109 //\r
110 // Add one byte for the NULL delimiter.\r
111 //\r
112 *Heap -= Len + 1;\r
113\r
114 CopyMem (*Heap, Data, Len);\r
115 *(*Heap + Len) = 0;\r
116}\r
117\r
118\r
119/**\r
120 Fill the Initiator section of the iSCSI Boot Firmware Table.\r
121\r
122 @param[in] Table The ACPI table.\r
123 @param[in, out] Heap The heap.\r
124\r
125**/\r
126VOID\r
127IScsiFillInitiatorSection (\r
128 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,\r
129 IN OUT UINT8 **Heap\r
130 )\r
131{\r
132 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;\r
133 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *Initiator;\r
134\r
135 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);\r
136\r
137 //\r
138 // Initiator section immediately follows the control section.\r
139 //\r
140 Initiator = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *)\r
141 ((UINT8 *) Control + IBFT_ROUNDUP (Control->Header.Length));\r
142\r
143 Control->InitiatorOffset = (UINT16) ((UINTN) Initiator - (UINTN) Table);\r
144\r
145 Initiator->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_ID;\r
146 Initiator->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_VERSION;\r
147 Initiator->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE);\r
148 Initiator->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BLOCK_VALID |\r
149 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BOOT_SELECTED;\r
150\r
151 //\r
152 // Fill the iSCSI Initiator Name into the heap.\r
153 //\r
154 IScsiAddHeapItem (Heap, mPrivate->InitiatorName, mPrivate->InitiatorNameLength - 1);\r
155\r
156 Initiator->IScsiNameLength = (UINT16) (mPrivate->InitiatorNameLength - 1);\r
157 Initiator->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
158}\r
159\r
160\r
161/**\r
162 Map the v4 IP address into v6 IP address.\r
163\r
164 @param[in] V4 The v4 IP address.\r
165 @param[out] V6 The v6 IP address.\r
166\r
167**/\r
168VOID\r
169IScsiMapV4ToV6Addr (\r
170 IN EFI_IPv4_ADDRESS *V4,\r
171 OUT EFI_IPv6_ADDRESS *V6\r
172 )\r
173{\r
174 UINTN Index;\r
175\r
176 ZeroMem (V6, sizeof (EFI_IPv6_ADDRESS));\r
177\r
178 V6->Addr[10] = 0xff;\r
179 V6->Addr[11] = 0xff;\r
180\r
181 for (Index = 0; Index < 4; Index++) {\r
182 V6->Addr[12 + Index] = V4->Addr[Index];\r
183 }\r
184}\r
185\r
186\r
187/**\r
188 Fill the NIC and target sections in iSCSI Boot Firmware Table.\r
189\r
190 @param[in] Table The buffer of the ACPI table.\r
191 @param[in, out] Heap The heap buffer used to store the variable length\r
192 parameters such as iSCSI name.\r
193\r
194**/\r
195VOID\r
196IScsiFillNICAndTargetSections (\r
197 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,\r
198 IN OUT UINT8 **Heap\r
199 )\r
200{\r
201 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;\r
202 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *Nic;\r
203 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *Target;\r
204 ISCSI_SESSION_CONFIG_NVDATA *NvData;\r
205 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfig;\r
206 UINT16 *SectionOffset;\r
207 UINTN Index;\r
208 UINT16 Length;\r
209 LIST_ENTRY *Entry;\r
210 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;\r
211 ISCSI_NIC_INFO *NicInfo;\r
212 BOOLEAN Flag;\r
213\r
214 //\r
215 // Get the offset of the first Nic and Target section.\r
216 //\r
217 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);\r
218 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Table +\r
219 Control->InitiatorOffset + IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE)));\r
220 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +\r
221 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));\r
222\r
223 SectionOffset = &Control->NIC0Offset;\r
224\r
225 Index = 0;\r
226 Flag = TRUE;\r
227\r
228 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
229 if (Index == 0) {\r
230 //\r
231 // First entry should be boot selected entry.\r
232 //\r
233 Attempt = IScsiConfigGetAttemptByConfigIndex (mPrivate->BootSelectedIndex);\r
234 if (Attempt == NULL) {\r
235 //\r
236 // First boot selected entry can not be found.\r
237 //\r
238 break;\r
239 }\r
240\r
241 ASSERT (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED);\r
242\r
243 } else {\r
244 if (Index == 1 && Flag) {\r
245 Entry = mPrivate->AttemptConfigs.ForwardLink;\r
246 Flag = FALSE;\r
247 }\r
248\r
249 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
250 if (Attempt->AttemptConfigIndex == mPrivate->BootSelectedIndex) {\r
251 continue;\r
252 }\r
253 }\r
254\r
255 if (Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
256 continue;\r
257 }\r
258\r
259 //\r
260 // Krb5 attempt will not be recorded in iBFT.\r
261 //\r
262 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {\r
263 continue;\r
264 }\r
265\r
266 //\r
267 // If multipath mode is enabled, only the attempts in MPIO will be recorded in iBFT.\r
268 //\r
269 if (mPrivate->EnableMpio && Attempt->SessionConfigData.Enabled != ISCSI_ENABLED_FOR_MPIO) {\r
270 continue;\r
271 }\r
272\r
273 //\r
274 // Only the valid attempts will be recorded.\r
275 //\r
276 if (!Attempt->ValidiBFTPath) {\r
277 continue;\r
278 }\r
279\r
280 NvData = &Attempt->SessionConfigData;\r
281 AuthConfig = &Attempt->AuthConfigData.CHAP;\r
282\r
283 //\r
284 // Fill the Nic section.\r
285 //\r
286\r
287 Nic->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_ID;\r
288 Nic->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_VERSION;\r
289 Nic->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE);\r
290 Nic->Header.Index = (UINT8) Index;\r
291 Nic->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BLOCK_VALID |\r
292 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_GLOBAL;\r
293\r
294 if (Index == 0) {\r
295 Nic->Header.Flags |= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BOOT_SELECTED;\r
296 }\r
297\r
298 if (NvData->InitiatorInfoFromDhcp) {\r
299 Nic->Origin = IpPrefixOriginDhcp;\r
300 } else {\r
301 Nic->Origin = IpPrefixOriginManual;\r
302 }\r
303\r
304 if (NvData->IpMode == IP_MODE_IP4 || NvData->IpMode == IP_MODE_AUTOCONFIG) {\r
305 //\r
306 // Get the subnet mask prefix length.\r
307 //\r
308 Nic->SubnetMaskPrefixLength = IScsiGetSubnetMaskPrefixLength (&NvData->SubnetMask);\r
309\r
310 //\r
311 // Map the various v4 addresses into v6 addresses.\r
312 //\r
75dce340 313 IScsiMapV4ToV6Addr (&NvData->LocalIp.v4, &Nic->Ip);\r
314 IScsiMapV4ToV6Addr (&NvData->Gateway.v4, &Nic->Gateway);\r
4c5a5e0c 315 IScsiMapV4ToV6Addr (&Attempt->PrimaryDns.v4, &Nic->PrimaryDns);\r
316 IScsiMapV4ToV6Addr (&Attempt->SecondaryDns.v4, &Nic->SecondaryDns);\r
317 IScsiMapV4ToV6Addr (&Attempt->DhcpServer.v4, &Nic->DhcpServer);\r
318\r
319 } else if (NvData->IpMode == IP_MODE_IP6 || NvData->IpMode == IP_MODE_AUTOCONFIG) {\r
4c5a5e0c 320\r
75dce340 321 Nic->SubnetMaskPrefixLength = NvData->PrefixLength;\r
322 CopyMem (&Nic->Ip, &NvData->LocalIp, sizeof (EFI_IPv6_ADDRESS));\r
323 CopyMem (&Nic->Gateway, &NvData->Gateway, sizeof (EFI_IPv6_ADDRESS));\r
4c5a5e0c 324 CopyMem (&Nic->PrimaryDns, &Attempt->PrimaryDns, sizeof (EFI_IPv6_ADDRESS));\r
325 CopyMem (&Nic->SecondaryDns, &Attempt->SecondaryDns, sizeof (EFI_IPv6_ADDRESS));\r
216f7970 326 CopyMem (&Nic->DhcpServer, &Attempt->DhcpServer, sizeof (EFI_IPv6_ADDRESS));\r
327\r
4c5a5e0c 328 } else {\r
329 ASSERT (FALSE);\r
330 }\r
331\r
332 //\r
333 // Get Nic Info: VLAN tag, Mac address, PCI location.\r
334 //\r
335 NicInfo = IScsiGetNicInfoByIndex (Attempt->NicIndex);\r
336 ASSERT (NicInfo != NULL);\r
337\r
338 Nic->VLanTag = NicInfo->VlanId;\r
339 CopyMem (Nic->Mac, &NicInfo->PermanentAddress, sizeof (Nic->Mac));\r
340 Nic->PciLocation = (UINT16) ((NicInfo->BusNumber << 8) |\r
341 (NicInfo->DeviceNumber << 3) | NicInfo->FunctionNumber);\r
342 *SectionOffset = (UINT16) ((UINTN) Nic - (UINTN) Table);\r
343 SectionOffset++;\r
344\r
345 //\r
346 // Fill the Target section.\r
347 //\r
348\r
349 Target->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID;\r
350 Target->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION;\r
351 Target->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE);\r
352 Target->Header.Index = (UINT8) Index;\r
353 Target->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BLOCK_VALID;\r
354\r
355 if (Index == 0) {\r
356 Target->Header.Flags |= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BOOT_SELECTED;\r
357 }\r
358\r
359 Target->Port = NvData->TargetPort;\r
360\r
361 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
362 Target->CHAPType = AuthConfig->CHAPType;\r
363 } else if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_NONE) {\r
364 Target->CHAPType = ISCSI_AUTH_TYPE_NONE;\r
365 }\r
366\r
367 Target->NicIndex = (UINT8) Index;\r
368\r
369 if (NvData->IpMode == IP_MODE_IP4 || NvData->IpMode == IP_MODE_AUTOCONFIG) {\r
370 IScsiMapV4ToV6Addr (&NvData->TargetIp.v4, &Target->Ip);\r
371 } else if (NvData->IpMode == IP_MODE_IP6 || NvData->IpMode == IP_MODE_AUTOCONFIG) {\r
372 CopyMem (&Target->Ip, &NvData->TargetIp, sizeof (EFI_IPv6_ADDRESS));\r
373 } else {\r
374 ASSERT (FALSE);\r
375 }\r
376\r
377 CopyMem (Target->BootLun, NvData->BootLun, sizeof (Target->BootLun));\r
378\r
379 //\r
380 // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.\r
381 //\r
382 Length = (UINT16) AsciiStrLen (NvData->TargetName);\r
383 IScsiAddHeapItem (Heap, NvData->TargetName, Length);\r
384\r
385 Target->IScsiNameLength = Length;\r
386 Target->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
387\r
388 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
389 //\r
390 // CHAP Name\r
391 //\r
392 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPName);\r
393 IScsiAddHeapItem (Heap, AuthConfig->CHAPName, Length);\r
394 Target->CHAPNameLength = Length;\r
395 Target->CHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
396\r
397 //\r
398 // CHAP Secret\r
399 //\r
400 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPSecret);\r
401 IScsiAddHeapItem (Heap, AuthConfig->CHAPSecret, Length);\r
402 Target->CHAPSecretLength = Length;\r
403 Target->CHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
404\r
405 if (Target->CHAPType == ISCSI_CHAP_MUTUAL) {\r
406 //\r
407 // Reverse CHAP Name.\r
408 //\r
409 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPName);\r
410 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPName, Length);\r
411 Target->ReverseCHAPNameLength = Length;\r
412 Target->ReverseCHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
413\r
414 //\r
415 // Reverse CHAP Secret.\r
416 //\r
417 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPSecret);\r
418 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPSecret, Length);\r
419 Target->ReverseCHAPSecretLength = Length;\r
420 Target->ReverseCHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
421 }\r
422 }\r
423\r
424 *SectionOffset = (UINT16) ((UINTN) Target - (UINTN) Table);\r
425 SectionOffset++;\r
426\r
427 //\r
428 // Advance to the next NIC/Target pair.\r
429 //\r
430 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Target +\r
431 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE)));\r
432 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +\r
433 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));\r
434\r
435 Index++;\r
436 }\r
437}\r
438\r
439\r
440/**\r
441 Publish and remove the iSCSI Boot Firmware Table according to the iSCSI\r
442 session status.\r
443\r
444**/\r
445VOID\r
446IScsiPublishIbft (\r
447 IN VOID\r
448 )\r
449{\r
450 EFI_STATUS Status;\r
451 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
452 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table;\r
453 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;\r
454 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;\r
455 UINT8 *Heap;\r
456 UINT8 Checksum;\r
457 UINTN Index;\r
458\r
459\r
460 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);\r
461 if (EFI_ERROR (Status)) {\r
462 return ;\r
463 }\r
464\r
465 //\r
466 // Find ACPI table RSD_PTR from the system table.\r
467 //\r
468 for (Index = 0, Rsdp = NULL; Index < gST->NumberOfTableEntries; Index++) {\r
469 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid) ||\r
470 CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid) ||\r
471 CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpiTableGuid)\r
472 ) {\r
473 //\r
474 // A match was found.\r
475 //\r
476 Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) gST->ConfigurationTable[Index].VendorTable;\r
477 break;\r
478 }\r
479 }\r
480\r
481 if (Rsdp == NULL) {\r
482 return ;\r
483 } else {\r
484 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;\r
485 }\r
486\r
487 if (mIbftInstalled) {\r
488 Status = AcpiTableProtocol->UninstallAcpiTable (\r
489 AcpiTableProtocol,\r
490 mTableKey\r
491 );\r
492 if (EFI_ERROR (Status)) {\r
493 return ;\r
494 }\r
495 mIbftInstalled = FALSE;\r
496 }\r
497\r
498 //\r
499 // If there is no valid attempt configuration, just return.\r
500 //\r
501 if ((!mPrivate->EnableMpio && mPrivate->ValidSinglePathCount == 0) ||\r
502 (mPrivate->EnableMpio && mPrivate->MpioCount <= mPrivate->Krb5MpioCount)) {\r
503 return ;\r
504 }\r
505\r
506 //\r
507 // Allocate 4k bytes to hold the ACPI table.\r
508 //\r
509 Table = AllocateZeroPool (IBFT_MAX_SIZE);\r
510 if (Table == NULL) {\r
511 return ;\r
512 }\r
513\r
514 Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;\r
515\r
516 //\r
517 // Fill in the various section of the iSCSI Boot Firmware Table.\r
518 //\r
519 IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId);\r
520 IScsiInitControlSection (Table);\r
521 IScsiFillInitiatorSection (Table, &Heap);\r
522 IScsiFillNICAndTargetSections (Table, &Heap);\r
523\r
524 Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length);\r
525 Table->Checksum = Checksum;\r
526\r
527 //\r
528 // Install or update the iBFT table.\r
529 //\r
530 Status = AcpiTableProtocol->InstallAcpiTable (\r
531 AcpiTableProtocol,\r
532 Table,\r
533 Table->Length,\r
534 &mTableKey\r
535 );\r
536 if (EFI_ERROR(Status)) {\r
537 return;\r
538 }\r
539\r
540 mIbftInstalled = TRUE;\r
541 FreePool (Table);\r
542}\r