1 /** @file 2 Implementation for iSCSI Boot Firmware Table publication. 3 4 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "IScsiImpl.h" 16 17 BOOLEAN mIbftInstalled = FALSE; 18 UINTN 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 **/ 27 VOID 28 IScsiInitIbfTableHeader ( 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 **/ 52 VOID 53 IScsiInitControlSection ( 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 **/ 91 VOID 92 IScsiAddHeapItem ( 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 **/ 114 VOID 115 IScsiFillInitiatorSection ( 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 **/ 171 VOID 172 IScsiMapV4ToV6Addr ( 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 **/ 198 UINT16 199 IScsiGetNICPciLocation ( 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 **/ 251 VOID 252 IScsiFillNICAndTargetSections ( 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 **/ 427 VOID 428 IScsiPublishIbft ( 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 UINTN Index; 440 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; 441 EFI_ACPI_DESCRIPTION_HEADER *Rsdt; 442 443 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol); 444 if (EFI_ERROR (Status)) { 445 return ; 446 } 447 448 449 // 450 // Find ACPI table RSD_PTR from system table 451 // 452 for (Index = 0, Rsdp = NULL; Index < gST->NumberOfTableEntries; Index++) { 453 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid) || 454 CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid) || 455 CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpiTableGuid) 456 ) { 457 // 458 // A match was found. 459 // 460 Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) gST->ConfigurationTable[Index].VendorTable; 461 break; 462 } 463 } 464 465 if (Rsdp == NULL) { 466 return ; 467 } else { 468 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress; 469 } 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 IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId); 510 IScsiInitControlSection (Table, HandleCount); 511 IScsiFillInitiatorSection (Table, &Heap, HandleBuffer[0]); 512 IScsiFillNICAndTargetSections (Table, &Heap, HandleCount, HandleBuffer); 513 514 Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length); 515 Table->Checksum = Checksum; 516 517 FreePool (HandleBuffer); 518 519 // 520 // Install or update the iBFT table. 521 // 522 Status = AcpiTableProtocol->InstallAcpiTable ( 523 AcpiTableProtocol, 524 Table, 525 Table->Length, 526 &mTableKey 527 ); 528 if (EFI_ERROR(Status)) { 529 return; 530 } 531 532 mIbftInstalled = TRUE; 533 FreePool (Table); 534 } 535