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