]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Network/IScsiDxe/IScsiIbft.c
Add 'file not found' debug message to MTFTP.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiIbft.c
... / ...
CommitLineData
1/** @file\r
2 Implementation for iSCSI Boot Firmware Table publication.\r
3\r
4Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>\r
5This 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
12\r
13**/\r
14\r
15#include "IScsiImpl.h"\r
16\r
17BOOLEAN mIbftInstalled = FALSE;\r
18UINTN mTableKey;\r
19\r
20/**\r
21 Initialize the header of the iSCSI Boot Firmware Table.\r
22 \r
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
26**/\r
27VOID\r
28IScsiInitIbfTableHeader (\r
29 OUT EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Header,\r
30 IN UINT8 *OemId,\r
31 IN UINT64 *OemTableId\r
32 )\r
33{\r
34 ZeroMem (Header, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER));\r
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 CopyMem (Header->OemId, OemId, sizeof (Header->OemId));\r
42 CopyMem (&Header->OemTableId, OemTableId, sizeof (UINT64));\r
43}\r
44\r
45/**\r
46 Initialize the control section of the iSCSI Boot Firmware Table.\r
47 \r
48 @param[in] Table The ACPI table.\r
49 @param[in] HandleCount The number of the handles associated with iSCSI sessions, it's\r
50 equal to the number of iSCSI sessions.\r
51**/\r
52VOID\r
53IScsiInitControlSection (\r
54 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,\r
55 IN UINTN HandleCount\r
56 )\r
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
63 ZeroMem (Control, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE));\r
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
67 Control->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE);\r
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
79 Control->Header.Length = (UINT16) (Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));\r
80 }\r
81}\r
82\r
83/**\r
84 Add one item into the heap.\r
85\r
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
90**/\r
91VOID\r
92IScsiAddHeapItem (\r
93 IN OUT UINT8 **Heap,\r
94 IN VOID *Data,\r
95 IN UINTN Len\r
96 )\r
97{\r
98 //\r
99 // Add one byte for the NULL delimiter.\r
100 //\r
101 *Heap -= Len + 1;\r
102\r
103 CopyMem (*Heap, Data, Len);\r
104 *(*Heap + Len) = 0;\r
105}\r
106\r
107/**\r
108 Fill the Initiator section of the iSCSI Boot Firmware Table.\r
109\r
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
113**/\r
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
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
137 ZeroMem (Initiator, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE));\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 | 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
147 Status = gBS->HandleProtocol (Handle, &gEfiCallerIdGuid, (VOID **) &IScsiIdentifier);\r
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
165/**\r
166 Map the v4 IP address into v6 IP address.\r
167\r
168 @param[in] V4 The v4 IP address.\r
169 @param[out] V6 The v6 IP address.\r
170**/\r
171VOID\r
172IScsiMapV4ToV6Addr (\r
173 IN EFI_IPv4_ADDRESS *V4,\r
174 OUT EFI_IPv6_ADDRESS *V6\r
175 )\r
176{\r
177 UINTN Index;\r
178\r
179 ZeroMem (V6, sizeof (EFI_IPv6_ADDRESS));\r
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
189/**\r
190 Get the NIC's PCI location and return it accroding to the composited\r
191 format defined in iSCSI Boot Firmware Table.\r
192\r
193 @param[in] Controller The handle of the controller.\r
194\r
195 @return UINT16 The composited representation of the NIC PCI location.\r
196 @retval 0 Other errors as indicated.\r
197**/\r
198UINT16\r
199IScsiGetNICPciLocation (\r
200 IN EFI_HANDLE Controller\r
201 )\r
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
215 (VOID **)&DevicePath\r
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
230 Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo);\r
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
243/**\r
244 Fill the NIC and target sections in iSCSI Boot Firmware Table.\r
245\r
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
250**/\r
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
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
268 EFI_MAC_ADDRESS MacAddress;\r
269 UINTN HwAddressSize;\r
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
285 Status = gBS->HandleProtocol (Handles[Index], &gEfiCallerIdGuid, (VOID **)&IScsiIdentifier);\r
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
298 ZeroMem (Nic, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE));\r
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
302 Nic->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE);\r
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
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
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
344 ZeroMem (Target, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE));\r
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
348 Target->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE);\r
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->NicIndex = (UINT8) Index;\r
353\r
354 if (AuthConfig->CHAPType == ISCSI_CHAP_NONE) {\r
355 Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_NO_CHAP;\r
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
361\r
362 IScsiMapV4ToV6Addr (&SessionConfigData->NvData.TargetIp, &Target->Ip);\r
363 CopyMem (Target->BootLun, SessionConfigData->NvData.BootLun, sizeof (Target->BootLun));\r
364\r
365 //\r
366 // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.\r
367 //\r
368 Length = (UINT16) AsciiStrLen (SessionConfigData->NvData.TargetName);\r
369 IScsiAddHeapItem (Heap, SessionConfigData->NvData.TargetName, Length);\r
370\r
371 Target->IScsiNameLength = Length;\r
372 Target->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
373\r
374 if (Target->CHAPType != EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_NO_CHAP) {\r
375 //\r
376 // CHAP Name\r
377 //\r
378 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPName);\r
379 IScsiAddHeapItem (Heap, AuthConfig->CHAPName, Length);\r
380 Target->CHAPNameLength = Length;\r
381 Target->CHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
382\r
383 //\r
384 // CHAP Secret\r
385 //\r
386 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPSecret);\r
387 IScsiAddHeapItem (Heap, AuthConfig->CHAPSecret, Length);\r
388 Target->CHAPSecretLength = Length;\r
389 Target->CHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
390\r
391 if (Target->CHAPType == EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP) {\r
392 //\r
393 // Reverse CHAP Name\r
394 //\r
395 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPName);\r
396 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPName, Length);\r
397 Target->ReverseCHAPNameLength = Length;\r
398 Target->ReverseCHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
399\r
400 //\r
401 // Reverse CHAP Secret\r
402 //\r
403 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPSecret);\r
404 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPSecret, Length);\r
405 Target->ReverseCHAPSecretLength = Length;\r
406 Target->ReverseCHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);\r
407 }\r
408 }\r
409\r
410 *SectionOffset = (UINT16) ((UINTN) Target - (UINTN) Table);\r
411 SectionOffset++;\r
412\r
413 //\r
414 // Advance to the next NIC/Target pair\r
415 //\r
416 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Target +\r
417 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE)));\r
418 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +\r
419 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));\r
420 }\r
421}\r
422\r
423/**\r
424 Publish and remove the iSCSI Boot Firmware Table according to the iSCSI\r
425 session status.\r
426**/\r
427VOID\r
428IScsiPublishIbft (\r
429 VOID\r
430 )\r
431{\r
432 EFI_STATUS Status;\r
433 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
434 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table;\r
435 UINTN HandleCount;\r
436 EFI_HANDLE *HandleBuffer;\r
437 UINT8 *Heap;\r
438 UINT8 Checksum;\r
439 UINTN Index;\r
440 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;\r
441 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;\r
442\r
443 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);\r
444 if (EFI_ERROR (Status)) {\r
445 return ;\r
446 }\r
447\r
448\r
449 //\r
450 // Find ACPI table RSD_PTR from system table\r
451 //\r
452 for (Index = 0, Rsdp = NULL; Index < gST->NumberOfTableEntries; Index++) {\r
453 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid) ||\r
454 CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid) ||\r
455 CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpiTableGuid)\r
456 ) {\r
457 //\r
458 // A match was found.\r
459 //\r
460 Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) gST->ConfigurationTable[Index].VendorTable;\r
461 break;\r
462 }\r
463 }\r
464\r
465 if (Rsdp == NULL) {\r
466 return ;\r
467 } else {\r
468 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;\r
469 }\r
470\r
471\r
472 if (mIbftInstalled) {\r
473 Status = AcpiTableProtocol->UninstallAcpiTable (\r
474 AcpiTableProtocol,\r
475 mTableKey\r
476 );\r
477 if (EFI_ERROR (Status)) {\r
478 return ;\r
479 }\r
480 mIbftInstalled = FALSE;\r
481 }\r
482\r
483 //\r
484 // Get all iSCSI private protocols.\r
485 //\r
486 Status = gBS->LocateHandleBuffer (\r
487 ByProtocol,\r
488 &gEfiCallerIdGuid,\r
489 NULL,\r
490 &HandleCount,\r
491 &HandleBuffer\r
492 );\r
493 if (EFI_ERROR (Status)) {\r
494 return ;\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
501 return ;\r
502 }\r
503\r
504 Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;\r
505\r
506 //\r
507 // Fill in the various section of the iSCSI Boot Firmware Table.\r
508 //\r
509 IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId);\r
510 IScsiInitControlSection (Table, HandleCount);\r
511 IScsiFillInitiatorSection (Table, &Heap, HandleBuffer[0]);\r
512 IScsiFillNICAndTargetSections (Table, &Heap, HandleCount, HandleBuffer);\r
513\r
514 Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length);\r
515 Table->Checksum = Checksum;\r
516\r
517 FreePool (HandleBuffer);\r
518\r
519 //\r
520 // Install or update the iBFT table.\r
521 //\r
522 Status = AcpiTableProtocol->InstallAcpiTable (\r
523 AcpiTableProtocol,\r
524 Table,\r
525 Table->Length,\r
526 &mTableKey\r
527 );\r
528 if (EFI_ERROR(Status)) {\r
529 return;\r
530 }\r
531\r
532 mIbftInstalled = TRUE;\r
533 FreePool (Table);\r
534}\r