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