diff --git a/Library/OcAcpiLib/OcAcpiLib.c b/Library/OcAcpiLib/OcAcpiLib.c index 76e0c1592f989cc556773aefb6a7680b0f7e5822..c242bbb3d8e60bb1bfb602029c3456333600cd19 100755 --- a/Library/OcAcpiLib/OcAcpiLib.c +++ b/Library/OcAcpiLib/OcAcpiLib.c @@ -263,6 +263,170 @@ AcpiFindName ( return 0; } +STATIC +VOID +AcpiRefreshTableChecksum ( + IN EFI_ACPI_DESCRIPTION_HEADER *Table + ) +{ + UINT32 TablePrintSignature; + + TablePrintSignature = AcpiReadSignature ((EFI_ACPI_COMMON_HEADER *) Table); + Table->Checksum = 0; + Table->Checksum = CalculateCheckSum8 ((UINT8 *) Table, Table->Length); + + DEBUG (( + DEBUG_INFO, + "OCA: Refreshed %.4a checksum to %02x\n", + (CHAR8 *) &TablePrintSignature, + Table->Checksum + )); +} + +STATIC +BOOLEAN +AcpiIsTableWritable ( + IN EFI_ACPI_COMMON_HEADER *Table + ) +{ + UINT32 LengthOriginal; + + LengthOriginal = Table->Length; + (*(volatile UINT32 *)&Table->Length)++; + + if (LengthOriginal == *(volatile UINT32 *)&Table->Length) { + return FALSE; + } + + Table->Length = LengthOriginal; + return TRUE; +} + +STATIC +EFI_STATUS +AcpiAllocateCopyTable ( + IN EFI_ACPI_COMMON_HEADER *Table, + IN UINT32 NewSize OPTIONAL, + OUT EFI_ACPI_COMMON_HEADER **NewTable + ) +{ + EFI_STATUS Status; + UINT32 TablePrintSignature; + EFI_PHYSICAL_ADDRESS NewTableAddress; + + if (NewSize < Table->Length) { + NewSize = Table->Length; + } + + TablePrintSignature = AcpiReadSignature (Table); + + NewTableAddress = BASE_4GB - 1; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES (NewSize), + &NewTableAddress + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_WARN, + "OCA: Failed to allocate %u bytes for table %.4a\n", + NewSize, + (CHAR8 *) &TablePrintSignature + )); + return Status; + } + + *NewTable = (EFI_ACPI_COMMON_HEADER *)(UINTN) NewTableAddress; + + DEBUG (( + DEBUG_INFO, + "OCA: Allocated new table %.4a at %p\n", + (CHAR8 *) &TablePrintSignature, + *NewTable + )); + + CopyMem (*NewTable, Table, Table->Length); + ZeroMem (((UINT8 *) *NewTable) + Table->Length, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (NewSize)) - Table->Length); + (*NewTable)->Length = NewSize; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +AcpiAllocateCopyFadt ( + IN OUT OC_ACPI_CONTEXT *Context, + IN UINT32 NewSize + ) +{ + EFI_STATUS Status; + EFI_ACPI_COMMON_HEADER *NewFadt; + UINT32 Index; + + Status = AcpiAllocateCopyTable ( + (EFI_ACPI_COMMON_HEADER *) Context->Fadt, + NewSize, + &NewFadt + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < Context->NumberOfTables; ++Index) { + // + // There is a possibility for multiple FADT tables. + // + if (Context->Tables[Index]->Signature == EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { + Context->Tables[Index] = NewFadt; + } + } + Context->Fadt = (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE *) NewFadt; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +AcpiAllocateCopyDsdt ( + IN OUT OC_ACPI_CONTEXT *Context, + IN EFI_ACPI_DESCRIPTION_HEADER *NewDsdt OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_ACPI_COMMON_HEADER *AllocatedDsdt; + + Status = AcpiAllocateCopyTable ( + (EFI_ACPI_COMMON_HEADER *) (NewDsdt != NULL ? NewDsdt : Context->Dsdt), + 0, + &AllocatedDsdt + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Reallocate FADT if needed. + // + if (!AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Context->Fadt)) { + Status = AcpiAllocateCopyFadt (Context, 0); + if (EFI_ERROR (Status)) { + FreePool (AllocatedDsdt); + return Status; + } + } + + if (Context->Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE, XDsdt) + sizeof (Context->Fadt->XDsdt)) { + Context->Fadt->XDsdt = (UINT64)(UINTN) AllocatedDsdt; + } + Context->Fadt->Dsdt = (UINT32)(UINTN) AllocatedDsdt; + AcpiRefreshTableChecksum ((EFI_ACPI_DESCRIPTION_HEADER *) Context->Fadt); + + Context->Dsdt = (EFI_ACPI_DESCRIPTION_HEADER *) AllocatedDsdt; + + return EFI_SUCCESS; +} + /** Load ACPI table regions. @@ -624,6 +788,15 @@ AcpiInitContext ( Context->Dsdt->Length, Index )); + + if ((UINTN)Context->Dsdt < BASE_1MB) { + DEBUG (( + DEBUG_INFO, + "OCA: Unlocking DSDT at %p\n", + Context->Dsdt + )); + LegacyRegionUnlock ((UINT32)(UINTN)Context->Tables[DstIndex], Context->Tables[DstIndex]->Length); + } } ++DstIndex; @@ -850,7 +1023,7 @@ AcpiInsertTable ( { EFI_ACPI_COMMON_HEADER *Common; EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS Table; + EFI_ACPI_COMMON_HEADER *NewTable; EFI_ACPI_COMMON_HEADER **NewTables; BOOLEAN ReplaceDsdt; UINT32 TablePrintSignature; @@ -887,54 +1060,37 @@ AcpiInsertTable ( Context->AllocatedTables += 2; } - Table = BASE_4GB - 1; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIMemoryNVS, - EFI_SIZE_TO_PAGES (Length), - &Table - ); - - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "OCA: Failed to allocate %u bytes for inserted ACPI table\n", Length)); - return Status; - } - - CopyMem ((UINT8 *)(UINTN)Table, Data, Length); - ZeroMem ((UINT8 *)(UINTN)Table + Length, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Length)) - Length); - if (ReplaceDsdt) { DEBUG (( DEBUG_INFO, "OCA: Replaced DSDT of %u bytes into ACPI\n", Common->Length )); - Context->Dsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Table; - if (Context->Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE, XDsdt) + sizeof (Context->Fadt->XDsdt)) { - Context->Fadt->XDsdt = (UINT64)(UINTN) Context->Dsdt; - } - Context->Fadt->Dsdt = (UINT32)(UINTN) Context->Dsdt; - Context->Fadt->Header.Checksum = 0; - Context->Fadt->Header.Checksum = CalculateCheckSum8 ( - (UINT8 *) Context->Fadt, - Context->Fadt->Header.Length - ); + Status = AcpiAllocateCopyDsdt (Context, (EFI_ACPI_DESCRIPTION_HEADER *) Data); + if (EFI_ERROR (Status)) { + return Status; + } } else { - TablePrintSignature = AcpiReadSignature (Common); + Status = AcpiAllocateCopyTable ((EFI_ACPI_COMMON_HEADER *) Data, 0, &NewTable); + if (EFI_ERROR (Status)) { + return Status; + } + + TablePrintSignature = AcpiReadSignature (NewTable); DEBUG (( DEBUG_INFO, "OCA: Inserted table %.4a (%08x) (OEM %016Lx) of %u bytes into ACPI at index %u\n", (CHAR8 *) &TablePrintSignature, - Common->Signature, - AcpiReadOemTableId (Common), - Common->Length, + NewTable->Signature, + AcpiReadOemTableId (NewTable), + NewTable->Length, Context->NumberOfTables )); - Context->Tables[Context->NumberOfTables] = (EFI_ACPI_COMMON_HEADER *)(UINTN)Table; + Context->Tables[Context->NumberOfTables] = NewTable; ++Context->NumberOfTables; } @@ -946,16 +1102,33 @@ AcpiNormalizeHeaders ( IN OUT OC_ACPI_CONTEXT *Context ) { - UINT32 Index; - UINT32 TablePrintSignature; + EFI_STATUS Status; + UINT32 Index; + EFI_ACPI_COMMON_HEADER *NewTable; + UINT32 TablePrintSignature; if (Context->Dsdt != NULL) { + if (!AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Context->Dsdt)) { + Status = AcpiAllocateCopyDsdt (Context, NULL); + if (EFI_ERROR (Status)) { + return; + } + } + if (AcpiNormalizeTableHeaders (Context->Dsdt)) { DEBUG ((DEBUG_INFO, "OCA: Normalized DSDT of %u bytes headers\n", Context->Dsdt->Length)); } } for (Index = 0; Index < Context->NumberOfTables; ++Index) { + if (!AcpiIsTableWritable (Context->Tables[Index])) { + Status = AcpiAllocateCopyTable (Context->Tables[Index], 0, &NewTable); + if (EFI_ERROR (Status)) { + return; + } + Context->Tables[Index] = NewTable; + } + if (AcpiNormalizeTableHeaders ((EFI_ACPI_DESCRIPTION_HEADER *) Context->Tables[Index])) { TablePrintSignature = AcpiReadSignature (Context->Tables[Index]); @@ -978,11 +1151,13 @@ AcpiApplyPatch ( IN OC_ACPI_PATCH *Patch ) { - UINT32 Index; - UINT64 CurrOemTableId; - UINT32 ReplaceCount; - UINT32 ReplaceLimit; - UINT32 TablePrintSignature; + EFI_STATUS Status; + UINT32 Index; + UINT64 CurrOemTableId; + UINT32 ReplaceCount; + UINT32 ReplaceLimit; + UINT32 TablePrintSignature; + EFI_ACPI_COMMON_HEADER *NewTable; DEBUG ((DEBUG_INFO, "OCA: Applying %u byte ACPI patch skip %u, count %u\n", Patch->Size, Patch->Skip, Patch->Count)); @@ -995,6 +1170,13 @@ AcpiApplyPatch ( ReplaceLimit = Context->Dsdt->Length; } + if (!AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Context->Dsdt)) { + Status = AcpiAllocateCopyDsdt (Context, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + } + ReplaceCount = ApplyPatch ( Patch->Find, Patch->Mask, @@ -1017,17 +1199,9 @@ AcpiApplyPatch ( )); if (ReplaceCount > 0) { - Context->Dsdt->Checksum = 0; - Context->Dsdt->Checksum = CalculateCheckSum8 ( - (UINT8 *) Context->Dsdt, - Context->Dsdt->Length - ); + AcpiRefreshTableChecksum (Context->Dsdt); + - DEBUG (( - DEBUG_INFO, - "OCA: Refreshed DSDT checksum to %02x\n", - Context->Dsdt->Checksum - )); } } @@ -1050,6 +1224,14 @@ AcpiApplyPatch ( ReplaceLimit = Context->Tables[Index]->Length; } + if (!AcpiIsTableWritable (Context->Tables[Index])) { + Status = AcpiAllocateCopyTable (Context->Tables[Index], 0, &NewTable); + if (EFI_ERROR (Status)) { + return Status; + } + Context->Tables[Index] = NewTable; + } + ReplaceCount = ApplyPatch ( Patch->Find, Patch->Mask, @@ -1078,17 +1260,7 @@ AcpiApplyPatch ( )); if (ReplaceCount > 0 && Context->Tables[Index]->Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER)) { - ((EFI_ACPI_DESCRIPTION_HEADER *)Context->Tables[Index])->Checksum = 0; - ((EFI_ACPI_DESCRIPTION_HEADER *)Context->Tables[Index])->Checksum = CalculateCheckSum8 ( - (UINT8 *) Context->Tables[Index], - Context->Tables[Index]->Length - ); - - DEBUG (( - DEBUG_INFO, - "OCA: Refreshed checksum to %02x\n", - ((EFI_ACPI_DESCRIPTION_HEADER *)Context->Tables[Index])->Checksum - )); + AcpiRefreshTableChecksum ((EFI_ACPI_DESCRIPTION_HEADER *) Context->Tables[Index]); } } } @@ -1145,7 +1317,9 @@ AcpiRelocateRegions ( IN OUT OC_ACPI_CONTEXT *Context ) { - UINT32 Index; + EFI_STATUS Status; + UINT32 Index; + EFI_ACPI_COMMON_HEADER *NewTable; // // Should not be called before AcpiLoadRegions, but just in case. @@ -1157,11 +1331,26 @@ AcpiRelocateRegions ( } if (Context->Dsdt != NULL) { + if (!AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Context->Dsdt)) { + Status = AcpiAllocateCopyDsdt (Context, NULL); + if (EFI_ERROR (Status)) { + return; + } + } + AcpiRelocateTableRegions (Context, (EFI_ACPI_COMMON_HEADER *) Context->Dsdt); } for (Index = 0; Index < Context->NumberOfTables; ++Index) { if (Context->Tables[Index]->Signature == EFI_ACPI_6_2_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) { + if (!AcpiIsTableWritable (Context->Tables[Index])) { + Status = AcpiAllocateCopyTable (Context->Tables[Index], 0, &NewTable); + if (EFI_ERROR (Status)) { + return; + } + Context->Tables[Index] = NewTable; + } + AcpiRelocateTableRegions (Context, Context->Tables[Index]); } } @@ -1172,12 +1361,9 @@ AcpiFadtEnableReset ( IN OUT OC_ACPI_CONTEXT *Context ) { - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS Table; - UINT32 OldSize; - UINT32 RequiredSize; - EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE *Fadt; - UINT32 Index; + EFI_STATUS Status; + UINT32 OldSize; + UINT32 RequiredSize; if (Context->Fadt == NULL) { return EFI_NOT_FOUND; @@ -1196,39 +1382,17 @@ AcpiFadtEnableReset ( // REF: https://github.com/acidanthera/bugtracker/issues/897 // - if (OldSize < RequiredSize) { - Table = BASE_4GB - 1; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIMemoryNVS, - EFI_SIZE_TO_PAGES (RequiredSize), - &Table - ); - + if (OldSize < RequiredSize || !AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Context->Fadt)) { + Status = AcpiAllocateCopyFadt (Context, OldSize < RequiredSize ? RequiredSize : 0); if (EFI_ERROR (Status)) { return Status; } - Fadt = (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN) Table; - CopyMem (Fadt, Context->Fadt, OldSize); - ZeroMem (((UINT8 *) Context->Fadt) + OldSize, RequiredSize - OldSize); - Fadt->Header.Length = RequiredSize; - - for (Index = 0; Index < Context->NumberOfTables; ++Index) { - // - // I think sometimes there are multiple FADT tables. - // - if (Context->Tables[Index]->Signature == EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { - Context->Tables[Index] = (EFI_ACPI_COMMON_HEADER *) Fadt; - } - } - } else if ((Context->Fadt->Flags & EFI_ACPI_6_2_RESET_REG_SUP) == 0 + } else if (!((Context->Fadt->Flags & EFI_ACPI_6_2_RESET_REG_SUP) == 0 || (Context->Fadt->Flags & EFI_ACPI_6_2_SLP_BUTTON) == 0 || (Context->Fadt->Flags & EFI_ACPI_6_2_PWR_BUTTON) != 0 || Context->Fadt->ResetReg.Address == 0 - || Context->Fadt->ResetReg.RegisterBitWidth != 8) { - Fadt = Context->Fadt; - } else { + || Context->Fadt->ResetReg.RegisterBitWidth != 8)) { return EFI_SUCCESS; } @@ -1236,24 +1400,23 @@ AcpiFadtEnableReset ( // Enable sleep button, but disable power button actions. // This resolves power button action in macOS on some models. // - Fadt->Flags |= EFI_ACPI_6_2_SLP_BUTTON | EFI_ACPI_6_2_RESET_REG_SUP; - Fadt->Flags &= ~EFI_ACPI_6_2_PWR_BUTTON; + Context->Fadt->Flags |= EFI_ACPI_6_2_SLP_BUTTON | EFI_ACPI_6_2_RESET_REG_SUP; + Context->Fadt->Flags &= ~EFI_ACPI_6_2_PWR_BUTTON; - if (Fadt->ResetReg.Address == 0 || Fadt->ResetReg.RegisterBitWidth != 8) { + if (Context->Fadt->ResetReg.Address == 0 || Context->Fadt->ResetReg.RegisterBitWidth != 8) { // // Resetting through port 0xCF9 is universal on Intel and AMD. // But may not be the case on some laptops, which use 0xB2. // - Fadt->ResetReg.AddressSpaceId = EFI_ACPI_6_2_SYSTEM_IO; - Fadt->ResetReg.RegisterBitWidth = 8; - Fadt->ResetReg.RegisterBitOffset = 0; - Fadt->ResetReg.AccessSize = EFI_ACPI_6_2_BYTE; - Fadt->ResetReg.Address = 0xCF9; - Fadt->ResetValue = 6; + Context->Fadt->ResetReg.AddressSpaceId = EFI_ACPI_6_2_SYSTEM_IO; + Context->Fadt->ResetReg.RegisterBitWidth = 8; + Context->Fadt->ResetReg.RegisterBitOffset = 0; + Context->Fadt->ResetReg.AccessSize = EFI_ACPI_6_2_BYTE; + Context->Fadt->ResetReg.Address = 0xCF9; + Context->Fadt->ResetValue = 6; } - Fadt->Header.Checksum = 0; - Fadt->Header.Checksum = CalculateCheckSum8 ((UINT8 *) Fadt, Fadt->Header.Length); + AcpiRefreshTableChecksum ((EFI_ACPI_DESCRIPTION_HEADER *) Context->Fadt); return EFI_SUCCESS; } @@ -1263,13 +1426,32 @@ AcpiResetLogoStatus ( IN OUT OC_ACPI_CONTEXT *Context ) { - UINT32 Index; + EFI_STATUS Status; + UINT32 Index; + + EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE *Bgrt; + EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE *BgrtNew; for (Index = 0; Index < Context->NumberOfTables; ++Index) { if (Context->Tables[Index]->Signature == EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE) { if (Context->Tables[Index]->Length >= sizeof (EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE)) { - EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE *Bgrt = - (EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE *)Context->Tables[Index]; + Bgrt = (EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE *) Context->Tables[Index]; + + if (!AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Bgrt)) { + Status = AcpiAllocateCopyTable ( + (EFI_ACPI_COMMON_HEADER *) Bgrt, + 0, + (EFI_ACPI_COMMON_HEADER **) &BgrtNew + ); + + if (EFI_ERROR (Status)) { + return; + } + + Context->Tables[Index] = (EFI_ACPI_COMMON_HEADER *) BgrtNew; + Bgrt = BgrtNew; + } + Bgrt->Status &= ~EFI_ACPI_6_2_BGRT_STATUS_DISPLAYED; Bgrt->Header.Checksum = 0; Bgrt->Header.Checksum = CalculateCheckSum8 ( @@ -1288,7 +1470,11 @@ AcpiHandleHardwareSignature ( IN BOOLEAN Reset ) { + EFI_STATUS Status; + BOOLEAN IsXFirmwareCtrl; + EFI_ACPI_6_2_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; + EFI_ACPI_6_2_FIRMWARE_ACPI_CONTROL_STRUCTURE *FacsNew; if (Context->Fadt == NULL) { return; @@ -1296,8 +1482,10 @@ AcpiHandleHardwareSignature ( if (Context->Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE, XFirmwareCtrl) + sizeof (Context->Fadt->XFirmwareCtrl)) { Facs = (EFI_ACPI_6_2_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN) Context->Fadt->XFirmwareCtrl; + IsXFirmwareCtrl = TRUE; } else { Facs = NULL; + IsXFirmwareCtrl = FALSE; } if (Facs == NULL && Context->Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE, FirmwareCtrl) + sizeof (Context->Fadt->FirmwareCtrl)) { @@ -1308,6 +1496,37 @@ AcpiHandleHardwareSignature ( DEBUG ((DEBUG_INFO, "OCA: FACS signature is %X (%d)\n", Facs->Flags, Reset)); if (Reset) { + if (!AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Facs)) { + Status = AcpiAllocateCopyTable ( + (EFI_ACPI_COMMON_HEADER *) Facs, + 0, + (EFI_ACPI_COMMON_HEADER **) &FacsNew + ); + if (EFI_ERROR (Status)) { + return; + } + + // + // Reallocate FADT if needed. + // + if (!AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Context->Fadt)) { + Status = AcpiAllocateCopyFadt (Context, 0); + if (EFI_ERROR (Status)) { + FreePool (FacsNew); + return; + } + } + + if (IsXFirmwareCtrl) { + Context->Fadt->XFirmwareCtrl = (UINT64)(UINTN) FacsNew; + } else { + Context->Fadt->FirmwareCtrl = (UINT32)(UINTN) FacsNew; + } + AcpiRefreshTableChecksum ((EFI_ACPI_DESCRIPTION_HEADER *) Context->Fadt); + + Facs = FacsNew; + } + // // TODO: We might also want to unset S4BIOS_F flag in Facs->Flags. //