The RSDT is only used when the bios need to support ACPI 1.0 version. When change PcdAcpiExposedTableVersions to 0x3C, it will not support ACPI 1.0. The default is 0x3E. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Zhang Lubo <lubo.zhang@intel.com> Cc: Eric Dong <eric.dong@intel.com> Cc: Ye Ting <ting.ye@intel.com> Cc: Fu Siyuan <siyuan.fu@intel.com> Reviewed-by: Ye Ting <ting.ye@intel.com> Reviewed-by: Eric Dong <eric.dong@intel.com>
		
			
				
	
	
		
			552 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			552 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Implementation for iSCSI Boot Firmware Table publication.
 | |
| 
 | |
| Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "IScsiImpl.h"
 | |
| 
 | |
| BOOLEAN mIbftInstalled = FALSE;
 | |
| UINTN   mTableKey;
 | |
| 
 | |
| /**
 | |
|   Initialize the header of the iSCSI Boot Firmware Table.
 | |
|   
 | |
|   @param[out]  Header     The header of the iSCSI Boot Firmware Table.
 | |
|   @param[in]   OemId      The OEM ID.
 | |
|   @param[in]   OemTableId The OEM table ID for the iBFT.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| IScsiInitIbfTableHeader (
 | |
|   OUT EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER   *Header,
 | |
|   IN  UINT8                                       *OemId,
 | |
|   IN  UINT64                                      *OemTableId
 | |
|   )
 | |
| {
 | |
|   Header->Signature = EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE;
 | |
|   Header->Length    = IBFT_HEAP_OFFSET;
 | |
|   Header->Revision  = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_REVISION;
 | |
|   Header->Checksum  = 0;
 | |
| 
 | |
|   CopyMem (Header->OemId, OemId, sizeof (Header->OemId));
 | |
|   CopyMem (&Header->OemTableId, OemTableId, sizeof (UINT64));
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Initialize the control section of the iSCSI Boot Firmware Table.
 | |
| 
 | |
|   @param[in]  Table       The ACPI table.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| IScsiInitControlSection (
 | |
|   IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER  *Table
 | |
|   )
 | |
| {
 | |
|   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE  *Control;
 | |
|   UINTN                                                 NumOffset;
 | |
| 
 | |
|   Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
 | |
| 
 | |
|   Control->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_ID;
 | |
|   Control->Header.Version     = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_VERSION;
 | |
|   Control->Header.Length      = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE);
 | |
| 
 | |
|   //
 | |
|   // If in multipathing mode, enable the Boot Failover Flag.
 | |
|   // If in single path mode, disable it. Mix-model is not allowed.
 | |
|   //
 | |
|   // BUGBUG: if Boot Failover Flag is set to 1, the OS installer cannot
 | |
|   // find the iSCSI mapped disk. So still keep not set for single path mode.
 | |
|   //
 | |
|   if (mPrivate->EnableMpio) {
 | |
|     Control->Header.Flags = 0;
 | |
|     NumOffset = 2 * (mPrivate->MpioCount - mPrivate->Krb5MpioCount);
 | |
|   } else {
 | |
|     NumOffset = 2 * mPrivate->ValidSinglePathCount;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Each attempt occupies two offsets: one for the NIC section;
 | |
|   // the other for the Target section.
 | |
|   //
 | |
|   if (NumOffset > 4) {
 | |
|     //
 | |
|     // Need expand the control section if more than 2 NIC/Target attempts
 | |
|     // exist.
 | |
|     //
 | |
|     Control->Header.Length = (UINT16) (Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Add one item into the heap.
 | |
| 
 | |
|   @param[in, out]  Heap  On input, the current address of the heap. On output, the address of
 | |
|                          the heap after the item is added.
 | |
|   @param[in]       Data  The data to add into the heap.
 | |
|   @param[in]       Len   Length of the Data in byte.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| IScsiAddHeapItem (
 | |
|   IN OUT UINT8  **Heap,
 | |
|   IN     VOID   *Data,
 | |
|   IN     UINTN  Len
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Add one byte for the NULL delimiter.
 | |
|   //
 | |
|   *Heap -= Len + 1;
 | |
| 
 | |
|   CopyMem (*Heap, Data, Len);
 | |
|   *(*Heap + Len) = 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Fill the Initiator section of the iSCSI Boot Firmware Table.
 | |
| 
 | |
|   @param[in]       Table    The ACPI table.
 | |
|   @param[in, out]  Heap     The heap.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| IScsiFillInitiatorSection (
 | |
|   IN     EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER  *Table,
 | |
|   IN OUT UINT8                                      **Heap
 | |
|   )
 | |
| {
 | |
|   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE    *Control;
 | |
|   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE  *Initiator;
 | |
| 
 | |
|   Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
 | |
| 
 | |
|   //
 | |
|   // Initiator section immediately follows the control section.
 | |
|   //
 | |
|   Initiator = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *)
 | |
|               ((UINT8 *) Control + IBFT_ROUNDUP (Control->Header.Length));
 | |
| 
 | |
|   Control->InitiatorOffset = (UINT16) ((UINTN) Initiator - (UINTN) Table);
 | |
| 
 | |
|   Initiator->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_ID;
 | |
|   Initiator->Header.Version     = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_VERSION;
 | |
|   Initiator->Header.Length      = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE);
 | |
|   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;
 | |
| 
 | |
|   //
 | |
|   // Fill the iSCSI Initiator Name into the heap.
 | |
|   //
 | |
|   IScsiAddHeapItem (Heap, mPrivate->InitiatorName, mPrivate->InitiatorNameLength - 1);
 | |
| 
 | |
|   Initiator->IScsiNameLength  = (UINT16) (mPrivate->InitiatorNameLength - 1);
 | |
|   Initiator->IScsiNameOffset  = (UINT16) ((UINTN) *Heap - (UINTN) Table);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Map the v4 IP address into v6 IP address.
 | |
| 
 | |
|   @param[in]   V4 The v4 IP address.
 | |
|   @param[out]  V6 The v6 IP address.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| IScsiMapV4ToV6Addr (
 | |
|   IN  EFI_IPv4_ADDRESS *V4,
 | |
|   OUT EFI_IPv6_ADDRESS *V6
 | |
|   )
 | |
| {
 | |
|   UINTN Index;
 | |
| 
 | |
|   ZeroMem (V6, sizeof (EFI_IPv6_ADDRESS));
 | |
| 
 | |
|   V6->Addr[10]  = 0xff;
 | |
|   V6->Addr[11]  = 0xff;
 | |
| 
 | |
|   for (Index = 0; Index < 4; Index++) {
 | |
|     V6->Addr[12 + Index] = V4->Addr[Index];
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Fill the NIC and target sections in iSCSI Boot Firmware Table.
 | |
| 
 | |
|   @param[in]       Table    The buffer of the ACPI table.
 | |
|   @param[in, out]  Heap     The heap buffer used to store the variable length
 | |
|                             parameters such as iSCSI name.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| IScsiFillNICAndTargetSections (
 | |
|   IN     EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER  *Table,
 | |
|   IN OUT UINT8                                      **Heap
 | |
|   )
 | |
| {
 | |
|   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE  *Control;
 | |
|   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE      *Nic;
 | |
|   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE   *Target;
 | |
|   ISCSI_SESSION_CONFIG_NVDATA                           *NvData;
 | |
|   ISCSI_CHAP_AUTH_CONFIG_NVDATA                         *AuthConfig;
 | |
|   UINT16                                                *SectionOffset;
 | |
|   UINTN                                                 Index;
 | |
|   UINT16                                                Length;
 | |
|   LIST_ENTRY                                            *Entry;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA                           *Attempt;
 | |
|   ISCSI_NIC_INFO                                        *NicInfo;
 | |
|   BOOLEAN                                               Flag;
 | |
| 
 | |
|   //
 | |
|   // Get the offset of the first Nic and Target section.
 | |
|   //
 | |
|   Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
 | |
|   Nic     = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Table +
 | |
|           Control->InitiatorOffset + IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE)));
 | |
|   Target  = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
 | |
|           IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
 | |
| 
 | |
|   SectionOffset = &Control->NIC0Offset;
 | |
| 
 | |
|   Index = 0;
 | |
|   Flag  = TRUE;
 | |
| 
 | |
|   NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
 | |
|     if (Index == 0) {
 | |
|       //
 | |
|       // First entry should be boot selected entry.
 | |
|       //
 | |
|       Attempt = IScsiConfigGetAttemptByConfigIndex (mPrivate->BootSelectedIndex);
 | |
|       if (Attempt == NULL) {
 | |
|         //
 | |
|         // First boot selected entry can not be found.
 | |
|         //
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       ASSERT (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED);
 | |
| 
 | |
|     } else {
 | |
|       if (Index == 1 && Flag) {
 | |
|         Entry = mPrivate->AttemptConfigs.ForwardLink;
 | |
|         Flag = FALSE;
 | |
|       }
 | |
| 
 | |
|       Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
 | |
|       if (Attempt->AttemptConfigIndex == mPrivate->BootSelectedIndex) {
 | |
|         continue;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Krb5 attempt will not be recorded in iBFT.
 | |
|     //
 | |
|     if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // If multipath mode is enabled, only the attempts in MPIO will be recorded in iBFT.
 | |
|     //
 | |
|     if (mPrivate->EnableMpio && Attempt->SessionConfigData.Enabled != ISCSI_ENABLED_FOR_MPIO) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Only the valid attempts will be recorded.
 | |
|     //
 | |
|     if (!Attempt->ValidiBFTPath) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     NvData     = &Attempt->SessionConfigData;
 | |
|     AuthConfig = &Attempt->AuthConfigData.CHAP;
 | |
| 
 | |
|     //
 | |
|     // Fill the Nic section.
 | |
|     //
 | |
| 
 | |
|     Nic->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_ID;
 | |
|     Nic->Header.Version     = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_VERSION;
 | |
|     Nic->Header.Length      = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE);
 | |
|     Nic->Header.Index       = (UINT8) Index;
 | |
|     Nic->Header.Flags       = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BLOCK_VALID |
 | |
|                             EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_GLOBAL;
 | |
| 
 | |
|     if (Index == 0) {
 | |
|       Nic->Header.Flags    |= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BOOT_SELECTED;
 | |
|     }
 | |
| 
 | |
|     if (NvData->InitiatorInfoFromDhcp) {
 | |
|       Nic->Origin = IpPrefixOriginDhcp;
 | |
|     } else {
 | |
|       Nic->Origin = IpPrefixOriginManual;
 | |
|     }
 | |
| 
 | |
|     if (NvData->IpMode == IP_MODE_IP4 || NvData->IpMode == IP_MODE_AUTOCONFIG) {
 | |
|       //
 | |
|       // Get the subnet mask prefix length.
 | |
|       //
 | |
|       Nic->SubnetMaskPrefixLength = IScsiGetSubnetMaskPrefixLength (&NvData->SubnetMask);
 | |
| 
 | |
|       //
 | |
|       // Map the various v4 addresses into v6 addresses.
 | |
|       //
 | |
|       IScsiMapV4ToV6Addr (&NvData->LocalIp.v4, &Nic->Ip);
 | |
|       IScsiMapV4ToV6Addr (&NvData->Gateway.v4, &Nic->Gateway);
 | |
|       IScsiMapV4ToV6Addr (&Attempt->PrimaryDns.v4, &Nic->PrimaryDns);
 | |
|       IScsiMapV4ToV6Addr (&Attempt->SecondaryDns.v4, &Nic->SecondaryDns);
 | |
|       IScsiMapV4ToV6Addr (&Attempt->DhcpServer.v4, &Nic->DhcpServer);
 | |
| 
 | |
|     } else if (NvData->IpMode == IP_MODE_IP6 || NvData->IpMode == IP_MODE_AUTOCONFIG) {
 | |
| 
 | |
|       Nic->SubnetMaskPrefixLength = NvData->PrefixLength;
 | |
|       CopyMem (&Nic->Ip, &NvData->LocalIp, sizeof (EFI_IPv6_ADDRESS));
 | |
|       CopyMem (&Nic->Gateway, &NvData->Gateway, sizeof (EFI_IPv6_ADDRESS));
 | |
|       CopyMem (&Nic->PrimaryDns, &Attempt->PrimaryDns, sizeof (EFI_IPv6_ADDRESS));
 | |
|       CopyMem (&Nic->SecondaryDns, &Attempt->SecondaryDns, sizeof (EFI_IPv6_ADDRESS));
 | |
|       CopyMem (&Nic->DhcpServer, &Attempt->DhcpServer, sizeof (EFI_IPv6_ADDRESS));
 | |
| 
 | |
|     } else {
 | |
|       ASSERT (FALSE);
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Get Nic Info: VLAN tag, Mac address, PCI location.
 | |
|     //
 | |
|     NicInfo = IScsiGetNicInfoByIndex (Attempt->NicIndex);
 | |
|     ASSERT (NicInfo != NULL);
 | |
| 
 | |
|     Nic->VLanTag = NicInfo->VlanId;
 | |
|     CopyMem (Nic->Mac, &NicInfo->PermanentAddress, sizeof (Nic->Mac));
 | |
|     Nic->PciLocation = (UINT16) ((NicInfo->BusNumber << 8)    |
 | |
|                                  (NicInfo->DeviceNumber << 3) | NicInfo->FunctionNumber);
 | |
|     *SectionOffset    = (UINT16) ((UINTN) Nic - (UINTN) Table);
 | |
|     SectionOffset++;
 | |
| 
 | |
|     //
 | |
|     // Fill the Target section.
 | |
|     //
 | |
| 
 | |
|     Target->Header.StructureId  = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID;
 | |
|     Target->Header.Version      = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION;
 | |
|     Target->Header.Length       = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE);
 | |
|     Target->Header.Index        = (UINT8) Index;
 | |
|     Target->Header.Flags        = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BLOCK_VALID;
 | |
| 
 | |
|     if (Index == 0) {
 | |
|       Target->Header.Flags     |= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BOOT_SELECTED;
 | |
|     }
 | |
| 
 | |
|     Target->Port                = NvData->TargetPort;
 | |
| 
 | |
|     if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
 | |
|       if (AuthConfig->CHAPType == ISCSI_CHAP_UNI) {
 | |
|         Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_CHAP;
 | |
|       } else if (AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL) {
 | |
|         Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP;
 | |
|       }
 | |
|     } else if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_NONE) {
 | |
|       Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_NO_CHAP;
 | |
|     }
 | |
| 
 | |
|     Target->NicIndex            = (UINT8) Index;
 | |
| 
 | |
|     if (NvData->IpMode == IP_MODE_IP4 || NvData->IpMode == IP_MODE_AUTOCONFIG) {
 | |
|       IScsiMapV4ToV6Addr (&NvData->TargetIp.v4, &Target->Ip);
 | |
|     } else if (NvData->IpMode == IP_MODE_IP6 || NvData->IpMode == IP_MODE_AUTOCONFIG) {
 | |
|       CopyMem (&Target->Ip, &NvData->TargetIp, sizeof (EFI_IPv6_ADDRESS));
 | |
|     } else {
 | |
|       ASSERT (FALSE);
 | |
|     }
 | |
| 
 | |
|     CopyMem (Target->BootLun, NvData->BootLun, sizeof (Target->BootLun));
 | |
| 
 | |
|     //
 | |
|     // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.
 | |
|     //
 | |
|     Length = (UINT16) AsciiStrLen (NvData->TargetName);
 | |
|     IScsiAddHeapItem (Heap, NvData->TargetName, Length);
 | |
| 
 | |
|     Target->IScsiNameLength = Length;
 | |
|     Target->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
 | |
| 
 | |
|     if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
 | |
|       //
 | |
|       // CHAP Name
 | |
|       //
 | |
|       Length = (UINT16) AsciiStrLen (AuthConfig->CHAPName);
 | |
|       IScsiAddHeapItem (Heap, AuthConfig->CHAPName, Length);
 | |
|       Target->CHAPNameLength  = Length;
 | |
|       Target->CHAPNameOffset  = (UINT16) ((UINTN) *Heap - (UINTN) Table);
 | |
| 
 | |
|       //
 | |
|       // CHAP Secret
 | |
|       //
 | |
|       Length = (UINT16) AsciiStrLen (AuthConfig->CHAPSecret);
 | |
|       IScsiAddHeapItem (Heap, AuthConfig->CHAPSecret, Length);
 | |
|       Target->CHAPSecretLength  = Length;
 | |
|       Target->CHAPSecretOffset  = (UINT16) ((UINTN) *Heap - (UINTN) Table);
 | |
| 
 | |
|       if (Target->CHAPType == EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP) {
 | |
|         //
 | |
|         // Reverse CHAP Name.
 | |
|         //
 | |
|         Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPName);
 | |
|         IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPName, Length);
 | |
|         Target->ReverseCHAPNameLength = Length;
 | |
|         Target->ReverseCHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
 | |
| 
 | |
|         //
 | |
|         // Reverse CHAP Secret.
 | |
|         //
 | |
|         Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPSecret);
 | |
|         IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPSecret, Length);
 | |
|         Target->ReverseCHAPSecretLength = Length;
 | |
|         Target->ReverseCHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     *SectionOffset = (UINT16) ((UINTN) Target - (UINTN) Table);
 | |
|     SectionOffset++;
 | |
| 
 | |
|     //
 | |
|     // Advance to the next NIC/Target pair.
 | |
|     //
 | |
|     Nic    = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Target +
 | |
|            IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE)));
 | |
|     Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
 | |
|            IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
 | |
| 
 | |
|     Index++;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Publish and remove the iSCSI Boot Firmware Table according to the iSCSI
 | |
|   session status.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| IScsiPublishIbft (
 | |
|   IN VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                                    Status;
 | |
|   EFI_ACPI_TABLE_PROTOCOL                       *AcpiTableProtocol;
 | |
|   EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER     *Table;
 | |
|   EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp;
 | |
|   EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt;
 | |
|   EFI_ACPI_DESCRIPTION_HEADER                   *Xsdt;
 | |
|   UINT8                                         *Heap;
 | |
|   UINT8                                         Checksum;
 | |
| 
 | |
|   Rsdt = NULL;
 | |
|   Xsdt = NULL;
 | |
| 
 | |
|   Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return ;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Find ACPI table RSD_PTR from the system table.
 | |
|   //
 | |
|   Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **) &Rsdp);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **) &Rsdp);
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status) || (Rsdp == NULL)) {
 | |
|     return ;
 | |
|   } else if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION && Rsdp->XsdtAddress != 0) {
 | |
|     Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;
 | |
|   } else if (Rsdp->RsdtAddress != 0) {
 | |
|     Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;
 | |
|   }
 | |
| 
 | |
|   if ((Xsdt == NULL) && (Rsdt == NULL)) {
 | |
|     return ;
 | |
|   }
 | |
| 
 | |
|   if (mIbftInstalled) {
 | |
|     Status = AcpiTableProtocol->UninstallAcpiTable (
 | |
|                                   AcpiTableProtocol,
 | |
|                                   mTableKey
 | |
|                                   );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return ;
 | |
|     }
 | |
|     mIbftInstalled = FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If there is no valid attempt configuration, just return.
 | |
|   //
 | |
|   if ((!mPrivate->EnableMpio && mPrivate->ValidSinglePathCount == 0) ||
 | |
|       (mPrivate->EnableMpio && mPrivate->MpioCount <= mPrivate->Krb5MpioCount)) {
 | |
|     return ;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Allocate 4k bytes to hold the ACPI table.
 | |
|   //
 | |
|   Table = AllocateZeroPool (IBFT_MAX_SIZE);
 | |
|   if (Table == NULL) {
 | |
|     return ;
 | |
|   }
 | |
| 
 | |
|   Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;
 | |
| 
 | |
|   //
 | |
|   // Fill in the various section of the iSCSI Boot Firmware Table.
 | |
|   //
 | |
|   if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) {
 | |
|     IScsiInitIbfTableHeader (Table, Xsdt->OemId, &Xsdt->OemTableId);
 | |
|   } else {
 | |
|     IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId);
 | |
|   }
 | |
| 
 | |
|   IScsiInitControlSection (Table);
 | |
|   IScsiFillInitiatorSection (Table, &Heap);
 | |
|   IScsiFillNICAndTargetSections (Table, &Heap);
 | |
| 
 | |
|   Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length);
 | |
|   Table->Checksum = Checksum;
 | |
| 
 | |
|   //
 | |
|   // Install or update the iBFT table.
 | |
|   //
 | |
|   Status = AcpiTableProtocol->InstallAcpiTable (
 | |
|                                 AcpiTableProtocol,
 | |
|                                 Table,
 | |
|                                 Table->Length,
 | |
|                                 &mTableKey
 | |
|                                 );
 | |
|   if (EFI_ERROR(Status)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   mIbftInstalled = TRUE;
 | |
|   FreePool (Table);
 | |
| }
 |