/** @file BMC ACPI. Copyright (c) 2018, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that 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. **/ // // 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, &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, &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; }