1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/zsl588-OpenCorePkg

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
OcAcpiLib.c 49 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
vit9696 Отправлено 3 лет назад e762311
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745
/** @file
Copyright (C) 2016, The HermitCrabs Lab. All rights reserved.
All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which 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.
**/
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/OcDebugLogLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/OcMemoryLib.h>
#include <Library/OcMiscLib.h>
#include <IndustryStandard/AcpiAml.h>
#include <IndustryStandard/Acpi.h>
#include <Guid/Acpi.h>
#include <Library/OcAcpiLib.h>
/**
Find RSD_PTR Table In Legacy Area
@retval EFI_ACPI_6_0_ROOT_SYSTEM_DESCRIPTION_POINTER
**/
STATIC
EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER *
AcpiFindLegacyRsdp (
VOID
)
{
EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
UINTN Address;
UINTN Index;
//
// First Search 0x0E0000 - 0x0FFFFF for RSD_PTR
//
Rsdp = NULL;
for (Address = 0x0E0000; Address < 0x0FFFFF; Address += 16) {
if (*(UINT64 *) Address == EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) {
Rsdp = (EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER *) Address;
}
}
//
// Then Search EBDA 0x40E - 0x800
//
if (Rsdp == NULL) {
Address = ((UINTN)(*(UINT16 *) 0x040E) << 4U);
for (Index = 0; Index < 0x0400; Index += 16) {
if (*(UINT64 *) (Address + Index) == EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) {
Rsdp = (EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER *) Address;
}
}
}
return Rsdp;
}
/**
Find RSD_PTR Table From System Configuration Tables
@retval EFI_ACPI_6_0_ROOT_SYSTEM_DESCRIPTION_POINTER
**/
STATIC
EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER *
AcpiFindRsdp (
VOID
)
{
EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
UINTN Index;
Rsdp = NULL;
//
// Find ACPI table RSD_PTR from system table
//
for (Index = 0; Index < gST->NumberOfTableEntries; ++Index) {
//
// Prefer ACPI 2.0
//
if (CompareGuid (&gST->ConfigurationTable[Index].VendorGuid, &gEfiAcpi20TableGuid)) {
Rsdp = (EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER *) gST->ConfigurationTable[Index].VendorTable;
DEBUG ((DEBUG_VERBOSE, "OCA: Found ACPI 2.0 RSDP table %p\n", Rsdp));
break;
}
//
// Otherwise use ACPI 1.0, but do search for ACPI 2.0.
//
if (CompareGuid (&gST->ConfigurationTable[Index].VendorGuid, &gEfiAcpi10TableGuid)) {
Rsdp = (EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER *) gST->ConfigurationTable[Index].VendorTable;
DEBUG ((DEBUG_VERBOSE, "OCA: Found ACPI 1.0 RSDP table %p\n", Rsdp));
}
}
//
// Try to use legacy search as a last resort.
//
if (Rsdp == NULL) {
Rsdp = AcpiFindLegacyRsdp ();
if (Rsdp != NULL) {
DEBUG ((DEBUG_VERBOSE, "OCA: Found ACPI legacy RSDP table %p\n", Rsdp));
}
}
if (Rsdp == NULL) {
DEBUG ((DEBUG_WARN, "OCA: Failed to find ACPI RSDP table\n"));
}
return Rsdp;
}
/**
Extract and verify ACPI signature from common header.
@param Common ACPI common header.
@return Signature.
**/
STATIC
UINT32
AcpiReadSignature (
IN CONST EFI_ACPI_COMMON_HEADER *Common
)
{
UINT32 Result;
CHAR8 *Walker;
UINT32 Index;
Result = Common->Signature;
Walker = (CHAR8 *) &Result;
for (Index = 0; Index < sizeof (Common->Signature); Index++) {
if (!IsAsciiPrint (Walker[Index])) {
Walker[Index] = '?';
}
}
return Result;
}
/**
Extract and verify ACPI OemTableId from common header.
@param Common ACPI common header.
@return OemTableId or 0.
**/
STATIC
UINT64
AcpiReadOemTableId (
IN CONST EFI_ACPI_COMMON_HEADER *Common
)
{
if (Common->Length <= sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
return 0;
}
return ((EFI_ACPI_DESCRIPTION_HEADER *) Common)->OemTableId;
}
/**
Extract and verify ACPI name from data.
@param Data Data of at least OC_ACPI_NAME_SIZE+1 bytes to read name from.
@param Name Name buffer of at least OC_ACPI_NAME_SIZE+1 bytes.
@param NameOffset Name offset from original data (1 if '\\' and 0 otherwise).
@return TRUE for valid names.
**/
STATIC
BOOLEAN
AcpiReadName (
IN CONST UINT8 *Data,
OUT CHAR8 *Name,
OUT UINT32 *NameOffset OPTIONAL
)
{
UINT32 Index;
UINT32 Off;
//
// Skip \ in \NAME.
//
Off = Data[0] == '\\' ? 1 : 0;
for (Index = Off; Index < Off + OC_ACPI_NAME_SIZE; ++Index) {
if (Data[Index] < '/'
|| ((Data[Index] > '9') && (Data[Index] < 'A'))
|| ((Data[Index] > 'Z') && (Data[Index] != '_'))) {
return FALSE;
}
Name[Index - Off] = Data[Index];
}
Name[OC_ACPI_NAME_SIZE] = 0;
if (NameOffset != NULL) {
*NameOffset = Off;
}
return TRUE;
}
/**
Find ACPI name declaration in data.
@param Data ACPI table data.
@param Length ACPI table data length.
@param Name ACPI name of at least OC_ACPI_NAME_SIZE bytes.
@return offset > 0 for valid names.
**/
STATIC
UINT32
AcpiFindName (
IN CONST UINT8 *Data,
IN UINT32 Length,
IN CONST CHAR8 *Name
)
{
UINT32 Index;
//
// Lookup from offset 1 and after.
//
if (Length < OC_ACPI_NAME_SIZE + 1) {
return 0;
}
for (Index = 0; Index < Length - OC_ACPI_NAME_SIZE; ++Index) {
if (Data[Index] == AML_NAME_OP
&& Data[Index+1] == Name[0]
&& Data[Index+2] == Name[1]
&& Data[Index+3] == Name[2]
&& Data[Index+4] == Name[3]) {
return Index+1;
}
}
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.
@param Context ACPI library context.
@param Table ACPI table.
@return EFI_SUCCESS unless memory allocation failure.
**/
STATIC
EFI_STATUS
AcpiLoadTableRegions (
IN OUT OC_ACPI_CONTEXT *Context,
IN EFI_ACPI_COMMON_HEADER *Table
)
{
UINT32 Index;
UINT32 Index2;
UINT32 NameOffset;
UINT8 *Buffer;
UINT32 BufferLen;
CHAR8 Name[OC_ACPI_NAME_SIZE+1];
CHAR8 NameAddr[OC_ACPI_NAME_SIZE+1];
OC_ACPI_REGION *NewRegions;
UINT32 Address;
Buffer = (UINT8 *) Table;
BufferLen = Table->Length;
if (BufferLen < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
return EFI_SUCCESS;
}
for (Index = sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < BufferLen - 0xF; ++Index) {
if (Buffer[Index] == AML_EXT_OP
&& Buffer[Index+1] == AML_EXT_REGION_OP
&& AcpiReadName (&Buffer[Index+2], &Name[0], &NameOffset)
&& Buffer[Index+OC_ACPI_NAME_SIZE+2+NameOffset] == EFI_ACPI_6_2_SYSTEM_MEMORY) {
//
// This is SystemMemory region. Try to save it.
//
Address = 0;
if (Buffer[Index+OC_ACPI_NAME_SIZE+3+NameOffset] == AML_DWORD_PREFIX) {
CopyMem (&Address, &Buffer[Index+OC_ACPI_NAME_SIZE+4+NameOffset], sizeof (UINT32));
} else if (Buffer[Index+OC_ACPI_NAME_SIZE+3+NameOffset] == AML_WORD_PREFIX) {
CopyMem (&Address, &Buffer[Index+OC_ACPI_NAME_SIZE+4+NameOffset], sizeof (UINT16));
} else if (AcpiReadName (&Buffer[Index+OC_ACPI_NAME_SIZE+3+NameOffset], &NameAddr[0], NULL)) {
Index2 = AcpiFindName (Buffer, BufferLen, &NameAddr[0]);
if (Index2 > 0 && Index2 < BufferLen - 0xF) {
if (Buffer[Index2+OC_ACPI_NAME_SIZE] == AML_DWORD_PREFIX) {
CopyMem (&Address, &Buffer[Index2+OC_ACPI_NAME_SIZE+1], sizeof (UINT32));
} else if (Buffer[Index2+OC_ACPI_NAME_SIZE] == AML_WORD_PREFIX) {
CopyMem (&Address, &Buffer[Index2+OC_ACPI_NAME_SIZE+1], sizeof (UINT16));
}
}
}
for (Index2 = 0; Index2 < Context->NumberOfRegions; ++Index2) {
if (Context->Regions[Index2].Address == Address) {
Address = 0;
break;
}
}
if (Address != 0) {
if (Context->AllocatedRegions == Context->NumberOfRegions) {
NewRegions = AllocatePool ((Context->AllocatedRegions + 2) * sizeof (Context->Regions[0]));
if (NewRegions == NULL) {
DEBUG ((DEBUG_WARN, "OCA: Failed to allocate memory for %u regions\n", Context->AllocatedRegions+2));
return EFI_OUT_OF_RESOURCES;
}
CopyMem (NewRegions, Context->Regions, Context->NumberOfRegions * sizeof (Context->Regions[0]));
FreePool (Context->Regions);
Context->Regions = NewRegions;
Context->AllocatedRegions += 2;
}
DEBUG ((DEBUG_INFO, "OCA: Found OperationRegion %a at %08X\n", Name, Address));
Context->Regions[Context->NumberOfRegions].Address = Address;
CopyMem (&Context->Regions[Context->NumberOfRegions].Name[0], &Name[0], sizeof (Name));
++Context->NumberOfRegions;
}
}
}
return EFI_SUCCESS;
}
/**
Relocate ACPI table regions.
@param Context ACPI library context.
@param Table ACPI table.
**/
STATIC
VOID
AcpiRelocateTableRegions (
IN OUT OC_ACPI_CONTEXT *Context,
IN EFI_ACPI_COMMON_HEADER *Table
)
{
UINT32 Index;
UINT32 Index2;
UINT32 RegionIndex;
UINT32 NameOffset;
UINT8 *Buffer;
UINT32 BufferLen;
CHAR8 Name[OC_ACPI_NAME_SIZE+1];
CHAR8 NameAddr[OC_ACPI_NAME_SIZE+1];
UINT32 OldAddress;
BOOLEAN Modified;
Buffer = (UINT8 *) Table;
BufferLen = Table->Length;
Modified = FALSE;
if (BufferLen < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
return;
}
for (Index = sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < BufferLen - 0xF; ++Index) {
if (Buffer[Index] == AML_EXT_OP
&& Buffer[Index+1] == AML_EXT_REGION_OP
&& AcpiReadName (&Buffer[Index+2], &Name[0], &NameOffset)
&& Buffer[Index+OC_ACPI_NAME_SIZE+2+NameOffset] == EFI_ACPI_6_2_SYSTEM_MEMORY) {
//
// This is region. Compare to current BIOS tables and relocate.
//
for (RegionIndex = 0; RegionIndex < Context->NumberOfRegions; ++RegionIndex) {
if (AsciiStrCmp (Context->Regions[RegionIndex].Name, Name) == 0) {
OldAddress = 0;
if (Buffer[Index+OC_ACPI_NAME_SIZE+3+NameOffset] == AML_DWORD_PREFIX) {
CopyMem (&OldAddress, &Buffer[Index+OC_ACPI_NAME_SIZE+4+NameOffset], sizeof (UINT32));
CopyMem (&Buffer[Index+OC_ACPI_NAME_SIZE+4+NameOffset], &Context->Regions[RegionIndex].Address, sizeof (UINT32));
Modified = TRUE;
} else if (Buffer[Index+OC_ACPI_NAME_SIZE+3+NameOffset] == AML_WORD_PREFIX) {
CopyMem (&OldAddress, &Buffer[Index+OC_ACPI_NAME_SIZE+4+NameOffset], sizeof (UINT16));
CopyMem (&Buffer[Index+OC_ACPI_NAME_SIZE+4+NameOffset], &Context->Regions[RegionIndex].Address, sizeof (UINT16));
Modified = TRUE;
} else if (AcpiReadName (&Buffer[Index+OC_ACPI_NAME_SIZE+3+NameOffset], &NameAddr[0], NULL)) {
Index2 = AcpiFindName (Buffer, BufferLen, &NameAddr[0]);
if (Index2 > 0 && Index2 < BufferLen - 0xF) {
if (Buffer[Index2+OC_ACPI_NAME_SIZE] == AML_DWORD_PREFIX) {
CopyMem (&OldAddress, &Buffer[Index2+OC_ACPI_NAME_SIZE+1], sizeof (UINT32));
CopyMem (&Buffer[Index2+OC_ACPI_NAME_SIZE+1], &Context->Regions[RegionIndex].Address, sizeof (UINT32));
Modified = TRUE;
} else if (Buffer[Index2+OC_ACPI_NAME_SIZE] == AML_WORD_PREFIX) {
CopyMem (&OldAddress, &Buffer[Index2+OC_ACPI_NAME_SIZE+1], sizeof (UINT16));
CopyMem (&Buffer[Index2+OC_ACPI_NAME_SIZE+1], &Context->Regions[RegionIndex].Address, sizeof (UINT16));
Modified = TRUE;
}
}
}
if (Modified && OldAddress != Context->Regions[RegionIndex].Address) {
DEBUG ((
DEBUG_INFO,
"OCA: Region %a address relocated from %08X to %08X\n",
Context->Regions[RegionIndex].Name,
OldAddress,
Context->Regions[RegionIndex].Address
));
}
break;
}
}
}
}
//
// Update checksum
//
if (Modified) {
((EFI_ACPI_DESCRIPTION_HEADER *)Table)->Checksum = 0;
((EFI_ACPI_DESCRIPTION_HEADER *)Table)->Checksum = CalculateCheckSum8 (
(UINT8 *) Table,
Table->Length
);
}
}
/**
Cleanup ACPI table from unprintable symbols.
Reference: https://alextjam.es/debugging-appleacpiplatform/.
@param Table ACPI table.
**/
STATIC
BOOLEAN
AcpiNormalizeTableHeaders (
IN EFI_ACPI_DESCRIPTION_HEADER *Table
)
{
BOOLEAN Modified;
CHAR8 *Walker;
UINT32 Index;
if (Table->Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
return FALSE;
}
Modified = FALSE;
Walker = (CHAR8 *) &Table->Signature;
for (Index = 0; Index < sizeof (Table->Signature); ++Index) {
if (!IsAsciiPrint (Walker[Index])) {
Walker[Index] = '?';
Modified = TRUE;
}
}
Walker = (CHAR8 *) &Table->OemId;
for (Index = 0; Index < sizeof (Table->OemId); ++Index) {
if (!IsAsciiPrint (Walker[Index])) {
Walker[Index] = '?';
Modified = TRUE;
}
}
Walker = (CHAR8 *) &Table->OemTableId;
for (Index = 0; Index < sizeof (Table->OemTableId); ++Index) {
if (!IsAsciiPrint (Walker[Index])) {
Walker[Index] = '?';
Modified = TRUE;
}
}
Walker = (CHAR8 *) &Table->CreatorId;
for (Index = 0; Index < sizeof (Table->CreatorId); ++Index) {
if (!IsAsciiPrint (Walker[Index])) {
Walker[Index] = '?';
Modified = TRUE;
}
}
if (Modified) {
Table->Checksum = 0;
Table->Checksum = CalculateCheckSum8 (
(UINT8 *) Table,
Table->Length
);
}
return Modified;
}
/**
Cleanup RSDP table from unprintable symbols.
Reference: https://alextjam.es/debugging-appleacpiplatform/.
@param Rsdp RSDP table.
@param HasXsdt RSDP has XSDT and is extended.
**/
STATIC
BOOLEAN
AcpiNormalizeRsdp (
IN EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp,
IN BOOLEAN HasXsdt
)
{
BOOLEAN Modified;
CHAR8 *Walker;
UINT32 Index;
Modified = FALSE;
Walker = (CHAR8 *) &Rsdp->OemId;
for (Index = 0; Index < sizeof (Rsdp->OemId); ++Index) {
if (!IsAsciiPrint (Walker[Index])) {
Walker[Index] = '?';
Modified = TRUE;
}
}
if (Modified) {
//
// Checksum is to be the first 0-19 bytes of RSDP.
// ExtendedChecksum is the entire table, only if newer than ACPI 1.0.
//
Rsdp->Checksum = 0;
Rsdp->Checksum = CalculateCheckSum8 (
(UINT8 *) Rsdp, 20
);
if (HasXsdt) {
Rsdp->ExtendedChecksum = 0;
Rsdp->ExtendedChecksum = CalculateCheckSum8 (
(UINT8 *) Rsdp, Rsdp->Length
);
}
}
return Modified;
}
EFI_STATUS
AcpiInitContext (
IN OUT OC_ACPI_CONTEXT *Context
)
{
UINT32 Index;
UINT32 DstIndex;
UINT32 TablePrintSignature;
ZeroMem (Context, sizeof (*Context));
Context->Rsdp = AcpiFindRsdp ();
if (Context->Rsdp == NULL) {
return EFI_NOT_FOUND;
}
//
// Support RSDT on ACPI 1.0 and newer.
//
Context->Rsdt = (OC_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_TABLE *)(UINTN) Context->Rsdp->RsdtAddress;
DEBUG ((DEBUG_VERBOSE, "OCA: Found ACPI RSDT table %p", Context->Rsdt));
//
// ACPI 2.0 and newer have XSDT as well.
//
if (Context->Rsdp->Revision > 0) {
Context->Xsdt = (OC_ACPI_6_2_EXTENDED_SYSTEM_DESCRIPTION_TABLE *)(UINTN) Context->Rsdp->XsdtAddress;
DEBUG ((DEBUG_VERBOSE, "OCA: Found ACPI XSDT table %p", Context->Xsdt));
}
if (Context->Rsdt == NULL && Context->Xsdt == NULL) {
DEBUG ((DEBUG_WARN, "OCA: Failed to find ACPI RSDT or XSDT tables\n"));
return EFI_NOT_FOUND;
}
if (Context->Xsdt != NULL) {
Context->NumberOfTables = (Context->Xsdt->Header.Length - sizeof (Context->Xsdt->Header))
/ sizeof (Context->Xsdt->Tables[0]);
} else {
Context->NumberOfTables = (Context->Rsdt->Header.Length - sizeof (Context->Rsdt->Header))
/ sizeof (Context->Rsdt->Tables[0]);
}
DEBUG ((DEBUG_INFO, "OCA: Found %u ACPI tables\n", Context->NumberOfTables));
if (Context->NumberOfTables == 0) {
DEBUG ((DEBUG_WARN, "OCA: No ACPI tables are available\n"));
return EFI_INVALID_PARAMETER;
}
Context->Tables = AllocatePool (Context->NumberOfTables * sizeof (Context->Tables[0]));
if (Context->Tables == NULL) {
DEBUG ((DEBUG_WARN, "OCA: Cannot allocate space for %u ACPI tables\n", Context->NumberOfTables));
return EFI_OUT_OF_RESOURCES;
}
Context->AllocatedTables = Context->NumberOfTables;
for (DstIndex = 0, Index = 0; Index < Context->NumberOfTables; ++Index) {
Context->Tables[DstIndex] = (EFI_ACPI_COMMON_HEADER *)(Context->Xsdt != NULL
? (UINTN) Context->Xsdt->Tables[Index] : (UINTN) Context->Rsdt->Tables[Index]);
//
// Skip NULL table entries, DSDT, and RSDP if any.
//
if (Context->Tables[DstIndex] == NULL
|| Context->Tables[DstIndex]->Signature == EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
|| *(UINT64 *) Context->Tables[DstIndex] == EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) {
continue;
}
TablePrintSignature = AcpiReadSignature (Context->Tables[DstIndex]);
DEBUG ((
DEBUG_INFO,
"OCA: Detected table %.4a (%08x) (OEM %016Lx) at %p of %u bytes at index %u\n",
(CHAR8 *) &TablePrintSignature,
Context->Tables[DstIndex]->Signature,
AcpiReadOemTableId (Context->Tables[DstIndex]),
Context->Tables[DstIndex],
Context->Tables[DstIndex]->Length,
Index
));
//
// Unlock table if in lower memory.
//
if ((UINTN)Context->Tables[DstIndex] < BASE_1MB) {
DEBUG ((
DEBUG_INFO,
"OCA: Unlocking table %.4a (%08x) at %p\n",
(CHAR8 *) &TablePrintSignature,
Context->Tables[DstIndex]->Signature,
Context->Tables[DstIndex]
));
LegacyRegionUnlock ((UINT32)(UINTN)Context->Tables[DstIndex], Context->Tables[DstIndex]->Length);
}
if (Context->Tables[DstIndex]->Signature == EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
Context->Fadt = (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE *) Context->Tables[DstIndex];
if (Context->Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE, XDsdt) + sizeof (Context->Fadt->XDsdt)) {
Context->Dsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Context->Fadt->XDsdt;
} else {
Context->Dsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Context->Fadt->Dsdt;
}
DEBUG ((
DEBUG_INFO,
"OCA: Detected DSDT at %p of %u bytes at index %u\n",
Context->Dsdt,
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;
}
if (Context->NumberOfTables != DstIndex) {
DEBUG ((DEBUG_INFO, "OCA: Only %u ACPI tables out of %u were valid\n", DstIndex, Context->NumberOfTables));
Context->NumberOfTables = DstIndex;
}
if (Context->Fadt == NULL) {
DEBUG ((DEBUG_WARN, "OCA: Failed to find ACPI FADT table\n"));
}
if (Context->Dsdt == NULL) {
DEBUG ((DEBUG_WARN, "OCA: Failed to find ACPI DSDT table\n"));
}
return EFI_SUCCESS;
}
VOID
AcpiFreeContext (
IN OUT OC_ACPI_CONTEXT *Context
)
{
if (Context->Tables != NULL) {
FreePool (Context->Tables);
Context->Tables = NULL;
}
if (Context->Regions != NULL) {
FreePool (Context->Regions);
Context->Regions = NULL;
}
}
EFI_STATUS
AcpiApplyContext (
IN OUT OC_ACPI_CONTEXT *Context
)
{
EFI_STATUS Status;
UINT32 XsdtSize;
UINT32 RsdtSize;
UINT32 Index;
UINT32 Size;
EFI_PHYSICAL_ADDRESS Table;
UINT32 TablePrintSignature;
XsdtSize = Context->Xsdt == NULL ? 0 : sizeof (*Context->Xsdt) + sizeof (Context->Xsdt->Tables[0]) * Context->NumberOfTables;
RsdtSize = Context->Rsdt == NULL ? 0 : sizeof (*Context->Rsdt) + sizeof (Context->Rsdt->Tables[0]) * Context->NumberOfTables;
Size = ALIGN_VALUE (XsdtSize, sizeof (UINT64)) + ALIGN_VALUE (RsdtSize, sizeof (UINT64));
Table = BASE_4GB - 1;
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiACPIMemoryNVS,
EFI_SIZE_TO_PAGES (Size),
&Table
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "OCA: Failed to allocate %u bytes for ACPI system tables\n", Size));
return Status;
}
if (Context->Xsdt != NULL) {
CopyMem ((VOID *)(UINTN)Table, Context->Xsdt, sizeof (*Context->Xsdt));
Context->Xsdt = (OC_ACPI_6_2_EXTENDED_SYSTEM_DESCRIPTION_TABLE *)(UINTN)Table;
Context->Xsdt->Header.Length = XsdtSize;
for (Index = 0; Index < Context->NumberOfTables; ++Index) {
Context->Xsdt->Tables[Index] = (UINT64)(UINTN) Context->Tables[Index];
TablePrintSignature = AcpiReadSignature (Context->Tables[Index]);
DEBUG ((
DEBUG_INFO,
"OCA: Exposing XSDT table table %.4a (%08x) (OEM %016Lx) at %p of %u bytes at index %u\n",
(CHAR8 *) &TablePrintSignature,
Context->Tables[Index]->Signature,
AcpiReadOemTableId (Context->Tables[Index]),
Context->Tables[Index],
Context->Tables[Index]->Length,
Index
));
}
Context->Xsdt->Header.Checksum = 0;
Context->Xsdt->Header.Checksum = CalculateCheckSum8 (
(UINT8 *) Context->Xsdt,
Context->Xsdt->Header.Length
);
Context->Rsdp->XsdtAddress = (UINT64) Table;
Table += ALIGN_VALUE (XsdtSize, sizeof (UINT64));
}
if (Context->Rsdt != NULL) {
CopyMem ((VOID *)(UINTN)Table, Context->Rsdt, sizeof (*Context->Rsdt));
Context->Rsdt = (OC_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_TABLE *)(UINTN)Table;
Context->Rsdt->Header.Length = RsdtSize;
for (Index = 0; Index < Context->NumberOfTables; ++Index) {
Context->Rsdt->Tables[Index] = (UINT32)(UINTN) Context->Tables[Index];
TablePrintSignature = AcpiReadSignature (Context->Tables[Index]);
DEBUG ((
Context->Xsdt != NULL ? DEBUG_BULK_INFO : DEBUG_INFO,
"OCA: Exposing RSDT table table %.4a (%08x) (OEM %016Lx) at %p of %u bytes at index %u\n",
(CHAR8 *) &TablePrintSignature,
Context->Tables[Index]->Signature,
AcpiReadOemTableId (Context->Tables[Index]),
Context->Tables[Index],
Context->Tables[Index]->Length,
Index
));
}
Context->Rsdt->Header.Checksum = 0;
Context->Rsdt->Header.Checksum = CalculateCheckSum8 (
(UINT8 *) Context->Rsdt,
Context->Rsdt->Header.Length
);
Context->Rsdp->RsdtAddress = (UINT32) Table;
Table += ALIGN_VALUE (RsdtSize, sizeof (UINT64));
}
//
// Checksum is to be the first 0-19 bytes of RSDP.
// ExtendedChecksum is the entire table, only if newer than ACPI 1.0.
//
Context->Rsdp->Checksum = 0;
Context->Rsdp->Checksum = CalculateCheckSum8 (
(UINT8 *) Context->Rsdp, 20
);
if (Context->Xsdt != NULL) {
Context->Rsdp->ExtendedChecksum = 0;
Context->Rsdp->ExtendedChecksum = CalculateCheckSum8 (
(UINT8 *) Context->Rsdp, Context->Rsdp->Length
);
}
return EFI_SUCCESS;
}
EFI_STATUS
AcpiDeleteTable (
IN OUT OC_ACPI_CONTEXT *Context,
IN UINT32 Signature,
IN UINT32 Length,
IN UINT64 OemTableId,
IN BOOLEAN All
)
{
UINT32 Index;
UINT64 CurrOemTableId;
BOOLEAN Found;
UINT32 TablePrintSignature;
Index = 0;
Found = FALSE;
while (Index < Context->NumberOfTables) {
if ((Signature == 0 || Context->Tables[Index]->Signature == Signature)
&& (Length == 0 || Context->Tables[Index]->Length == Length)) {
if (Context->Tables[Index]->Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
CurrOemTableId = ((EFI_ACPI_DESCRIPTION_HEADER *) Context->Tables[Index])->OemTableId;
} else {
CurrOemTableId = 0;
}
if (OemTableId == 0 || CurrOemTableId == OemTableId) {
TablePrintSignature = AcpiReadSignature (Context->Tables[Index]);
DEBUG ((
DEBUG_INFO,
"OCA: Deleting table %.4a (%08x) (OEM %016Lx) of %u bytes with %016Lx ID at index %u\n",
(CHAR8 *) &TablePrintSignature,
Context->Tables[Index]->Signature,
AcpiReadOemTableId (Context->Tables[Index]),
Context->Tables[Index]->Length,
CurrOemTableId,
Index
));
CopyMem (
&Context->Tables[Index],
&Context->Tables[Index+1],
(Context->NumberOfTables - Index - 1) * sizeof (Context->Tables[0])
);
--Context->NumberOfTables;
if (All) {
Found = TRUE;
continue;
} else {
return EFI_SUCCESS;
}
}
}
++Index;
}
if (Found) {
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
EFI_STATUS
AcpiInsertTable (
IN OUT OC_ACPI_CONTEXT *Context,
IN CONST UINT8 *Data,
IN UINT32 Length
)
{
EFI_ACPI_COMMON_HEADER *Common;
EFI_STATUS Status;
EFI_ACPI_COMMON_HEADER *NewTable;
EFI_ACPI_COMMON_HEADER **NewTables;
BOOLEAN ReplaceDsdt;
UINT32 TablePrintSignature;
if (Length < sizeof (EFI_ACPI_COMMON_HEADER)) {
DEBUG ((DEBUG_WARN, "OCA: Inserted ACPI table is only %u bytes, ignoring\n", Length));
return EFI_INVALID_PARAMETER;
}
Common = (EFI_ACPI_COMMON_HEADER *) Data;
if (Common->Length != Length) {
DEBUG ((DEBUG_WARN, "OCA: Inserted ACPI table has length mismatch %u vs %u, ignoring\n", Length, Common->Length));
return EFI_INVALID_PARAMETER;
}
ReplaceDsdt = Common->Signature == EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
if (ReplaceDsdt && (Context->Dsdt == NULL || Context->Fadt == NULL)) {
DEBUG ((DEBUG_WARN, "OCA: We do not have DSDT to replace\n"));
return EFI_INVALID_PARAMETER;
}
if (!ReplaceDsdt && Context->NumberOfTables == Context->AllocatedTables) {
NewTables = AllocatePool ((Context->NumberOfTables + 2) * sizeof (Context->Tables[0]));
if (NewTables == NULL) {
DEBUG ((DEBUG_WARN, "OCA: Cannot allocate space for new %u ACPI tables\n", Context->NumberOfTables+2));
return EFI_OUT_OF_RESOURCES;
}
CopyMem (NewTables, Context->Tables, Context->NumberOfTables * sizeof (Context->Tables[0]));
FreePool (Context->Tables);
Context->Tables = NewTables;
Context->AllocatedTables += 2;
}
if (ReplaceDsdt) {
DEBUG ((
DEBUG_INFO,
"OCA: Replaced DSDT of %u bytes into ACPI\n",
Common->Length
));
Status = AcpiAllocateCopyDsdt (Context, (EFI_ACPI_DESCRIPTION_HEADER *) Data);
if (EFI_ERROR (Status)) {
return Status;
}
} else {
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,
NewTable->Signature,
AcpiReadOemTableId (NewTable),
NewTable->Length,
Context->NumberOfTables
));
Context->Tables[Context->NumberOfTables] = NewTable;
++Context->NumberOfTables;
}
return EFI_SUCCESS;
}
VOID
AcpiNormalizeHeaders (
IN OUT OC_ACPI_CONTEXT *Context
)
{
EFI_STATUS Status;
UINT32 Index;
EFI_ACPI_COMMON_HEADER *NewTable;
UINT32 TablePrintSignature;
if (AcpiNormalizeRsdp (Context->Rsdp, Context->Xsdt != NULL)) {
DEBUG ((DEBUG_INFO, "OCA: Normalized RSDP\n"));
}
if (Context->Xsdt != NULL) {
if (!AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Context->Xsdt)) {
Status = AcpiAllocateCopyTable ((EFI_ACPI_COMMON_HEADER *) Context->Xsdt, 0, &NewTable);
if (EFI_ERROR (Status)) {
return;
}
Context->Xsdt = (OC_ACPI_6_2_EXTENDED_SYSTEM_DESCRIPTION_TABLE *) NewTable;
}
if (AcpiNormalizeTableHeaders ((EFI_ACPI_DESCRIPTION_HEADER *) Context->Xsdt)) {
DEBUG ((DEBUG_INFO, "OCA: Normalized XSDT of %u bytes headers\n", Context->Xsdt->Header.Length));
}
}
if (Context->Rsdt != NULL) {
if (!AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Context->Rsdt)) {
Status = AcpiAllocateCopyTable ((EFI_ACPI_COMMON_HEADER *) Context->Rsdt, 0, &NewTable);
if (EFI_ERROR (Status)) {
return;
}
Context->Rsdt = (OC_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_TABLE *) NewTable;
}
if (AcpiNormalizeTableHeaders ((EFI_ACPI_DESCRIPTION_HEADER *) Context->Rsdt)) {
DEBUG ((DEBUG_INFO, "OCA: Normalized RSDT of %u bytes headers\n", Context->Rsdt->Header.Length));
}
}
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]);
DEBUG ((
DEBUG_INFO,
"OCA: Normalized %.4a (%08x) (OEM %016Lx) of %u bytes headers at index %u\n",
(CHAR8 *) &TablePrintSignature,
Context->Tables[Index]->Signature,
AcpiReadOemTableId (Context->Tables[Index]),
Context->Tables[Index]->Length,
Index
));
}
}
}
EFI_STATUS
AcpiApplyPatch (
IN OUT OC_ACPI_CONTEXT *Context,
IN OC_ACPI_PATCH *Patch
)
{
EFI_STATUS Status;
EFI_ACPI_COMMON_HEADER *NewTable;
UINT32 Index;
UINT32 BaseOffset;
UINT64 CurrOemTableId;
UINT32 ReplaceCount;
UINT32 ReplaceLimit;
UINT32 TablePrintSignature;
DEBUG ((DEBUG_INFO, "OCA: Applying %u byte ACPI patch skip %u, count %u\n", Patch->Size, Patch->Skip, Patch->Count));
if (Context->Dsdt != NULL
&& (Patch->TableSignature == 0 || Patch->TableSignature == EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)
&& (Patch->TableLength == 0 || Context->Dsdt->Length == Patch->TableLength)
&& (Patch->OemTableId == 0 || Context->Dsdt->OemTableId == Patch->OemTableId)) {
ReplaceLimit = Context->Dsdt->Length;
if (Patch->Limit > 0) {
ReplaceLimit = MIN (ReplaceLimit, Patch->Limit);
}
BaseOffset = 0;
if (Patch->Base != NULL && Patch->Base[0] != '\0') {
Status = AcpiFindEntryInMemory (
(VOID *) Context->Dsdt,
Patch->Base,
(UINT8) (Patch->BaseSkip + 1),
&BaseOffset,
Context->Dsdt->Length
);
if (!EFI_ERROR (Status)) {
ReplaceLimit = MIN (ReplaceLimit, Context->Dsdt->Length - BaseOffset);
} else {
DEBUG ((
DEBUG_INFO,
"OCA: Patching DSDT of %u bytes failed to find base %a\n",
Context->Dsdt->Length,
Patch->Base
));
}
} else {
Status = EFI_SUCCESS;
}
if (!EFI_ERROR (Status)) {
if (!AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Context->Dsdt)) {
Status = AcpiAllocateCopyDsdt (Context, NULL);
if (EFI_ERROR (Status)) {
return Status;
}
}
ReplaceCount = ApplyPatch (
Patch->Find,
Patch->Mask,
Patch->Size,
Patch->Replace,
Patch->ReplaceMask,
(UINT8 *) Context->Dsdt + BaseOffset,
ReplaceLimit,
Patch->Count,
Patch->Skip
);
DEBUG ((
ReplaceCount > 0 ? DEBUG_INFO : DEBUG_BULK_INFO,
"OCA: Patching DSDT of %u bytes with %016Lx ID replaced %u of %u\n",
ReplaceLimit,
Patch->OemTableId,
ReplaceCount,
Patch->Count
));
if (ReplaceCount > 0) {
AcpiRefreshTableChecksum (Context->Dsdt);
}
}
}
for (Index = 0; Index < Context->NumberOfTables; ++Index) {
if ((Patch->TableSignature == 0 || Context->Tables[Index]->Signature == Patch->TableSignature)
&& (Patch->TableLength == 0 || Context->Tables[Index]->Length == Patch->TableLength)) {
if (Context->Tables[Index]->Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
CurrOemTableId = ((EFI_ACPI_DESCRIPTION_HEADER *) Context->Tables[Index])->OemTableId;
} else {
CurrOemTableId = 0;
}
if (Patch->OemTableId != 0 && CurrOemTableId != Patch->OemTableId) {
continue;
}
ReplaceLimit = Context->Tables[Index]->Length;
if (Patch->Limit > 0) {
ReplaceLimit = MIN (ReplaceLimit, Patch->Limit);
}
TablePrintSignature = AcpiReadSignature (Context->Tables[Index]);
BaseOffset = 0;
if (Patch->Base != NULL && Patch->Base[0] != '\0') {
Status = AcpiFindEntryInMemory (
(VOID *) Context->Tables[Index],
Patch->Base,
(UINT8) (Patch->BaseSkip + 1),
&BaseOffset,
Context->Tables[Index]->Length
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_INFO,
"OCA: Patching %.4a (%08x) (OEM %016Lx) of %u bytes with %016Lx ID failed to find base %a\n",
(CHAR8 *) &TablePrintSignature,
Context->Tables[Index]->Signature,
AcpiReadOemTableId (Context->Tables[Index]),
Context->Tables[Index]->Length,
CurrOemTableId,
Patch->Base
));
continue;
}
ReplaceLimit = MIN (ReplaceLimit, Context->Tables[Index]->Length - BaseOffset);
}
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,
Patch->Size,
Patch->Replace,
Patch->ReplaceMask,
(UINT8 *) Context->Tables[Index] + BaseOffset,
ReplaceLimit,
Patch->Count,
Patch->Skip
);
DEBUG ((
ReplaceCount > 0 ? DEBUG_INFO : DEBUG_BULK_INFO,
"OCA: Patching %.4a (%08x) (OEM %016Lx) of %u bytes with %016Lx ID at %u replaced %u of %u\n",
(CHAR8 *) &TablePrintSignature,
Context->Tables[Index]->Signature,
AcpiReadOemTableId (Context->Tables[Index]),
Context->Tables[Index]->Length,
CurrOemTableId,
Index,
ReplaceCount,
Patch->Count
));
if (ReplaceCount > 0 && Context->Tables[Index]->Length >= sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
AcpiRefreshTableChecksum ((EFI_ACPI_DESCRIPTION_HEADER *) Context->Tables[Index]);
}
}
}
return EFI_SUCCESS;
}
EFI_STATUS
AcpiLoadRegions (
IN OUT OC_ACPI_CONTEXT *Context
)
{
EFI_STATUS Status;
UINT32 Index;
//
// Should not be called twice, but just in case.
//
ASSERT (Context->Regions == NULL);
//
// Allocate something reasonably large by default.
//
Context->NumberOfRegions = 0;
Context->AllocatedRegions = 8;
Context->Regions = AllocatePool (sizeof (Context->Regions[0]) * Context->AllocatedRegions);
if (Context->Regions == NULL) {
DEBUG ((DEBUG_WARN, "OCA: Failed to allocate memory for %u regions\n", Context->NumberOfRegions));
return EFI_OUT_OF_RESOURCES;
}
if (Context->Dsdt != NULL) {
Status = AcpiLoadTableRegions (Context, (EFI_ACPI_COMMON_HEADER *) Context->Dsdt);
if (EFI_ERROR (Status)) {
return Status;
}
}
for (Index = 0; Index < Context->NumberOfTables; ++Index) {
if (Context->Tables[Index]->Signature == EFI_ACPI_6_2_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
Status = AcpiLoadTableRegions (Context, Context->Tables[Index]);
if (EFI_ERROR (Status)) {
return Status;
}
}
}
return EFI_SUCCESS;
}
VOID
AcpiRelocateRegions (
IN OUT OC_ACPI_CONTEXT *Context
)
{
EFI_STATUS Status;
UINT32 Index;
EFI_ACPI_COMMON_HEADER *NewTable;
//
// Should not be called before AcpiLoadRegions, but just in case.
//
ASSERT (Context->Regions != NULL);
if (Context->NumberOfRegions == 0) {
return;
}
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]);
}
}
}
EFI_STATUS
AcpiFadtEnableReset (
IN OUT OC_ACPI_CONTEXT *Context
)
{
EFI_STATUS Status;
UINT32 OldSize;
UINT32 RequiredSize;
if (Context->Fadt == NULL) {
return EFI_NOT_FOUND;
}
OldSize = Context->Fadt->Header.Length;
RequiredSize = OFFSET_OF (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE, ArmBootArch);
DEBUG ((DEBUG_INFO, "OCA: FADT reset got %u need %u\n", OldSize, RequiredSize));
//
// One some types of firmware, the table is too small and does not include
// Reset Register area. We will reallocate in this case.
// Interestingly EFI_ACPI_6_2_RESET_REG_SUP may be set.
//
// REF: https://github.com/acidanthera/bugtracker/issues/897
//
if (OldSize < RequiredSize || !AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Context->Fadt)) {
Status = AcpiAllocateCopyFadt (Context, OldSize < RequiredSize ? RequiredSize : 0);
if (EFI_ERROR (Status)) {
return Status;
}
} 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.Address == 0x64
|| Context->Fadt->ResetReg.RegisterBitWidth != 8)) {
return EFI_SUCCESS;
}
//
// Enable sleep button, but disable power button actions.
// This resolves power button action in macOS on some models.
//
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;
//
// We also change keyboard controller reset (0xFE to 0x64) to 0xCF9 reset
// as it is known to work incorrectly at least on Dell Latitude E6410
// when the NVIDIA GPU is attached.
//
if (Context->Fadt->ResetReg.Address == 0
|| Context->Fadt->ResetReg.Address == 0x64
|| Context->Fadt->ResetReg.RegisterBitWidth != 8) {
//
// Resetting through port 0xCF9 is universal on Intel and AMD.
// But may not be the case on e.g. Dell laptops and desktops, which use 0xB2.
//
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;
}
AcpiRefreshTableChecksum ((EFI_ACPI_DESCRIPTION_HEADER *) Context->Fadt);
return EFI_SUCCESS;
}
VOID
AcpiResetLogoStatus (
IN OUT OC_ACPI_CONTEXT *Context
)
{
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)) {
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 (
(UINT8 *) Bgrt,
Bgrt->Header.Length
);
}
break;
}
}
}
VOID
AcpiSyncTableIds (
IN OUT OC_ACPI_CONTEXT *Context
)
{
EFI_ACPI_DESCRIPTION_HEADER *Slic;
UINT32 Index;
Slic = NULL;
for (Index = 0; Index < Context->NumberOfTables; ++Index) {
if (Context->Tables[Index]->Signature == EFI_ACPI_6_2_SOFTWARE_LICENSING_TABLE_SIGNATURE) {
Slic = (VOID *)Context->Tables[Index];
break;
}
}
if (Slic == NULL) {
DEBUG ((DEBUG_INFO, "OCA: SLIC table is not found\n"));
return;
}
//
// SLIC identifiers must match RSDT and FADT, also doing XSDT for newer EFI just in case.
// REF: https://bugzilla.redhat.com/show_bug.cgi?id=1248758
//
if (Context->Rsdt != NULL) {
CopyMem (&Context->Rsdt->Header.OemId, &Slic->OemId, sizeof (Context->Rsdt->Header.OemId));
Context->Rsdt->Header.OemTableId = Slic->OemTableId;
Context->Rsdt->Header.Checksum = 0;
Context->Rsdt->Header.Checksum = CalculateCheckSum8 (
(UINT8 *) Context->Rsdt,
Context->Rsdt->Header.Length
);
DEBUG ((DEBUG_INFO, "OCA: SLIC table IDs fixed in RSDT\n"));
}
if (Context->Xsdt != NULL) {
CopyMem (&Context->Xsdt->Header.OemId, &Slic->OemId, sizeof (Context->Xsdt->Header.OemId));
Context->Xsdt->Header.OemTableId = Slic->OemTableId;
Context->Xsdt->Header.Checksum = 0;
Context->Xsdt->Header.Checksum = CalculateCheckSum8 (
(UINT8 *) Context->Xsdt,
Context->Xsdt->Header.Length
);
DEBUG ((DEBUG_INFO, "OCA: SLIC table IDs fixed in XSDT\n"));
}
if (Context->Fadt != NULL) {
CopyMem (&Context->Fadt->Header.OemId, &Slic->OemId, sizeof (Context->Fadt->Header.OemId));
Context->Fadt->Header.OemTableId = Slic->OemTableId;
Context->Fadt->Header.Checksum = 0;
Context->Fadt->Header.Checksum = CalculateCheckSum8 (
(UINT8 *) Context->Fadt,
Context->Fadt->Header.Length
);
DEBUG ((DEBUG_INFO, "OCA: SLIC table IDs fixed in FADT\n"));
}
}
VOID
AcpiHandleHardwareSignature (
IN OUT OC_ACPI_CONTEXT *Context,
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;
}
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)) {
Facs = (EFI_ACPI_6_2_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN) Context->Fadt->FirmwareCtrl;
}
if (Facs != NULL && Facs->Length >= OFFSET_OF (EFI_ACPI_6_2_FIRMWARE_ACPI_CONTROL_STRUCTURE, Flags) + sizeof (Facs->HardwareSignature)) {
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.
//
Facs->HardwareSignature = 0x0;
}
} else {
//
// For macOS this is just fine.
//
DEBUG ((
DEBUG_INFO,
"OCA: FACS signature is too far %d / %u\n",
Facs != NULL,
Facs != NULL ? Facs->Length : 0
));
}
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/zsl588-OpenCorePkg.git
git@gitlife.ru:oschina-mirror/zsl588-OpenCorePkg.git
oschina-mirror
zsl588-OpenCorePkg
zsl588-OpenCorePkg
0.7.7