]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IScsiDxe/IScsiIbft.c
NetworkPkg: Clean up source files
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiIbft.c
CommitLineData
4c5a5e0c 1/** @file\r
2 Implementation for iSCSI Boot Firmware Table publication.\r
3\r
f75a7f56 4Copyright (c) 2004 - 2018, 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
f75a7f56 22\r
4c5a5e0c 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
0e0fb74a
FS
362 if (AuthConfig->CHAPType == ISCSI_CHAP_UNI) {\r
363 Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_CHAP;\r
364 } else if (AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL) {\r
365 Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP;\r
366 }\r
4c5a5e0c 367 } else if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_NONE) {\r
0e0fb74a 368 Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_NO_CHAP;\r
4c5a5e0c 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
0e0fb74a 409 if (Target->CHAPType == EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP) {\r
4c5a5e0c 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
79d90984 459 EFI_ACPI_DESCRIPTION_HEADER *Xsdt;\r
4c5a5e0c 460 UINT8 *Heap;\r
461 UINT8 Checksum;\r
4c5a5e0c 462\r
79d90984
ZL
463 Rsdt = NULL;\r
464 Xsdt = NULL;\r
4c5a5e0c 465\r
466 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);\r
467 if (EFI_ERROR (Status)) {\r
468 return ;\r
469 }\r
470\r
471 //\r
472 // Find ACPI table RSD_PTR from the system table.\r
473 //\r
79d90984
ZL
474 Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **) &Rsdp);\r
475 if (EFI_ERROR (Status)) {\r
476 Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **) &Rsdp);\r
4c5a5e0c 477 }\r
478\r
79d90984 479 if (EFI_ERROR (Status) || (Rsdp == NULL)) {\r
4c5a5e0c 480 return ;\r
79d90984
ZL
481 } else if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION && Rsdp->XsdtAddress != 0) {\r
482 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;\r
483 } else if (Rsdp->RsdtAddress != 0) {\r
4c5a5e0c 484 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;\r
485 }\r
486\r
79d90984
ZL
487 if ((Xsdt == NULL) && (Rsdt == NULL)) {\r
488 return ;\r
489 }\r
490\r
4c5a5e0c 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
79d90984
ZL
523 if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) {\r
524 IScsiInitIbfTableHeader (Table, Xsdt->OemId, &Xsdt->OemTableId);\r
525 } else {\r
526 IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId);\r
527 }\r
528\r
4c5a5e0c 529 IScsiInitControlSection (Table);\r
530 IScsiFillInitiatorSection (Table, &Heap);\r
531 IScsiFillNICAndTargetSections (Table, &Heap);\r
532\r
533 Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length);\r
534 Table->Checksum = Checksum;\r
535\r
536 //\r
537 // Install or update the iBFT table.\r
538 //\r
539 Status = AcpiTableProtocol->InstallAcpiTable (\r
540 AcpiTableProtocol,\r
541 Table,\r
542 Table->Length,\r
543 &mTableKey\r
544 );\r
545 if (EFI_ERROR(Status)) {\r
546 return;\r
547 }\r
548\r
549 mIbftInstalled = TRUE;\r
550 FreePool (Table);\r
551}\r