/** @file BMC ACPI. Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ // // Statements that include other header files // #include #include #include #include #include #include #include #include #include #include #include #include #ifndef EFI_ACPI_CREATOR_ID #define EFI_ACPI_CREATOR_ID SIGNATURE_32 ('M', 'S', 'F', 'T') #endif #ifndef EFI_ACPI_CREATOR_REVISION #define EFI_ACPI_CREATOR_REVISION 0x0100000D #endif /** Locate the first instance of a protocol. If the protocol requested is an FV protocol, then it will return the first FV that contains the ACPI table storage file. @param Protocol - The protocol to find. Instance - Return pointer to the first instance of the protocol. Type - The type of protocol to locate. @retval EFI_SUCCESS - The function completed successfully. @retval EFI_NOT_FOUND - The protocol could not be located. @retval EFI_OUT_OF_RESOURCES - There are not enough resources to find the protocol. **/ EFI_STATUS LocateSupportProtocol ( IN EFI_GUID *Protocol, OUT VOID **Instance, IN UINT32 Type ) { EFI_STATUS Status; EFI_HANDLE *HandleBuffer; UINTN NumberOfHandles; EFI_FV_FILETYPE FileType; UINT32 FvStatus = 0; EFI_FV_FILE_ATTRIBUTES Attributes; UINTN Size; UINTN Index; Status = gBS->LocateHandleBuffer (ByProtocol, Protocol, NULL, &NumberOfHandles, &HandleBuffer); if (EFI_ERROR (Status)) { return Status; } // // Looking for FV with ACPI storage file // for (Index = 0; Index < NumberOfHandles; Index++) { Status = gBS->HandleProtocol (HandleBuffer[Index], Protocol, Instance); ASSERT (!EFI_ERROR (Status)); if (!Type) { // // Not looking for the FV protocol, so find the first instance of the // protocol. There should not be any errors because our handle buffer // should always contain at least one or LocateHandleBuffer would have // returned not found. // break; } // // See if it has the ACPI storage file // Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL *) (*Instance))->ReadFile ( *Instance, &gEfiCallerIdGuid, NULL, &Size, &FileType, &Attributes, &FvStatus ); // // If we found it, then we are done // if (!EFI_ERROR (Status)) { break; } } gBS->FreePool (HandleBuffer); return Status; } EFI_STATUS UpdateDeviceSsdtTable ( IN OUT EFI_ACPI_COMMON_HEADER *Table ) { EFI_ACPI_DESCRIPTION_HEADER *TableHeader = NULL; UINT64 TempOemTableId; UINT8 *DataPtr; EFI_ACPI_IO_PORT_DESCRIPTOR *IoRsc; TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *)Table; // // Update the OEMID and OEM Table ID. // CopyMem (&TableHeader->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof(TableHeader->OemId)); TempOemTableId = PcdGet64 (PcdAcpiDefaultOemTableId); CopyMem (&TableHeader->OemTableId, &TempOemTableId, sizeof(UINT64)); TableHeader->CreatorId = EFI_ACPI_CREATOR_ID; TableHeader->CreatorRevision = EFI_ACPI_CREATOR_REVISION; // // Update IO(Decode16, 0xCA2, 0xCA2, 0, 2) // DEBUG ((DEBUG_INFO, "UpdateDeviceSsdtTable - IPMI\n")); for (DataPtr = (UINT8 *)(Table + 1); DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length - 4); DataPtr++) { if (CompareMem(DataPtr, "_CRS", 4) == 0) { DataPtr += 4; // Skip _CRS ASSERT (*DataPtr == AML_BUFFER_OP); DataPtr ++; // Skip AML_BUFFER_OP ASSERT ((*DataPtr & (BIT7|BIT6)) == 0); DataPtr ++; // Skip PkgLength - 0xD ASSERT ((*DataPtr) == AML_BYTE_PREFIX); DataPtr ++; // Skip BufferSize OpCode DataPtr ++; // Skip BufferSize - 0xA IoRsc = (VOID *)DataPtr; ASSERT (IoRsc->Header.Bits.Type == ACPI_SMALL_ITEM_FLAG); ASSERT (IoRsc->Header.Bits.Name == ACPI_SMALL_IO_PORT_DESCRIPTOR_NAME); ASSERT (IoRsc->Header.Bits.Length == sizeof(EFI_ACPI_IO_PORT_DESCRIPTOR) - sizeof(ACPI_SMALL_RESOURCE_HEADER)); DEBUG ((DEBUG_INFO, "IPMI IO Base in ASL update - 0x%04x <= 0x%04x\n", IoRsc->BaseAddressMin, PcdGet16(PcdIpmiIoBaseAddress))); IoRsc->BaseAddressMin = PcdGet16(PcdIpmiIoBaseAddress); IoRsc->BaseAddressMax = PcdGet16(PcdIpmiIoBaseAddress); } } return EFI_SUCCESS; } /** Entry point for Acpi platform driver. @param ImageHandle - A handle for the image that is initializing this driver. @param SystemTable - A pointer to the EFI system table. @retval EFI_SUCCESS - Driver initialized successfully. @retval EFI_LOAD_ERROR - Failed to Initialize or has been loaded. @retval EFI_OUT_OF_RESOURCES - Could not allocate needed resources. **/ EFI_STATUS EFIAPI BmcAcpiEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_STATUS AcpiStatus; EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; INTN Instance = 0; EFI_ACPI_COMMON_HEADER *CurrentTable = NULL; UINTN TableHandle = 0; UINT32 FvStatus; UINT32 Size; EFI_ACPI_TABLE_PROTOCOL *AcpiTable; UINTN TableSize; // // Find the AcpiTable protocol // Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable); if (EFI_ERROR (Status)) { return EFI_ABORTED; } // // Locate the firmware volume protocol // Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID **) &FwVol, 1); if (EFI_ERROR (Status)) { return Status; } Status = EFI_SUCCESS; Instance = 0; // // Read tables from the storage file. // while (!EFI_ERROR (Status)) { CurrentTable = NULL; Status = FwVol->ReadSection ( FwVol, &gEfiCallerIdGuid, EFI_SECTION_RAW, Instance, (VOID **) &CurrentTable, (UINTN *) &Size, &FvStatus ); if (!EFI_ERROR (Status)) { // // Perform any table specific updates. // AcpiStatus = UpdateDeviceSsdtTable (CurrentTable); if (!EFI_ERROR (AcpiStatus)) { TableHandle = 0; TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length; ASSERT (Size >= TableSize); Status = AcpiTable->InstallAcpiTable ( AcpiTable, CurrentTable, TableSize, &TableHandle ); ASSERT_EFI_ERROR (Status); } // // Increment the instance // Instance++; } } return EFI_SUCCESS; }