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