示例#1
0
/**
  Check the direction to program variable MTRRs.

  This function determines which direction of programming the variable
  MTRRs will use fewer MTRRs.

  @param  Input       Length of Memory to program MTRR
  @param  MtrrNumber  Pointer to the number of necessary MTRRs

  @retval TRUE        Positive direction is better.
          FALSE       Negtive direction is better.

**/
BOOLEAN
GetDirection (
  IN UINT64      Input,
  IN UINTN       *MtrrNumber
  )
{
  UINT64  TempQword;
  UINT32  Positive;
  UINT32  Subtractive;

  TempQword   = Input;
  Positive    = 0;
  Subtractive = 0;

  do {
    TempQword -= Power2MaxMemory (TempQword);
    Positive++;
  } while (TempQword != 0);

  TempQword = Power2MaxMemory (LShiftU64 (Input, 1)) - Input;
  Subtractive++;
  do {
    TempQword -= Power2MaxMemory (TempQword);
    Subtractive++;
  } while (TempQword != 0);

  if (Positive <= Subtractive) {
    *MtrrNumber = Positive;
    return TRUE;
  } else {
    *MtrrNumber = Subtractive;
    return FALSE;
  }
}
示例#2
0
/**
  Determine the MTRR numbers used to program a memory range.

  This function first checks the alignment of the base address. If the alignment of the base address <= Length,
  cover the memory range (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and Length -= alignment.
  Repeat the step until alignment > Length.

  Then this function determines which direction of programming the variable MTRRs for the remaining length
  will use fewer MTRRs.

  @param  BaseAddress Length of Memory to program MTRR
  @param  Length      Length of Memory to program MTRR
  @param  MtrrNumber  Pointer to the number of necessary MTRRs

  @retval TRUE        Positive direction is better.
          FALSE       Negtive direction is better.

**/
BOOLEAN
GetMtrrNumberAndDirection (
  IN UINT64      BaseAddress,
  IN UINT64      Length,
  IN UINTN       *MtrrNumber
  )
{
  UINT64  TempQword;
  UINT64  Alignment;
  UINT32  Positive;
  UINT32  Subtractive;

  *MtrrNumber = 0;

  if (BaseAddress != 0) {
    do {
      //
      // Calculate the alignment of the base address.
      //
      Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));

      if (Alignment > Length) {
        break;
      }

      (*MtrrNumber)++;
      BaseAddress += Alignment;
      Length -= Alignment;
    } while (TRUE);

    if (Length == 0) {
      return TRUE;
    }
  }

  TempQword   = Length;
  Positive    = 0;
  Subtractive = 0;

  do {
    TempQword -= Power2MaxMemory (TempQword);
    Positive++;
  } while (TempQword != 0);

  TempQword = Power2MaxMemory (LShiftU64 (Length, 1)) - Length;
  Subtractive++;
  do {
    TempQword -= Power2MaxMemory (TempQword);
    Subtractive++;
  } while (TempQword != 0);

  if (Positive <= Subtractive) {
    *MtrrNumber += Positive;
    return TRUE;
  } else {
    *MtrrNumber += Subtractive;
    return FALSE;
  }
}
示例#3
0
/**
  This function attempts to set the attributes for a memory range.

  @param  BaseAddress            The physical address that is the start
                                 address of a memory region.
  @param  Length                 The size in bytes of the memory region.
  @param  Attributes             The bit mask of attributes to set for the
                                 memory region.

  @retval RETURN_SUCCESS            The attributes were set for the memory
                                    region.
  @retval RETURN_INVALID_PARAMETER  Length is zero.
  @retval RETURN_UNSUPPORTED        The processor does not support one or
                                    more bytes of the memory resource range
                                    specified by BaseAddress and Length.
  @retval RETURN_UNSUPPORTED        The bit mask of attributes is not support
                                    for the memory resource range specified
                                    by BaseAddress and Length.
  @retval RETURN_ACCESS_DENIED      The attributes for the memory resource
                                    range specified by BaseAddress and Length
                                    cannot be modified.
  @retval RETURN_OUT_OF_RESOURCES   There are not enough system resources to
                                    modify the attributes of the memory
                                    resource range.

**/
RETURN_STATUS
EFIAPI
MtrrSetMemoryAttribute (
  IN PHYSICAL_ADDRESS        BaseAddress,
  IN UINT64                  Length,
  IN MTRR_MEMORY_CACHE_TYPE  Attribute
  )
{
  UINT64                    TempQword;
  RETURN_STATUS             Status;
  UINT64                    MemoryType;
  UINT64                    Alignment;
  BOOLEAN                   OverLap;
  BOOLEAN                   Positive;
  UINT32                    MsrNum;
  UINTN                     MtrrNumber;
  VARIABLE_MTRR             VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
  UINT32                    UsedMtrr;
  UINT64                    MtrrValidBitsMask;
  UINT64                    MtrrValidAddressMask;
  BOOLEAN                   OverwriteExistingMtrr;
  UINT32                    FirmwareVariableMtrrCount;
  UINT32                    VariableMtrrEnd;
  MTRR_CONTEXT              MtrrContext;

  DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));

  if (!IsMtrrSupported ()) {
    Status = RETURN_UNSUPPORTED;
    goto Done;
  }

  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
  VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;

  MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);

  TempQword = 0;
  MemoryType = (UINT64)Attribute;
  OverwriteExistingMtrr = FALSE;

  //
  // Check for an invalid parameter
  //
  if (Length == 0) {
    Status = RETURN_INVALID_PARAMETER;
    goto Done;
  }

  if (
       (BaseAddress & ~MtrrValidAddressMask) != 0 ||
       (Length & ~MtrrValidAddressMask) != 0
     ) {
    Status = RETURN_UNSUPPORTED;
    goto Done;
  }

  //
  // Check if Fixed MTRR
  //
  Status = RETURN_SUCCESS;
  while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {
    PreMtrrChange (&MtrrContext);
    Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length);
    PostMtrrChange (&MtrrContext);
    if (RETURN_ERROR (Status)) {
      goto Done;
    }
  }

  if (Length == 0) {
    //
    // A Length of 0 can only make sense for fixed MTTR ranges.
    // Since we just handled the fixed MTRRs, we can skip the
    // variable MTRR section.
    //
    goto Done;
  }

  //
  // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
  // we can set the base to 0 to save variable MTRRs.
  //
  if (BaseAddress == BASE_1MB) {
    BaseAddress = 0;
    Length += SIZE_1MB;
  }

  //
  // Check for overlap
  //
  UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);
  OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr);
  if (OverLap) {
    Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr);
    if (RETURN_ERROR (Status)) {
      goto Done;
    }

    if (Length == 0) {
      //
      // Combined successfully, invalidate the now-unused MTRRs
      //
      InvalidateMtrr(VariableMtrr);
      Status = RETURN_SUCCESS;
      goto Done;
    }
  }

  //
  // The memory type is the same with the type specified by
  // MTRR_LIB_IA32_MTRR_DEF_TYPE.
  //
  if ((!OverwriteExistingMtrr) && (Attribute == MtrrGetDefaultMemoryType ())) {
    //
    // Invalidate the now-unused MTRRs
    //
    InvalidateMtrr(VariableMtrr);
    goto Done;
  }

  Positive = GetMtrrNumberAndDirection (BaseAddress, Length, &MtrrNumber);

  if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) {
    Status = RETURN_OUT_OF_RESOURCES;
    goto Done;
  }

  //
  // Invalidate the now-unused MTRRs
  //
  InvalidateMtrr(VariableMtrr);

  //
  // Find first unused MTRR
  //
  for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;
       MsrNum < VariableMtrrEnd;
       MsrNum += 2
      ) {
    if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
      break;
    }
  }

  if (BaseAddress != 0) {
    do {
      //
      // Calculate the alignment of the base address.
      //
      Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));

      if (Alignment > Length) {
        break;
      }

      //
      // Find unused MTRR
      //
      for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
        if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
          break;
        }
      }

      ProgramVariableMtrr (
        MsrNum,
        BaseAddress,
        Alignment,
        MemoryType,
        MtrrValidAddressMask
        );
      BaseAddress += Alignment;
      Length -= Alignment;
    } while (TRUE);

    if (Length == 0) {
      goto Done;
    }
  }

  TempQword = Length;

  if (!Positive) {
    Length = Power2MaxMemory (LShiftU64 (TempQword, 1));

    //
    // Find unused MTRR
    //
    for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
      if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
        break;
      }
    }

    ProgramVariableMtrr (
      MsrNum,
      BaseAddress,
      Length,
      MemoryType,
      MtrrValidAddressMask
      );
    BaseAddress += Length;
    TempQword   = Length - TempQword;
    MemoryType  = MTRR_CACHE_UNCACHEABLE;
  }

  do {
    //
    // Find unused MTRR
    //
    for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
      if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
        break;
      }
    }

    Length = Power2MaxMemory (TempQword);
    if (!Positive) {
      BaseAddress -= Length;
    }

    ProgramVariableMtrr (
      MsrNum,
      BaseAddress,
      Length,
      MemoryType,
      MtrrValidAddressMask
      );

    if (Positive) {
      BaseAddress += Length;
    }
    TempQword -= Length;

  } while (TempQword > 0);

Done:
  DEBUG((DEBUG_CACHE, "  Status = %r\n", Status));
  if (!RETURN_ERROR (Status)) {
    MtrrDebugPrintAllMtrrs ();
  }

  return Status;
}
示例#4
0
/**
  This function attempts to set the attributes for a memory range.

  @param  BaseAddress            The physical address that is the start
                                 address of a memory region.
  @param  Length                 The size in bytes of the memory region.
  @param  Attributes             The bit mask of attributes to set for the
                                 memory region.

  @retval RETURN_SUCCESS            The attributes were set for the memory
                                    region.
  @retval RETURN_INVALID_PARAMETER  Length is zero.
  @retval RETURN_UNSUPPORTED        The processor does not support one or
                                    more bytes of the memory resource range
                                    specified by BaseAddress and Length.
  @retval RETURN_UNSUPPORTED        The bit mask of attributes is not support
                                    for the memory resource range specified
                                    by BaseAddress and Length.
  @retval RETURN_ACCESS_DENIED      The attributes for the memory resource
                                    range specified by BaseAddress and Length
                                    cannot be modified.
  @retval RETURN_OUT_OF_RESOURCES   There are not enough system resources to
                                    modify the attributes of the memory
                                    resource range.

**/
RETURN_STATUS
EFIAPI
MtrrSetMemoryAttribute (
  IN PHYSICAL_ADDRESS        BaseAddress,
  IN UINT64                  Length,
  IN MTRR_MEMORY_CACHE_TYPE  Attribute
  )
{
  UINT64                    TempQword;
  RETURN_STATUS             Status;
  UINT64                    MemoryType;
  UINT64                    Remainder;
  BOOLEAN                   OverLap;
  BOOLEAN                   Positive;
  UINT32                    MsrNum;
  UINTN                     MtrrNumber;
  VARIABLE_MTRR             VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
  UINT32                    UsedMtrr;
  UINT64                    MtrrValidBitsMask;
  UINT64                    MtrrValidAddressMask;
  UINTN                     Cr4;
  BOOLEAN                   OverwriteExistingMtrr;
  UINT32                    FirmwareVariableMtrrCount;
  UINT32                    VariableMtrrEnd;

  if (!IsMtrrSupported ()) {
    return RETURN_UNSUPPORTED;
  }

  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();
  VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;

  MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);

  TempQword = 0;
  MemoryType = (UINT64)Attribute;
  OverwriteExistingMtrr = FALSE;

  //
  // Check for an invalid parameter
  //
  if (Length == 0) {
    return RETURN_INVALID_PARAMETER;
  }

  if (
       (BaseAddress &~MtrrValidAddressMask) != 0 ||
       (Length &~MtrrValidAddressMask) != 0
     ) {
    return RETURN_UNSUPPORTED;
  }

  //
  // Check if Fixed MTRR
  //
  Status = RETURN_SUCCESS;
  while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {
    Cr4 = PreMtrrChange ();
    Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length);
    PostMtrrChange (Cr4);
    if (RETURN_ERROR (Status)) {
      return Status;
    }
  }

  if (Length == 0) {
    //
    // A Length of 0 can only make sense for fixed MTTR ranges.
    // Since we just handled the fixed MTRRs, we can skip the
    // variable MTRR section.
    //
    goto Done;
  }

  //
  // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
  // we can set the bade to 0 to save variable MTRRs.
  //
  if (BaseAddress == BASE_1MB) {
    BaseAddress = 0;
    Length += SIZE_1MB;
  }

  //
  // Check memory base address alignment
  //
  DivU64x64Remainder (BaseAddress, Power2MaxMemory (LShiftU64 (Length, 1)), &Remainder);
  if (Remainder != 0) {
    DivU64x64Remainder (BaseAddress, Power2MaxMemory (Length), &Remainder);
    if (Remainder != 0) {
      Status = RETURN_UNSUPPORTED;
      goto Done;
    }
  }

  //
  // Check for overlap
  //
  UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);
  OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr);
  if (OverLap) {
    Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr);
    if (RETURN_ERROR (Status)) {
      goto Done;
    }

    if (Length == 0) {
      //
      // Combined successfully
      //
      Status = RETURN_SUCCESS;
      goto Done;
    }
  }

  //
  // Program Variable MTRRs
  //
  // Avoid hardcode here and read data dynamically
  //
  if (UsedMtrr >= FirmwareVariableMtrrCount) {
    Status = RETURN_OUT_OF_RESOURCES;
    goto Done;
  }

  //
  // The memory type is the same with the type specified by
  // MTRR_LIB_IA32_MTRR_DEF_TYPE.
  //
  if ((!OverwriteExistingMtrr) && (Attribute == GetMtrrDefaultMemoryType ())) {
    //
    // Invalidate the now-unused MTRRs
    //
    InvalidateMtrr(VariableMtrr);
    goto Done;
  }

  TempQword = Length;


  if (TempQword == Power2MaxMemory (TempQword)) {
    //
    // Invalidate the now-unused MTRRs
    //
    InvalidateMtrr(VariableMtrr);

    //
    // Find first unused MTRR
    //
    for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;
         MsrNum < VariableMtrrEnd;
         MsrNum += 2
        ) {
      if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
        break;
      }
    }

    ProgramVariableMtrr (
      MsrNum,
      BaseAddress,
      Length,
      MemoryType,
      MtrrValidAddressMask
      );
  } else {

    Positive = GetDirection (TempQword, &MtrrNumber);

    if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) {
      Status = RETURN_OUT_OF_RESOURCES;
      goto Done;
    }

    //
    // Invalidate the now-unused MTRRs
    //
    InvalidateMtrr(VariableMtrr);

    //
    // Find first unused MTRR
    //
    for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;
         MsrNum < VariableMtrrEnd;
         MsrNum += 2
        ) {
      if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
        break;
      }
    }

    if (!Positive) {
      Length = Power2MaxMemory (LShiftU64 (TempQword, 1));
      ProgramVariableMtrr (
        MsrNum,
        BaseAddress,
        Length,
        MemoryType,
        MtrrValidAddressMask
        );
      BaseAddress += Length;
      TempQword   = Length - TempQword;
      MemoryType  = MTRR_CACHE_UNCACHEABLE;
    }

    do {
      //
      // Find unused MTRR
      //
      for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {
        if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {
          break;
        }
      }

      Length = Power2MaxMemory (TempQword);
      if (!Positive) {
        BaseAddress -= Length;
      }

      ProgramVariableMtrr (
        MsrNum,
        BaseAddress,
        Length,
        MemoryType,
        MtrrValidAddressMask
        );

      if (Positive) {
        BaseAddress += Length;
      }
      TempQword -= Length;

    } while (TempQword > 0);
  }

Done:
  return Status;

}
示例#5
0
EFI_STATUS
EFIAPI
SubmitResources (
  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
  IN EFI_HANDLE                                       RootBridgeHandle,
  IN VOID                                             *Configuration
  )
/*++

Routine Description:
  Submits the I/O and memory resource requirements for the specified PCI Root Bridge
  
Arguments:
  This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
  RootBridgeHandle -- The PCI Root Bridge whose I/O and memory resource requirements 
                      are being submitted
  Configuration -- The pointer to the PCI I/O and PCI memory resource descriptor                    
Returns:

--*/
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
{
  EFI_LIST_ENTRY                    *List;
  PCI_HOST_BRIDGE_INSTANCE          *HostBridgeInstance;
  PCI_ROOT_BRIDGE_INSTANCE          *RootBridgeInstance;
  UINT8                             *Temp;
  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
  UINT64                            AddrLen;
  UINT64                            Alignment;

  //
  // Check the input parameter: Configuration
  //
  if (Configuration == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  HostBridgeInstance  = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
  List                = HostBridgeInstance->Head.ForwardLink;

  Temp                = (UINT8 *) Configuration;
  while (*Temp == 0x8A) {
    Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
  }

  if (*Temp != 0x79) {
    return EFI_INVALID_PARAMETER;
  }

  Temp = (UINT8 *) Configuration;
  while (List != &HostBridgeInstance->Head) {
    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
    if (RootBridgeHandle == RootBridgeInstance->Handle) {
      while (*Temp == 0x8A) {
        ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;

        //
        // Check Address Length
        //
        if (ptr->AddrLen > 0xffffffff) {
          return EFI_INVALID_PARAMETER;
        }

        //
        // Check address range alignment
        //
        if (ptr->AddrRangeMax >= 0xffffffff || 
            ptr->AddrRangeMax != (Power2MaxMemory(ptr->AddrRangeMax + 1) - 1)) {
          return EFI_INVALID_PARAMETER;
        }

        switch (ptr->ResType) {
        case 0:
          //
          // Check invalid Address Sapce Granularity
          //
          if (ptr->AddrSpaceGranularity != 32) {
            return EFI_INVALID_PARAMETER;
          }
            
          //
          // check the memory resource request is supported by PCI root bridge
          //
            if (RootBridgeInstance->RootBridgeAttrib == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
                ptr->SpecificFlag == 0x06 ) {
            return EFI_INVALID_PARAMETER;
          }

          AddrLen   = ptr->AddrLen;
          Alignment = ptr->AddrRangeMax;
          if (ptr->AddrSpaceGranularity == 32) {
            if (ptr->SpecificFlag == 0x06) {
              //
              // Apply from GCD
              //
              RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted;
            } else {
              RootBridgeInstance->ResAllocNode[TypeMem32].Length    = AddrLen;
              RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;
              RootBridgeInstance->ResAllocNode[TypeMem32].Status    = ResRequested;
              HostBridgeInstance->ResourceSubmited                  = TRUE;
            }
          }

          if (ptr->AddrSpaceGranularity == 64) {
            if (ptr->SpecificFlag == 0x06) {
              RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;
            } else {
              RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted;
            }
          }
          break;

        case 1:
          AddrLen   = (UINTN) ptr->AddrLen;
          Alignment = (UINTN) ptr->AddrRangeMax;
          RootBridgeInstance->ResAllocNode[TypeIo].Length     = AddrLen;
          RootBridgeInstance->ResAllocNode[TypeIo].Alignment  = Alignment;
          RootBridgeInstance->ResAllocNode[TypeIo].Status     = ResRequested;
          HostBridgeInstance->ResourceSubmited                = TRUE;
          break;

        default:
          break;
        }

        Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
      }

      return EFI_SUCCESS;
    }

    List = List->ForwardLink;
  }

  return EFI_INVALID_PARAMETER;
}