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