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