]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/IScsiDxe/IScsiIbft.c
Code clean up in NetLib:
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiIbft.c
CommitLineData
12618416 1/** @file\r
2 Implementation for iSCSI Boot Firmware Table publication.\r
6a690e23 3\r
85b990a8 4Copyright (c) 2004 - 2009, Intel Corporation.<BR>\r
7a444476 5All rights reserved. This 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
6a690e23 12\r
12618416 13**/\r
6a690e23 14\r
15#include "IScsiImpl.h"\r
16\r
85b990a8 17BOOLEAN mIbftInstalled = FALSE;\r
18UINTN mTableKey;\r
19\r
12618416 20/**\r
21 Initialize the header of the iSCSI Boot Firmware Table.\r
22 \r
f6b7393c 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
12618416 26**/\r
6a690e23 27VOID\r
28IScsiInitIbfTableHeader (\r
54fbbbd7 29 OUT EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Header,\r
30 IN UINT8 *OemId,\r
31 IN UINT64 *OemTableId\r
6a690e23 32 )\r
6a690e23 33{\r
e48e37fc 34 ZeroMem (Header, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER));\r
6a690e23 35\r
36 Header->Signature = EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE;\r
37 Header->Length = IBFT_HEAP_OFFSET;\r
38 Header->Revision = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_REVISION;\r
39 Header->Checksum = 0;\r
40\r
41 Header->OemId[0] = 'I';\r
42 Header->OemId[1] = 'N';\r
43 Header->OemId[2] = 'T';\r
44 Header->OemId[3] = 'E';\r
45 Header->OemId[4] = 'L';\r
54fbbbd7 46 \r
47 CopyMem (Header->OemId, OemId, sizeof (Header->OemId));\r
48 Header->OemTableId = *OemTableId;\r
6a690e23 49}\r
50\r
12618416 51/**\r
52 Initialize the control section of the iSCSI Boot Firmware Table.\r
53 \r
d8c04564 54 @param[in] Table The ACPI table.\r
55 @param[in] HandleCount The number of the handles associated with iSCSI sessions, it's\r
12618416 56 equal to the number of iSCSI sessions.\r
12618416 57**/\r
6a690e23 58VOID\r
59IScsiInitControlSection (\r
60 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,\r
61 IN UINTN HandleCount\r
62 )\r
6a690e23 63{\r
64 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;\r
65 UINTN NumOffset;\r
66\r
67 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);\r
68\r
e48e37fc 69 ZeroMem (Control, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE));\r
6a690e23 70\r
71 Control->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_ID;\r
72 Control->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_VERSION;\r
73 Control->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE);\r
74\r
75 //\r
76 // Each session occupies two offsets, one for the NIC section,\r
77 // the other for the Target section.\r
78 //\r
79 NumOffset = 2 * HandleCount;\r
80 if (NumOffset > 4) {\r
81 //\r
82 // Need expand the control section if more than 2 NIC/Target sections\r
83 // exist.\r
84 //\r
69b0882d 85 Control->Header.Length = (UINT16) (Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));\r
6a690e23 86 }\r
87}\r
88\r
12618416 89/**\r
90 Add one item into the heap.\r
91\r
d8c04564 92 @param[in, out] Heap On input, the current address of the heap; On output, the address of\r
93 the heap after the item is added.\r
94 @param[in] Data The data to add into the heap.\r
95 @param[in] Len Length of the Data in byte.\r
12618416 96**/\r
6a690e23 97VOID\r
98IScsiAddHeapItem (\r
99 IN OUT UINT8 **Heap,\r
100 IN VOID *Data,\r
101 IN UINTN Len\r
102 )\r
6a690e23 103{\r
104 //\r
105 // Add one byte for the NULL delimiter.\r
106 //\r
107 *Heap -= Len + 1;\r
108\r
e48e37fc 109 CopyMem (*Heap, Data, Len);\r
6a690e23 110 *(*Heap + Len) = 0;\r
111}\r
112\r
12618416 113/**\r
114 Fill the Initiator section of the iSCSI Boot Firmware Table.\r
115\r
d8c04564 116 @param[in] Table The ACPI table.\r
117 @param[in, out] Heap The heap.\r
118 @param[in] Handle The handle associated with the iSCSI session.\r
12618416 119**/\r
6a690e23 120VOID\r
121IScsiFillInitiatorSection (\r
122 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,\r
123 IN OUT UINT8 **Heap,\r
124 IN EFI_HANDLE Handle\r
125 )\r
6a690e23 126{\r
127 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;\r
128 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *Initiator;\r
129 ISCSI_DRIVER_DATA *DriverData;\r
130 ISCSI_SESSION *Session;\r
131 ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;\r
132 EFI_STATUS Status;\r
133\r
134 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);\r
135\r
136 //\r
137 // Initiator section immediately follows the control section.\r
138 //\r
139 Initiator = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *) ((UINT8 *) Control + IBFT_ROUNDUP (Control->Header.Length));\r
140\r
141 Control->InitiatorOffset = (UINT16) ((UINTN) Initiator - (UINTN) Table);\r
142\r
e48e37fc 143 ZeroMem (Initiator, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE));\r
6a690e23 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 = 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 | EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BOOT_SELECTED;\r
149\r
150 //\r
151 // Get the identifier from the handle.\r
152 //\r
5af5b3fd 153 Status = gBS->HandleProtocol (Handle, &gIScsiPrivateGuid, (VOID **) &IScsiIdentifier);\r
6a690e23 154 if (EFI_ERROR (Status)) {\r
155 ASSERT (FALSE);\r
156 return ;\r
157 }\r
158\r
159 DriverData = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);\r
160 Session = &DriverData->Session;\r
161\r
162 //\r
163 // Fill the iSCSI Initiator Name into the heap.\r
164 //\r
165 IScsiAddHeapItem (Heap, Session->InitiatorName, Session->InitiatorNameLength - 1);\r
166\r
167 Initiator->IScsiNameLength = (UINT16) (Session->InitiatorNameLength - 1);\r
168 Initiator->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
169}\r
170\r
12618416 171/**\r
172 Map the v4 IP address into v6 IP address.\r
173\r
d8c04564 174 @param[in] V4 The v4 IP address.\r
175 @param[out] V6 The v6 IP address.\r
12618416 176**/\r
6a690e23 177VOID\r
178IScsiMapV4ToV6Addr (\r
179 IN EFI_IPv4_ADDRESS *V4,\r
180 OUT EFI_IPv6_ADDRESS *V6\r
181 )\r
6a690e23 182{\r
183 UINTN Index;\r
184\r
e48e37fc 185 ZeroMem (V6, sizeof (EFI_IPv6_ADDRESS));\r
6a690e23 186\r
187 V6->Addr[10] = 0xff;\r
188 V6->Addr[11] = 0xff;\r
189\r
190 for (Index = 0; Index < 4; Index++) {\r
191 V6->Addr[12 + Index] = V4->Addr[Index];\r
192 }\r
193}\r
194\r
12618416 195/**\r
6a690e23 196 Get the NIC's PCI location and return it accroding to the composited\r
197 format defined in iSCSI Boot Firmware Table.\r
6a690e23 198\r
d8c04564 199 @param[in] Controller The handle of the controller.\r
6a690e23 200\r
d8c04564 201 @return UINT16 The composited representation of the NIC PCI location.\r
963dbb30 202 @retval 0 Other errors as indicated.\r
12618416 203**/\r
12618416 204UINT16\r
205IScsiGetNICPciLocation (\r
206 IN EFI_HANDLE Controller\r
207 )\r
6a690e23 208{\r
209 EFI_STATUS Status;\r
210 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
211 EFI_HANDLE PciIoHandle;\r
212 EFI_PCI_IO_PROTOCOL *PciIo;\r
213 UINTN Segment;\r
214 UINTN Bus;\r
215 UINTN Device;\r
216 UINTN Function;\r
217\r
218 Status = gBS->HandleProtocol (\r
219 Controller,\r
220 &gEfiDevicePathProtocolGuid,\r
69b0882d 221 (VOID **)&DevicePath\r
6a690e23 222 );\r
223 if (EFI_ERROR (Status)) {\r
224 return 0;\r
225 }\r
226\r
227 Status = gBS->LocateDevicePath (\r
228 &gEfiPciIoProtocolGuid,\r
229 &DevicePath,\r
230 &PciIoHandle\r
231 );\r
232 if (EFI_ERROR (Status)) {\r
233 return 0;\r
234 }\r
235\r
69b0882d 236 Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo);\r
6a690e23 237 if (EFI_ERROR (Status)) {\r
238 return 0;\r
239 }\r
240\r
241 Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);\r
242 if (EFI_ERROR (Status)) {\r
243 return 0;\r
244 }\r
245\r
246 return (UINT16) ((Bus << 8) | (Device << 3) | Function);\r
247}\r
248\r
12618416 249/**\r
250 Get the MAC address of the controller.\r
251 \r
d8c04564 252 @param[in] Controller The handle of the controller.\r
12618416 253\r
d8c04564 254 @return EFI_MAC_ADDRESS * The mac address.\r
12618416 255**/\r
6a690e23 256EFI_MAC_ADDRESS *\r
257IScsiGetMacAddress (\r
258 IN EFI_HANDLE Controller\r
259 )\r
6a690e23 260{\r
261 EFI_STATUS Status;\r
262 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
263\r
264 Status = gBS->HandleProtocol (\r
265 Controller,\r
266 &gEfiSimpleNetworkProtocolGuid,\r
69b0882d 267 (VOID **) &Snp\r
6a690e23 268 );\r
269 ASSERT_EFI_ERROR (Status);\r
270\r
271 return &Snp->Mode->PermanentAddress;\r
272}\r
273\r
12618416 274/**\r
275 Fill the NIC and target sections in iSCSI Boot Firmware Table.\r
276\r
d8c04564 277 @param[in] Table The buffer of the ACPI table.\r
278 @param[in, out] Heap The heap buffer used to store the variable length parameters such as iSCSI name.\r
279 @param[in] HandleCount Count The number of handles having iSCSI private protocol installed.\r
280 @param[in] Handles The handle buffer.\r
12618416 281**/\r
6a690e23 282VOID\r
283IScsiFillNICAndTargetSections (\r
284 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,\r
285 IN OUT UINT8 **Heap,\r
286 IN UINTN HandleCount,\r
287 IN EFI_HANDLE *Handles\r
288 )\r
6a690e23 289{\r
290 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;\r
291 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *Nic;\r
292 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *Target;\r
293 ISCSI_DRIVER_DATA *DriverData;\r
294 ISCSI_SESSION_CONFIG_DATA *SessionConfigData;\r
295 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfig;\r
296 UINT16 *SectionOffset;\r
297 UINTN Index;\r
298 UINT16 Length;\r
299 EFI_MAC_ADDRESS *Mac;\r
300 ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;\r
301 EFI_STATUS Status;\r
302\r
303 //\r
304 // Get the offset of the first Nic and Target section.\r
305 //\r
306 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);\r
307 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Table +\r
308 Control->InitiatorOffset + IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE)));\r
309 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +\r
310 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));\r
311\r
312 SectionOffset = &Control->NIC0Offset;\r
313\r
314 for (Index = 0; Index < HandleCount; Index++) {\r
5af5b3fd 315 Status = gBS->HandleProtocol (Handles[Index], &gIScsiPrivateGuid, (VOID **)&IScsiIdentifier);\r
6a690e23 316 if (EFI_ERROR (Status)) {\r
317 ASSERT (FALSE);\r
318 return ;\r
319 }\r
320\r
321 DriverData = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);\r
322 SessionConfigData = &DriverData->Session.ConfigData;\r
323 AuthConfig = &DriverData->Session.AuthData.AuthConfig;\r
324\r
325 //\r
326 // Fill the Nic section.\r
327 //\r
e48e37fc 328 ZeroMem (Nic, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE));\r
6a690e23 329\r
330 Nic->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_ID;\r
331 Nic->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_VERSION;\r
332 Nic->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE);\r
333 Nic->Header.Index = (UINT8) Index;\r
334 Nic->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BLOCK_VALID |\r
335 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BOOT_SELECTED |\r
336 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_GLOBAL;\r
337\r
338 //\r
339 // Get the subnet mask prefix length.\r
340 //\r
341 Nic->SubnetMaskPrefixLength = IScsiGetSubnetMaskPrefixLength (&SessionConfigData->NvData.SubnetMask);\r
342\r
343 if (SessionConfigData->NvData.InitiatorInfoFromDhcp) {\r
344 Nic->Origin = IpPrefixOriginDhcp;\r
345 } else {\r
346 Nic->Origin = IpPrefixOriginManual;\r
347 }\r
348 //\r
349 // Map the various v4 addresses into v6 addresses.\r
350 //\r
351 IScsiMapV4ToV6Addr (&SessionConfigData->NvData.LocalIp, &Nic->Ip);\r
352 IScsiMapV4ToV6Addr (&SessionConfigData->NvData.Gateway, &Nic->Gateway);\r
353 IScsiMapV4ToV6Addr (&SessionConfigData->PrimaryDns, &Nic->PrimaryDns);\r
354 IScsiMapV4ToV6Addr (&SessionConfigData->SecondaryDns, &Nic->SecondaryDns);\r
355 IScsiMapV4ToV6Addr (&SessionConfigData->DhcpServer, &Nic->DhcpServer);\r
356\r
357 Mac = IScsiGetMacAddress (DriverData->Controller);\r
e48e37fc 358 CopyMem (Nic->Mac, Mac, sizeof (Nic->Mac));\r
6a690e23 359\r
360 //\r
361 // Get the PCI location of the Nic.\r
362 //\r
363 Nic->PciLocation = IScsiGetNICPciLocation (DriverData->Controller);\r
364\r
365 *SectionOffset = (UINT16) ((UINTN) Nic - (UINTN) Table);\r
366 SectionOffset++;\r
367\r
368 //\r
369 // Fill the Target section.\r
370 //\r
e48e37fc 371 ZeroMem (Target, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE));\r
6a690e23 372\r
373 Target->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID;\r
374 Target->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION;\r
375 Target->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE);\r
376 Target->Header.Index = (UINT8) Index;\r
377 Target->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BLOCK_VALID | EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BOOT_SELECTED;\r
378 Target->Port = SessionConfigData->NvData.TargetPort;\r
379 Target->CHAPType = AuthConfig->CHAPType;\r
380 Target->NicIndex = (UINT8) Index;\r
381\r
382 IScsiMapV4ToV6Addr (&SessionConfigData->NvData.TargetIp, &Target->Ip);\r
e48e37fc 383 CopyMem (Target->BootLun, SessionConfigData->NvData.BootLun, sizeof (Target->BootLun));\r
6a690e23 384\r
385 //\r
386 // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.\r
387 //\r
388 Length = (UINT16) AsciiStrLen (SessionConfigData->NvData.TargetName);\r
389 IScsiAddHeapItem (Heap, SessionConfigData->NvData.TargetName, Length);\r
390\r
391 Target->IScsiNameLength = Length;\r
392 Target->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
393\r
394 if (Target->CHAPType != ISCSI_CHAP_NONE) {\r
395 //\r
396 // CHAP Name\r
397 //\r
398 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPName);\r
399 IScsiAddHeapItem (Heap, AuthConfig->CHAPName, Length);\r
400 Target->CHAPNameLength = Length;\r
401 Target->CHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
402\r
403 //\r
404 // CHAP Secret\r
405 //\r
406 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPSecret);\r
407 IScsiAddHeapItem (Heap, AuthConfig->CHAPSecret, Length);\r
408 Target->CHAPSecretLength = Length;\r
409 Target->CHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
410\r
411 if (Target->CHAPType == ISCSI_CHAP_MUTUAL) {\r
412 //\r
413 // Reverse CHAP Name\r
414 //\r
415 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPName);\r
416 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPName, Length);\r
417 Target->ReverseCHAPNameLength = Length;\r
418 Target->ReverseCHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
419\r
420 //\r
421 // Reverse CHAP Secret\r
422 //\r
423 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPSecret);\r
424 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPSecret, Length);\r
425 Target->ReverseCHAPSecretLength = Length;\r
426 Target->ReverseCHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
427 }\r
428 }\r
429\r
430 *SectionOffset = (UINT16) ((UINTN) Target - (UINTN) Table);\r
431 SectionOffset++;\r
432\r
433 //\r
434 // Advance to the next NIC/Target pair\r
435 //\r
436 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Target +\r
437 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE)));\r
438 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +\r
439 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));\r
440 }\r
441}\r
442\r
12618416 443/**\r
6a690e23 444 Publish and remove the iSCSI Boot Firmware Table according to the iSCSI\r
445 session status.\r
12618416 446**/\r
447VOID\r
448IScsiPublishIbft (\r
55a64ae0 449 VOID\r
12618416 450 )\r
6a690e23 451{\r
452 EFI_STATUS Status;\r
85b990a8 453 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
6a690e23 454 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table;\r
455 UINTN HandleCount;\r
456 EFI_HANDLE *HandleBuffer;\r
457 UINT8 *Heap;\r
35c290c5 458 UINT8 Checksum;\r
54fbbbd7 459 UINTN Index;\r
460 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;\r
461 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;\r
6a690e23 462\r
85b990a8 463 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);\r
6a690e23 464 if (EFI_ERROR (Status)) {\r
465 return ;\r
466 }\r
6a690e23 467\r
54fbbbd7 468\r
469 //\r
470 // Find ACPI table RSD_PTR from 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\r
85b990a8 492 if (mIbftInstalled) {\r
493 Status = AcpiTableProtocol->UninstallAcpiTable (\r
494 AcpiTableProtocol,\r
495 mTableKey\r
496 );\r
497 if (EFI_ERROR (Status)) {\r
498 return ;\r
6a690e23 499 }\r
85b990a8 500 mIbftInstalled = FALSE;\r
6a690e23 501 }\r
85b990a8 502\r
6a690e23 503 //\r
504 // Get all iSCSI private protocols.\r
505 //\r
506 Status = gBS->LocateHandleBuffer (\r
507 ByProtocol,\r
5af5b3fd 508 &gIScsiPrivateGuid,\r
6a690e23 509 NULL,\r
510 &HandleCount,\r
511 &HandleBuffer\r
512 );\r
513 if (EFI_ERROR (Status)) {\r
514 return ;\r
515 }\r
516 //\r
517 // Allocate 4k bytes to hold the ACPI table.\r
518 //\r
35c290c5 519 Table = AllocateZeroPool (IBFT_MAX_SIZE);\r
6a690e23 520 if (Table == NULL) {\r
521 return ;\r
522 }\r
523\r
69b0882d 524 Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;\r
6a690e23 525\r
526 //\r
527 // Fill in the various section of the iSCSI Boot Firmware Table.\r
528 //\r
54fbbbd7 529 IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId);\r
6a690e23 530 IScsiInitControlSection (Table, HandleCount);\r
531 IScsiFillInitiatorSection (Table, &Heap, HandleBuffer[0]);\r
532 IScsiFillNICAndTargetSections (Table, &Heap, HandleCount, HandleBuffer);\r
533\r
35c290c5 534 Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length);\r
535 Table->Checksum = Checksum;\r
536\r
85b990a8 537 FreePool (HandleBuffer);\r
6a690e23 538\r
539 //\r
540 // Install or update the iBFT table.\r
541 //\r
85b990a8 542 Status = AcpiTableProtocol->InstallAcpiTable (\r
543 AcpiTableProtocol,\r
544 Table,\r
545 Table->Length,\r
546 &mTableKey\r
547 );\r
548 if (EFI_ERROR(Status)) {\r
549 return;\r
6a690e23 550 }\r
551\r
85b990a8 552 mIbftInstalled = TRUE;\r
553 FreePool (Table);\r
6a690e23 554}\r