]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IScsiDxe/IScsiIbft.c
1. Fix a bug in PXE driver that the PXE boot do not restart if a new boot option...
[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
324 \r
4c5a5e0c 325 CopyMem (&Nic->PrimaryDns, &Attempt->PrimaryDns, sizeof (EFI_IPv6_ADDRESS));\r
326 CopyMem (&Nic->SecondaryDns, &Attempt->SecondaryDns, sizeof (EFI_IPv6_ADDRESS));\r
327 //\r
328 // TODO: DHCP server address cannot be retrieved by DHCPv6 process since \r
329 // DHCP server option is removed.\r
330 //CopyMem (&Nic->DhcpServer, &Attempt->DhcpServer, sizeof (EFI_IPv6_ADDRESS));\r
331 //\r
332 } else {\r
333 ASSERT (FALSE);\r
334 }\r
335\r
336 //\r
337 // Get Nic Info: VLAN tag, Mac address, PCI location.\r
338 //\r
339 NicInfo = IScsiGetNicInfoByIndex (Attempt->NicIndex);\r
340 ASSERT (NicInfo != NULL);\r
341\r
342 Nic->VLanTag = NicInfo->VlanId;\r
343 CopyMem (Nic->Mac, &NicInfo->PermanentAddress, sizeof (Nic->Mac));\r
344 Nic->PciLocation = (UINT16) ((NicInfo->BusNumber << 8) |\r
345 (NicInfo->DeviceNumber << 3) | NicInfo->FunctionNumber);\r
346 *SectionOffset = (UINT16) ((UINTN) Nic - (UINTN) Table);\r
347 SectionOffset++;\r
348\r
349 //\r
350 // Fill the Target section.\r
351 //\r
352\r
353 Target->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID;\r
354 Target->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION;\r
355 Target->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE);\r
356 Target->Header.Index = (UINT8) Index;\r
357 Target->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BLOCK_VALID;\r
358\r
359 if (Index == 0) {\r
360 Target->Header.Flags |= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BOOT_SELECTED;\r
361 }\r
362\r
363 Target->Port = NvData->TargetPort;\r
364\r
365 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
366 Target->CHAPType = AuthConfig->CHAPType;\r
367 } else if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_NONE) {\r
368 Target->CHAPType = ISCSI_AUTH_TYPE_NONE;\r
369 }\r
370\r
371 Target->NicIndex = (UINT8) Index;\r
372\r
373 if (NvData->IpMode == IP_MODE_IP4 || NvData->IpMode == IP_MODE_AUTOCONFIG) {\r
374 IScsiMapV4ToV6Addr (&NvData->TargetIp.v4, &Target->Ip);\r
375 } else if (NvData->IpMode == IP_MODE_IP6 || NvData->IpMode == IP_MODE_AUTOCONFIG) {\r
376 CopyMem (&Target->Ip, &NvData->TargetIp, sizeof (EFI_IPv6_ADDRESS));\r
377 } else {\r
378 ASSERT (FALSE);\r
379 }\r
380\r
381 CopyMem (Target->BootLun, NvData->BootLun, sizeof (Target->BootLun));\r
382\r
383 //\r
384 // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.\r
385 //\r
386 Length = (UINT16) AsciiStrLen (NvData->TargetName);\r
387 IScsiAddHeapItem (Heap, NvData->TargetName, Length);\r
388\r
389 Target->IScsiNameLength = Length;\r
390 Target->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
391\r
392 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
393 //\r
394 // CHAP Name\r
395 //\r
396 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPName);\r
397 IScsiAddHeapItem (Heap, AuthConfig->CHAPName, Length);\r
398 Target->CHAPNameLength = Length;\r
399 Target->CHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
400\r
401 //\r
402 // CHAP Secret\r
403 //\r
404 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPSecret);\r
405 IScsiAddHeapItem (Heap, AuthConfig->CHAPSecret, Length);\r
406 Target->CHAPSecretLength = Length;\r
407 Target->CHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
408\r
409 if (Target->CHAPType == ISCSI_CHAP_MUTUAL) {\r
410 //\r
411 // Reverse CHAP Name.\r
412 //\r
413 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPName);\r
414 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPName, Length);\r
415 Target->ReverseCHAPNameLength = Length;\r
416 Target->ReverseCHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
417\r
418 //\r
419 // Reverse CHAP Secret.\r
420 //\r
421 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPSecret);\r
422 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPSecret, Length);\r
423 Target->ReverseCHAPSecretLength = Length;\r
424 Target->ReverseCHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
425 }\r
426 }\r
427\r
428 *SectionOffset = (UINT16) ((UINTN) Target - (UINTN) Table);\r
429 SectionOffset++;\r
430\r
431 //\r
432 // Advance to the next NIC/Target pair.\r
433 //\r
434 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Target +\r
435 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE)));\r
436 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +\r
437 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));\r
438\r
439 Index++;\r
440 }\r
441}\r
442\r
443\r
444/**\r
445 Publish and remove the iSCSI Boot Firmware Table according to the iSCSI\r
446 session status.\r
447\r
448**/\r
449VOID\r
450IScsiPublishIbft (\r
451 IN VOID\r
452 )\r
453{\r
454 EFI_STATUS Status;\r
455 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
456 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table;\r
457 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;\r
458 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;\r
459 UINT8 *Heap;\r
460 UINT8 Checksum;\r
461 UINTN Index;\r
462\r
463\r
464 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);\r
465 if (EFI_ERROR (Status)) {\r
466 return ;\r
467 }\r
468\r
469 //\r
470 // Find ACPI table RSD_PTR from the system table.\r
471 //\r
472 for (Index = 0, Rsdp = NULL; Index < gST->NumberOfTableEntries; Index++) {\r
473 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid) ||\r
474 CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid) ||\r
475 CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpiTableGuid)\r
476 ) {\r
477 //\r
478 // A match was found.\r
479 //\r
480 Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) gST->ConfigurationTable[Index].VendorTable;\r
481 break;\r
482 }\r
483 }\r
484\r
485 if (Rsdp == NULL) {\r
486 return ;\r
487 } else {\r
488 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;\r
489 }\r
490\r
491 if (mIbftInstalled) {\r
492 Status = AcpiTableProtocol->UninstallAcpiTable (\r
493 AcpiTableProtocol,\r
494 mTableKey\r
495 );\r
496 if (EFI_ERROR (Status)) {\r
497 return ;\r
498 }\r
499 mIbftInstalled = FALSE;\r
500 }\r
501\r
502 //\r
503 // If there is no valid attempt configuration, just return.\r
504 //\r
505 if ((!mPrivate->EnableMpio && mPrivate->ValidSinglePathCount == 0) ||\r
506 (mPrivate->EnableMpio && mPrivate->MpioCount <= mPrivate->Krb5MpioCount)) {\r
507 return ;\r
508 }\r
509\r
510 //\r
511 // Allocate 4k bytes to hold the ACPI table.\r
512 //\r
513 Table = AllocateZeroPool (IBFT_MAX_SIZE);\r
514 if (Table == NULL) {\r
515 return ;\r
516 }\r
517\r
518 Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;\r
519\r
520 //\r
521 // Fill in the various section of the iSCSI Boot Firmware Table.\r
522 //\r
523 IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId);\r
524 IScsiInitControlSection (Table);\r
525 IScsiFillInitiatorSection (Table, &Heap);\r
526 IScsiFillNICAndTargetSections (Table, &Heap);\r
527\r
528 Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length);\r
529 Table->Checksum = Checksum;\r
530\r
531 //\r
532 // Install or update the iBFT table.\r
533 //\r
534 Status = AcpiTableProtocol->InstallAcpiTable (\r
535 AcpiTableProtocol,\r
536 Table,\r
537 Table->Length,\r
538 &mTableKey\r
539 );\r
540 if (EFI_ERROR(Status)) {\r
541 return;\r
542 }\r
543\r
544 mIbftInstalled = TRUE;\r
545 FreePool (Table);\r
546}\r