mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-25 11:55:28 +01:00
538 lines
18 KiB
C
538 lines
18 KiB
C
/** @file
|
|
Implementation for iSCSI Boot Firmware Table publication.
|
|
|
|
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#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);
|
|
}
|