12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511 |
- /*++
- Copyright (c) 2014 Minoca Corp.
- This file is licensed under the terms of the GNU General Public License
- version 3. Alternative licensing terms are available. Contact
- info@minocacorp.com for details. See the LICENSE file at the root of this
- project for complete licensing information.
- Module Name:
- acpi.c
- Abstract:
- This module implements support for installing ACPI tables into the EFI
- system table.
- Author:
- Evan Green 25-Mar-2014
- Environment:
- Firmware
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "ueficore.h"
- #include "efiimg.h"
- #include "fwvol.h"
- #include "fv2.h"
- #include <minoca/fw/acpitabs.h>
- #include <minoca/uefi/guid/acpi.h>
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define EFI_ACPI_TABLE_ENTRY_MAGIC 0x62544145 // 'bTAE'
- #define EFI_ACPI_TABLE_EXPANSION_COUNT 0x10
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- typedef struct _EFI_ACPI_COMMON_HEADER {
- UINT32 Signature;
- UINT32 Length;
- } EFI_ACPI_COMMON_HEADER, *PEFI_ACPI_COMMON_HEADER;
- typedef struct _EFI_ACPI_TABLE_ENTRY {
- UINT32 Magic;
- LIST_ENTRY ListEntry;
- EFI_ACPI_COMMON_HEADER *Table;
- EFI_PHYSICAL_ADDRESS PageAddress;
- UINTN NumberOfPages;
- UINTN Handle;
- } EFI_ACPI_TABLE_ENTRY, *PEFI_ACPI_TABLE_ENTRY;
- typedef struct _EFI_ACPI_CONTEXT {
- LIST_ENTRY TableList;
- UINTN CurrentHandle;
- UINTN TableCount;
- UINTN TableCapacity;
- PFADT Fadt;
- PFACS Facs;
- PRSDP Rsdp;
- PRSDT Rsdt;
- PXSDT Xsdt;
- PDESCRIPTION_HEADER Dsdt;
- } EFI_ACPI_CONTEXT, *PEFI_ACPI_CONTEXT;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- EFI_STATUS
- EfipLocateFirmwareVolumeWithAcpiTables (
- EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
- );
- EFI_STATUS
- EfipAcpiInitializeTables (
- VOID
- );
- EFI_STATUS
- EfipSetAcpiTable (
- VOID *Table,
- BOOLEAN Checksum,
- UINTN *Handle
- );
- EFI_STATUS
- EfipAddAcpiTableToList (
- VOID *Table,
- BOOLEAN Checksum,
- UINTN *Handle
- );
- EFI_STATUS
- EfipRemoveAcpiTableFromList (
- UINTN Handle
- );
- VOID
- EfipAcpiDeleteTable (
- PEFI_ACPI_TABLE_ENTRY Table
- );
- EFI_STATUS
- EfipAcpiRemoveTableFromRsdt (
- PEFI_ACPI_TABLE_ENTRY Table,
- UINTN *TableCount,
- PDESCRIPTION_HEADER Rsdt,
- PDESCRIPTION_HEADER Xsdt
- );
- EFI_STATUS
- EfipAcpiFindTableByHandle (
- UINTN Handle,
- PLIST_ENTRY ListHead,
- PEFI_ACPI_TABLE_ENTRY *FoundEntry
- );
- EFI_STATUS
- EfipReallocateAcpiTableBuffer (
- VOID
- );
- EFI_STATUS
- EfipAcpiPublishTables (
- VOID
- );
- VOID
- EfipAcpiChecksumCommonTables (
- VOID
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- EFI_GUID EfiAcpiTable1Guid = EFI_ACPI_10_TABLE_GUID;
- EFI_GUID EfiAcpiTableGuid = EFI_ACPI_20_TABLE_GUID;
- EFI_GUID EfiAcpiTableStorageFileGuid = EFI_ACPI_TABLE_STORAGE_FILE_GUID;
- //
- // Define the master EFI ACPI context.
- //
- EFI_ACPI_CONTEXT EfiAcpiContext;
- //
- // Define default values to stick in the table header. These can be overridden
- // by the platform. Note that once the FADT is installed, the values from that
- // header will overwrite values installed here.
- //
- CHAR8 *EfiAcpiDefaultOemId = "Minoca";
- UINT64 EfiAcpiDefaultOemTableId;
- UINT32 EfiAcpiDefaultOemRevision;
- UINT32 EfiAcpiDefaultCreatorId;
- UINT32 EfiAcpiDefaultCreatorRevision;
- //
- // ------------------------------------------------------------------ Functions
- //
- EFIAPI
- EFI_STATUS
- EfiAcpiDriverEntry (
- EFI_HANDLE ImageHandle,
- EFI_SYSTEM_TABLE *SystemTable
- )
- /*++
- Routine Description:
- This routine is the entry point into the ACPI driver.
- Arguments:
- ImageHandle - Supplies the driver image handle.
- SystemTable - Supplies a pointer to the EFI system table.
- Return Value:
- EFI status code.
- --*/
- {
- EFI_ACPI_COMMON_HEADER *CurrentTable;
- EFI_FIRMWARE_VOLUME2_PROTOCOL *FirmwareVolume;
- UINT32 FirmwareVolumeStatus;
- INTN Instance;
- UINTN Size;
- EFI_STATUS Status;
- UINTN TableHandle;
- UINTN TableSize;
- CurrentTable = NULL;
- Instance = 0;
- TableHandle = 0;
- Status = EfipAcpiInitializeTables();
- if (EFI_ERROR(Status)) {
- return Status;
- }
- Status = EfipLocateFirmwareVolumeWithAcpiTables(&FirmwareVolume);
- if (EFI_ERROR(Status)) {
- return EFI_SUCCESS;
- }
- while (Status == EFI_SUCCESS) {
- Status = FirmwareVolume->ReadSection(FirmwareVolume,
- &EfiAcpiTableStorageFileGuid,
- EFI_SECTION_RAW,
- Instance,
- (VOID **)&CurrentTable,
- &Size,
- &FirmwareVolumeStatus);
- if (!EFI_ERROR(Status)) {
- TableHandle = 0;
- TableSize = ((EFI_ACPI_COMMON_HEADER *)CurrentTable)->Length;
- ASSERT(Size >= TableSize);
- EfiAcpiChecksumTable(CurrentTable,
- TableSize,
- OFFSET_OF(DESCRIPTION_HEADER, Checksum));
- Status = EfiAcpiInstallTable(CurrentTable, TableSize, &TableHandle);
- EfiFreePool(CurrentTable);
- if (EFI_ERROR(Status)) {
- return EFI_ABORTED;
- }
- Instance += 1;
- CurrentTable = NULL;
- }
- }
- return EFI_SUCCESS;
- }
- EFIAPI
- EFI_STATUS
- EfiAcpiInstallTable (
- VOID *AcpiTableBuffer,
- UINTN AcpiTableBufferSize,
- UINTN *TableKey
- )
- /*++
- Routine Description:
- This routine installs an ACPI table into the RSDT/XSDT.
- Arguments:
- AcpiTableBuffer - Supplies a pointer to the buffer containing the ACPI
- table to insert.
- AcpiTableBufferSize - Supplies the size in bytes of the ACPI table buffer.
- TableKey - Supplies a pointer where a key will be returned that refers
- to the table.
- Return Value:
- EFI status code.
- --*/
- {
- EFI_STATUS Status;
- VOID *TableCopy;
- ASSERT(EfiAcpiContext.TableList.Next != NULL);
- if ((AcpiTableBuffer == NULL) || (TableKey == NULL) ||
- (((EFI_ACPI_COMMON_HEADER *)AcpiTableBuffer)->Length !=
- AcpiTableBufferSize)) {
- return EFI_INVALID_PARAMETER;
- }
- Status = EfiAllocatePool(EfiBootServicesData,
- AcpiTableBufferSize,
- (VOID **)&TableCopy);
- if (EFI_ERROR(Status)) {
- return Status;
- }
- EfiCopyMem(TableCopy, AcpiTableBuffer, AcpiTableBufferSize);
- *TableKey = 0;
- Status = EfipSetAcpiTable(TableCopy, TRUE, TableKey);
- if (!EFI_ERROR(Status)) {
- Status = EfipAcpiPublishTables();
- }
- EfiFreePool(TableCopy);
- return Status;
- }
- EFIAPI
- EFI_STATUS
- EfiAcpiUninstallTable (
- UINTN TableKey
- )
- /*++
- Routine Description:
- This routine uninstalls a previously install ACPI table.
- Arguments:
- TableKey - Supplies the key returned when the table was installed.
- Return Value:
- EFI status code.
- --*/
- {
- EFI_STATUS Status;
- ASSERT(EfiAcpiContext.TableList.Next != NULL);
- Status = EfipSetAcpiTable(NULL, FALSE, &TableKey);
- if (!EFI_ERROR(Status)) {
- Status = EfipAcpiPublishTables();
- }
- if (EFI_ERROR(Status)) {
- return EFI_NOT_FOUND;
- }
- return EFI_SUCCESS;
- }
- EFIAPI
- VOID
- EfiAcpiChecksumTable (
- VOID *Buffer,
- UINTN Size,
- UINTN ChecksumOffset
- )
- /*++
- Routine Description:
- This routine checksums an ACPI table.
- Arguments:
- Buffer - Supplies a pointer to the table to checksum.
- Size - Supplies the size of the table in bytes.
- ChecksumOffset - Supplies the offset of the 8 bit checksum field.
- Return Value:
- None.
- --*/
- {
- UINT8 *Pointer;
- UINT8 Sum;
- Sum = 0;
- Pointer = Buffer;
- Pointer[ChecksumOffset] = 0;
- while (Size != 0) {
- Sum = (UINT8)(Sum + *Pointer);
- Pointer += 1;
- Size -= 1;
- }
- Pointer = Buffer;
- Pointer[ChecksumOffset] = (UINT8)(0xFF - Sum + 1);
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- EFI_STATUS
- EfipLocateFirmwareVolumeWithAcpiTables (
- EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
- )
- /*++
- Routine Description:
- This routine returns the first instance of the firmware volume protocol
- that contains an ACPI table storage file.
- Arguments:
- Instance - Supplies a pointer where a pointer to the instance will be
- returned on success.
- Return Value:
- EFI status code.
- --*/
- {
- EFI_FV_FILE_ATTRIBUTES Attributes;
- EFI_FV_FILETYPE FileType;
- UINT32 FirmwareVolumeStatus;
- EFI_HANDLE *HandleBuffer;
- UINTN HandleCount;
- UINTN Index;
- UINTN Size;
- EFI_STATUS Status;
- EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume;
- FirmwareVolumeStatus = 0;
- //
- // Get all the firmware volume handles.
- //
- Status = EfiLocateHandleBuffer(ByProtocol,
- &EfiFirmwareVolume2ProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer);
- if (EFI_ERROR(Status)) {
- return Status;
- }
- //
- // Loop through all the firmware volume handles looking for an ACPI
- // table storage file.
- //
- for (Index = 0; Index < HandleCount; Index += 1) {
- Status = EfiHandleProtocol(HandleBuffer[Index],
- &EfiFirmwareVolume2ProtocolGuid,
- (VOID **)&Volume);
- ASSERT(!EFI_ERROR(Status));
- //
- // See if it has an ACPI storage file.
- //
- Status = Volume->ReadFile(Volume,
- &EfiAcpiTableStorageFileGuid,
- NULL,
- &Size,
- &FileType,
- &Attributes,
- &FirmwareVolumeStatus);
- if (Status == EFI_SUCCESS) {
- *Instance = Volume;
- break;
- }
- }
- EfiFreePool(HandleBuffer);
- return Status;
- }
- EFI_STATUS
- EfipAcpiInitializeTables (
- VOID
- )
- /*++
- Routine Description:
- This routine creates the initial RSDP and XSDT tables.
- Arguments:
- None.
- Return Value:
- EFI status code.
- --*/
- {
- PEFI_ACPI_CONTEXT Context;
- UINT64 CurrentData;
- EFI_PHYSICAL_ADDRESS PageAddress;
- UINT8 *Pointer;
- UINTN RsdpTableSize;
- EFI_STATUS Status;
- UINTN TotalSize;
- Context = &EfiAcpiContext;
- INITIALIZE_LIST_HEAD(&(Context->TableList));
- Context->CurrentHandle = 1;
- RsdpTableSize = sizeof(RSDP);
- //
- // Allocate space for the initial RSDP below 4GB for 32-bit OSes.
- //
- PageAddress = 0xFFFFFFFF;
- Status = EfiAllocatePages(AllocateMaxAddress,
- EfiACPIReclaimMemory,
- EFI_SIZE_TO_PAGES(RsdpTableSize),
- &PageAddress);
- if (EFI_ERROR(Status)) {
- return EFI_OUT_OF_RESOURCES;
- }
- Pointer = (UINT8 *)(UINTN)PageAddress;
- EfiSetMem(Pointer, RsdpTableSize, 0);
- Context->Rsdp = (PRSDP)Pointer;
- //
- // Allocate space for the RSDT and XSDT below 4GB, again for historical
- // reasons.
- //
- Context->TableCapacity = EFI_ACPI_TABLE_EXPANSION_COUNT;
- TotalSize = sizeof(DESCRIPTION_HEADER) +
- (Context->TableCapacity * sizeof(UINT32)) +
- sizeof(DESCRIPTION_HEADER) +
- (Context->TableCapacity * sizeof(UINT64));
- PageAddress = 0xFFFFFFFF;
- Status = EfiAllocatePages(AllocateMaxAddress,
- EfiACPIReclaimMemory,
- EFI_SIZE_TO_PAGES(TotalSize),
- &PageAddress);
- if (EFI_ERROR(Status)) {
- EfiFreePages((EFI_PHYSICAL_ADDRESS)(UINTN)(Context->Rsdp),
- EFI_SIZE_TO_PAGES(RsdpTableSize));
- return EFI_OUT_OF_RESOURCES;
- }
- Pointer = (UINT8 *)(UINTN)PageAddress;
- EfiSetMem(Pointer, TotalSize, 0);
- Context->Rsdt = (PRSDT)Pointer;
- Pointer += sizeof(DESCRIPTION_HEADER) +
- (Context->TableCapacity * sizeof(UINT32));
- Context->Xsdt = (PXSDT)Pointer;
- //
- // Initialize the RSDP.
- //
- CurrentData = RSDP_SIGNATURE;
- EfiCopyMem(&(Context->Rsdp->Signature), &CurrentData, sizeof(UINT64));
- EfiCopyMem(&(Context->Rsdp->OemId),
- EfiAcpiDefaultOemId,
- sizeof(Context->Rsdp->OemId));
- Context->Rsdp->Revision = ACPI_20_RSDP_REVISION;
- Context->Rsdp->RsdtAddress = (UINT32)(UINTN)(Context->Rsdt);
- Context->Rsdp->Length = sizeof(RSDP);
- CurrentData = (UINT64)(UINTN)(Context->Xsdt);
- EfiCopyMem(&(Context->Rsdp->XsdtAddress), &CurrentData, sizeof(UINT64));
- EfiSetMem(Context->Rsdp->Reserved, sizeof(Context->Rsdp->Reserved), 0);
- //
- // Initialize the RSDT. Reserve the first entry for the FADT.
- //
- Context->TableCount = 1;
- Context->Rsdt->Header.Length = sizeof(DESCRIPTION_HEADER) + sizeof(UINT32);
- Context->Rsdt->Header.Signature = RSDT_SIGNATURE;
- Context->Rsdt->Header.Revision = ACPI_30_RSDT_REVISION;
- EfiCopyMem(&(Context->Rsdt->Header.OemId),
- EfiAcpiDefaultOemId,
- sizeof(Context->Rsdt->Header.OemId));
- CurrentData = EfiAcpiDefaultOemTableId;
- EfiCopyMem(&(Context->Rsdt->Header.OemTableId),
- &CurrentData,
- sizeof(UINT64));
- Context->Rsdt->Header.OemRevision = EfiAcpiDefaultOemRevision;
- Context->Rsdt->Header.CreatorId = EfiAcpiDefaultCreatorId;
- Context->Rsdt->Header.CreatorRevision = EfiAcpiDefaultCreatorRevision;
- //
- // Initialize the XSDT, again reserving the first entry for the FADT.
- //
- Context->TableCount = 1;
- Context->Rsdt->Header.Length = sizeof(DESCRIPTION_HEADER) + sizeof(UINT64);
- Context->Rsdt->Header.Signature = RSDT_SIGNATURE;
- Context->Rsdt->Header.Revision = ACPI_30_XSDT_REVISION;
- EfiCopyMem(&(Context->Rsdt->Header.OemId),
- EfiAcpiDefaultOemId,
- sizeof(Context->Rsdt->Header.OemId));
- CurrentData = EfiAcpiDefaultOemTableId;
- EfiCopyMem(&(Context->Rsdt->Header.OemTableId),
- &CurrentData,
- sizeof(UINT64));
- Context->Rsdt->Header.OemRevision = EfiAcpiDefaultOemRevision;
- Context->Rsdt->Header.CreatorId = EfiAcpiDefaultCreatorId;
- Context->Rsdt->Header.CreatorRevision = EfiAcpiDefaultCreatorRevision;
- EfipAcpiChecksumCommonTables();
- return EFI_SUCCESS;
- }
- EFI_STATUS
- EfipSetAcpiTable (
- VOID *Table,
- BOOLEAN Checksum,
- UINTN *Handle
- )
- /*++
- Routine Description:
- This routine adds, removes, or updates ACPI tables. If the address is
- not NULL and the handle is NULL, the table is added. If both the address
- and the handle is not NULL, the table is updated. If the address is NULL
- and the handle is not, the table is deleted.
- Arguments:
- Table - Supplies an optional pointer to the table to intall. If not
- supplied, the table is deleted.
- Checksum - Supplies a boolean indicating if the checksum should be
- recomputed.
- Handle - Supplies a pointer to the handle of the table.
- Return Value:
- EFI status code.
- --*/
- {
- UINTN SavedHandle;
- EFI_STATUS Status;
- ASSERT(Handle != NULL);
- //
- // If there is no handle, add the table.
- //
- if (*Handle == 0) {
- if (Table == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- Status = EfipAddAcpiTableToList(Table, Checksum, Handle);
- //
- // There is a handle, update or delete the table.
- //
- } else {
- if (Table != NULL) {
- Status = EfipRemoveAcpiTableFromList(*Handle);
- if (EFI_ERROR(Status)) {
- return EFI_ABORTED;
- }
- //
- // Set the handle to replace the table at the same handle.
- //
- SavedHandle = EfiAcpiContext.CurrentHandle;
- EfiAcpiContext.CurrentHandle = *Handle;
- Status = EfipAddAcpiTableToList(Table, Checksum, Handle);
- EfiAcpiContext.CurrentHandle = SavedHandle;
- } else {
- Status = EfipRemoveAcpiTableFromList(*Handle);
- }
- }
- if (EFI_ERROR(Status)) {
- return EFI_ABORTED;
- }
- return EFI_SUCCESS;
- }
- EFI_STATUS
- EfipAddAcpiTableToList (
- VOID *Table,
- BOOLEAN Checksum,
- UINTN *Handle
- )
- /*++
- Routine Description:
- This routine adds an ACPI table to the table list. It detects the FACS,
- allocates the correct type of memory, and properly aligns the table.
- Arguments:
- Table - Supplies a pointer to the table to intall.
- Checksum - Supplies a boolean indicating if the checksum should be
- recomputed.
- Handle - Supplies a pointer to the handle of the table.
- Return Value:
- EFI status code.
- --*/
- {
- BOOLEAN AddToRsdt;
- UINT64 Buffer64;
- UINT32 *RsdtEntry;
- EFI_STATUS Status;
- PEFI_ACPI_TABLE_ENTRY TableEntry;
- UINT32 TableSignature;
- UINT32 TableSize;
- UINT32 *XsdtEntry;
- ASSERT((Table != NULL) && (Handle != NULL));
- AddToRsdt = TRUE;
- TableEntry = EfiCoreAllocateBootPool(sizeof(EFI_ACPI_TABLE_ENTRY));
- if (TableEntry == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- TableEntry->Magic = EFI_ACPI_TABLE_ENTRY_MAGIC;
- TableSignature = ((EFI_ACPI_COMMON_HEADER *)Table)->Signature;
- TableSize = ((EFI_ACPI_COMMON_HEADER *)Table)->Length;
- //
- // Allocate a buffer for the table. All tables are allocated in the lower
- // 32 bits for backwards compatibility with 32-bit OSes.
- //
- TableEntry->PageAddress = 0xFFFFFFFF;
- TableEntry->NumberOfPages = EFI_SIZE_TO_PAGES(TableSize);
- //
- // The FACS is aligned on a 64-byte boundary and must be ACPI NVS memory.
- //
- if (TableSignature == FACS_SIGNATURE) {
- ASSERT((EFI_PAGE_SIZE % 64) == 0);
- Status = EfiAllocatePages(AllocateMaxAddress,
- EfiACPIMemoryNVS,
- TableEntry->NumberOfPages,
- &(TableEntry->PageAddress));
- //
- // Everything else is just ACPI reclaim memory.
- //
- } else {
- Status = EfiAllocatePages(AllocateMaxAddress,
- EfiACPIReclaimMemory,
- TableEntry->NumberOfPages,
- &(TableEntry->PageAddress));
- }
- if (EFI_ERROR(Status)) {
- EfiFreePool(TableEntry);
- return EFI_OUT_OF_RESOURCES;
- }
- TableEntry->Table = (VOID *)(UINTN)(TableEntry->PageAddress);
- EfiCopyMem(TableEntry->Table, Table, TableSize);
- TableEntry->Handle = EfiAcpiContext.CurrentHandle;
- EfiAcpiContext.CurrentHandle += 1;
- *Handle = TableEntry->Handle;
- //
- // Update some pointers depending on the table signature.
- //
- switch (TableSignature) {
- case FADT_SIGNATURE:
- AddToRsdt = FALSE;
- if (EfiAcpiContext.Fadt != NULL) {
- EfiFreePages(TableEntry->PageAddress, TableEntry->NumberOfPages);
- EfiFreePool(TableEntry);
- return EFI_ABORTED;
- }
- EfiAcpiContext.Fadt = (PFADT)(TableEntry->Table);
- if (EfiAcpiContext.Facs <= (PFACS)0xFFFFFFFF) {
- EfiAcpiContext.Fadt->FirmwareControlAddress =
- (UINT32)(UINTN)(EfiAcpiContext.Facs);
- } else {
- Buffer64 = (UINTN)(EfiAcpiContext.Facs);
- EfiCopyMem(&(EfiAcpiContext.Fadt->XFirmwareControl),
- &Buffer64,
- sizeof(UINT64));
- }
- EfiAcpiContext.Fadt->DsdtAddress = (UINT32)(UINTN)(EfiAcpiContext.Dsdt);
- Buffer64 = (UINTN)(EfiAcpiContext.Dsdt);
- EfiCopyMem(&(EfiAcpiContext.Fadt->XDsdt), &Buffer64, sizeof(UINT64));
- //
- // Copy the RSDP information to match the FADT OEM information.
- //
- ASSERT(EfiAcpiContext.Rsdp != NULL);
- EfiCopyMem(&(EfiAcpiContext.Rsdp->OemId),
- &(EfiAcpiContext.Fadt->Header.OemId),
- sizeof(EfiAcpiContext.Fadt->Header.OemId));
- //
- // Copy the RSDT OEM information to match the FADT.
- //
- ASSERT(EfiAcpiContext.Rsdt != NULL);
- EfiCopyMem(&(EfiAcpiContext.Rsdt->Header.OemId),
- &(EfiAcpiContext.Fadt->Header.OemId),
- sizeof(EfiAcpiContext.Fadt->Header.OemId));
- EfiCopyMem(&(EfiAcpiContext.Rsdt->Header.OemTableId),
- &(EfiAcpiContext.Fadt->Header.OemTableId),
- sizeof(EfiAcpiContext.Fadt->Header.OemTableId));
- EfiAcpiContext.Rsdt->Header.OemRevision =
- EfiAcpiContext.Fadt->Header.OemRevision;
- //
- // Copy over the XSDT OEM information to match the FADT as well.
- //
- ASSERT(EfiAcpiContext.Xsdt != NULL);
- EfiCopyMem(&(EfiAcpiContext.Xsdt->Header.OemId),
- &(EfiAcpiContext.Fadt->Header.OemId),
- sizeof(EfiAcpiContext.Fadt->Header.OemId));
- EfiCopyMem(&(EfiAcpiContext.Xsdt->Header.OemTableId),
- &(EfiAcpiContext.Fadt->Header.OemTableId),
- sizeof(EfiAcpiContext.Fadt->Header.OemTableId));
- EfiAcpiContext.Xsdt->Header.OemRevision =
- EfiAcpiContext.Fadt->Header.OemRevision;
- if (Checksum != FALSE) {
- EfiAcpiChecksumTable(TableEntry->Table,
- TableEntry->Table->Length,
- OFFSET_OF(DESCRIPTION_HEADER, Checksum));
- }
- break;
- case FACS_SIGNATURE:
- if (EfiAcpiContext.Facs != NULL) {
- EfiFreePages(TableEntry->PageAddress, TableEntry->NumberOfPages);
- EfiFreePool(TableEntry);
- return EFI_ABORTED;
- }
- //
- // The FACS is referenced by the FADT and is not part of the RSDT.
- //
- AddToRsdt = FALSE;
- EfiAcpiContext.Facs = (PFACS)(TableEntry->Table);
- if (EfiAcpiContext.Fadt != NULL) {
- if (EfiAcpiContext.Facs <= (PFACS)0xFFFFFFFF) {
- EfiAcpiContext.Fadt->FirmwareControlAddress =
- (UINT32)(UINTN)(TableEntry->Table);
- } else {
- Buffer64 = (UINTN)(TableEntry->Table);
- EfiCopyMem(&(EfiAcpiContext.Fadt->XFirmwareControl),
- &Buffer64,
- sizeof(UINT64));
- }
- //
- // Checksum the FADT.
- //
- EfiAcpiChecksumTable(EfiAcpiContext.Fadt,
- EfiAcpiContext.Fadt->Header.Length,
- OFFSET_OF(DESCRIPTION_HEADER, Checksum));
- }
- break;
- case DSDT_SIGNATURE:
- if (EfiAcpiContext.Dsdt != NULL) {
- EfiFreePages(TableEntry->PageAddress, TableEntry->NumberOfPages);
- EfiFreePool(TableEntry);
- return EFI_ABORTED;
- }
- //
- // The DSDT is referenced by the FADT and is not part of the RSDT.
- //
- AddToRsdt = FALSE;
- EfiAcpiContext.Dsdt = (PDESCRIPTION_HEADER)TableEntry->Table;
- if (EfiAcpiContext.Fadt != NULL) {
- EfiAcpiContext.Fadt->DsdtAddress =
- (UINT32)(UINTN)(EfiAcpiContext.Dsdt);
- Buffer64 = (UINT64)(UINTN)(EfiAcpiContext.Dsdt);
- EfiCopyMem(&(EfiAcpiContext.Fadt->XDsdt),
- &Buffer64,
- sizeof(UINT64));
- //
- // Checksum the FADT.
- //
- EfiAcpiChecksumTable(EfiAcpiContext.Fadt,
- EfiAcpiContext.Fadt->Header.Length,
- OFFSET_OF(DESCRIPTION_HEADER, Checksum));
- }
- break;
- //
- // The average joe table.
- //
- default:
- if (Checksum != FALSE) {
- EfiAcpiChecksumTable(TableEntry->Table,
- TableEntry->Table->Length,
- OFFSET_OF(DESCRIPTION_HEADER, Checksum));
- }
- break;
- }
- //
- // Add the table to the global list.
- //
- INSERT_BEFORE(&(TableEntry->ListEntry), &(EfiAcpiContext.TableList));
- //
- // Add this to the RSDT/XSDT.
- //
- if (AddToRsdt != FALSE) {
- if (EfiAcpiContext.TableCount >= EfiAcpiContext.TableCapacity) {
- Status = EfipReallocateAcpiTableBuffer();
- if (EFI_ERROR(Status)) {
- ASSERT(FALSE);
- return EFI_OUT_OF_RESOURCES;
- }
- }
- RsdtEntry = (UINT32 *)((UINT8 *)(EfiAcpiContext.Rsdt) +
- sizeof(DESCRIPTION_HEADER) +
- (EfiAcpiContext.TableCount *
- sizeof(UINT32)));
- XsdtEntry = (VOID *)((UINT8 *)(EfiAcpiContext.Xsdt) +
- sizeof(DESCRIPTION_HEADER) +
- EfiAcpiContext.TableCount *
- sizeof(UINT64));
- *RsdtEntry = (UINT32)(UINTN)(TableEntry->Table);
- EfiAcpiContext.Rsdt->Header.Length += sizeof(UINT32);
- Buffer64 = (UINTN)(TableEntry->Table);
- EfiCopyMem(XsdtEntry, &Buffer64, sizeof(UINT64));
- EfiAcpiContext.Xsdt->Header.Length += sizeof(UINT64);
- EfiAcpiContext.TableCount += 1;
- }
- EfipAcpiChecksumCommonTables();
- return EFI_SUCCESS;
- }
- EFI_STATUS
- EfipRemoveAcpiTableFromList (
- UINTN Handle
- )
- /*++
- Routine Description:
- This routine removes the table with the given handle.
- Arguments:
- Handle - Supplies the handle of the table to remove.
- Return Value:
- EFI Status code.
- --*/
- {
- EFI_STATUS Status;
- PEFI_ACPI_TABLE_ENTRY TableEntry;
- TableEntry = NULL;
- Status = EfipAcpiFindTableByHandle(Handle,
- &(EfiAcpiContext.TableList),
- &TableEntry);
- if (EFI_ERROR(Status)) {
- return EFI_NOT_FOUND;
- }
- EfipAcpiDeleteTable(TableEntry);
- return EFI_SUCCESS;
- }
- VOID
- EfipAcpiDeleteTable (
- PEFI_ACPI_TABLE_ENTRY Table
- )
- /*++
- Routine Description:
- This routine removes the given table from the ACPI list.
- Arguments:
- Table - Supplies a pointer to the table entry to remove.
- Return Value:
- EFI Status code.
- --*/
- {
- BOOLEAN RemoveFromRsdt;
- UINT32 TableSignature;
- RemoveFromRsdt = TRUE;
- ASSERT(Table->Table != NULL);
- TableSignature = Table->Table->Signature;
- if ((TableSignature == FACS_SIGNATURE) ||
- (TableSignature == DSDT_SIGNATURE)) {
- RemoveFromRsdt = FALSE;
- }
- if (TableSignature == FADT_SIGNATURE) {
- RemoveFromRsdt = FALSE;
- }
- if (RemoveFromRsdt != FALSE) {
- ASSERT((EfiAcpiContext.Rsdt != NULL) && (EfiAcpiContext.Xsdt != NULL));
- EfipAcpiRemoveTableFromRsdt(Table,
- &(EfiAcpiContext.TableCount),
- &(EfiAcpiContext.Rsdt->Header),
- &(EfiAcpiContext.Xsdt->Header));
- }
- switch (TableSignature) {
- case FADT_SIGNATURE:
- EfiAcpiContext.Fadt = NULL;
- break;
- case FACS_SIGNATURE:
- EfiAcpiContext.Facs = NULL;
- if (EfiAcpiContext.Fadt != NULL) {
- EfiAcpiContext.Fadt->FirmwareControlAddress = 0;
- EfiSetMem(&(EfiAcpiContext.Fadt->XFirmwareControl),
- sizeof(UINT64),
- 0);
- EfiAcpiChecksumTable(EfiAcpiContext.Fadt,
- EfiAcpiContext.Fadt->Header.Length,
- OFFSET_OF(DESCRIPTION_HEADER, Checksum));
- }
- break;
- case DSDT_SIGNATURE:
- EfiAcpiContext.Dsdt = NULL;
- if (EfiAcpiContext.Fadt != NULL) {
- EfiAcpiContext.Fadt->DsdtAddress = 0;
- EfiSetMem(&(EfiAcpiContext.Fadt->XDsdt), sizeof(UINT64), 0);
- EfiAcpiChecksumTable(EfiAcpiContext.Fadt,
- EfiAcpiContext.Fadt->Header.Length,
- OFFSET_OF(DESCRIPTION_HEADER, Checksum));
- }
- break;
- default:
- break;
- }
- //
- // Remove and free the table entry.
- //
- EfiFreePages(Table->PageAddress, Table->NumberOfPages);
- LIST_REMOVE(&(Table->ListEntry));
- Table->Magic = 0;
- EfiFreePool(Table);
- return;
- }
- EFI_STATUS
- EfipAcpiRemoveTableFromRsdt (
- PEFI_ACPI_TABLE_ENTRY Table,
- UINTN *TableCount,
- PDESCRIPTION_HEADER Rsdt,
- PDESCRIPTION_HEADER Xsdt
- )
- /*++
- Routine Description:
- This routine removes the given table from the RSDT and optionally from the
- XSDT.
- Arguments:
- Table - Supplies a pointer to the table entry to remove.
- TableCount - Supplies a pointer to the current number of tables. This value
- will be updated.
- Rsdt - Supplies a pointer to the RSDT to remove the table from.
- Xsdt - Supplies an optional pointer to the XSDT to remove the table from.
- Return Value:
- EFI Status code.
- --*/
- {
- UINTN Index;
- UINT32 *RsdtEntry;
- UINT64 Table64;
- VOID *XsdtEntry;
- for (Index = 0; Index < *TableCount; Index += 1) {
- RsdtEntry = (UINT32 *)((UINT8 *)Rsdt +
- sizeof(DESCRIPTION_HEADER) +
- (Index * sizeof(UINT32)));
- XsdtEntry = NULL;
- Table64 = 0;
- if (Xsdt != NULL) {
- XsdtEntry = (UINT64 *)((UINT8 *)Xsdt +
- sizeof(DESCRIPTION_HEADER) +
- (Index * sizeof(UINT64)));
- EfiCopyMem(&Table64, XsdtEntry, sizeof(UINT64));
- }
- //
- // Fix up the table if this is the right entry.
- //
- if ((*RsdtEntry == (UINT32)(UINTN)(Table->Table)) &&
- ((Xsdt == NULL) || (Table64 == (UINT64)(UINTN)(Table->Table)))) {
- EfiCopyMem(RsdtEntry,
- RsdtEntry + 1,
- (*TableCount - Index) * sizeof(UINT32));
- Rsdt->Length -= sizeof(UINT32);
- if (Xsdt != NULL) {
- EfiCopyMem(XsdtEntry,
- (UINT64 *)XsdtEntry + 1,
- (*TableCount - Index * sizeof(UINT64)));
- Xsdt->Length -= sizeof(UINT64);
- }
- break;
- //
- // Watch out for the end of the list, fail if the table wasn't found.
- //
- } else if (Index + 1 == *TableCount) {
- return EFI_INVALID_PARAMETER;
- }
- }
- EfiAcpiChecksumTable(Rsdt,
- Rsdt->Length,
- OFFSET_OF(DESCRIPTION_HEADER, Checksum));
- if (Xsdt != NULL) {
- EfiAcpiChecksumTable(Xsdt,
- Xsdt->Length,
- OFFSET_OF(DESCRIPTION_HEADER, Checksum));
- }
- *TableCount -= 1;
- return EFI_SUCCESS;
- }
- EFI_STATUS
- EfipAcpiFindTableByHandle (
- UINTN Handle,
- PLIST_ENTRY ListHead,
- PEFI_ACPI_TABLE_ENTRY *FoundEntry
- )
- /*++
- Routine Description:
- This routine finds the table entry with the given handle.
- Arguments:
- Handle - Supplies the handle of the table to find.
- ListHead - Supplies a pointer to the head of the list of table entries.
- FoundEntry - Supplies a pointer where a pointer to the found entry will be
- returned on success.
- Return Value:
- EFI_SUCCESS on success.
- EFI_NOT_FOUND if no table with the given handle exists.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PEFI_ACPI_TABLE_ENTRY TableEntry;
- CurrentEntry = ListHead->Next;
- while (CurrentEntry != ListHead) {
- TableEntry = LIST_VALUE(CurrentEntry, EFI_ACPI_TABLE_ENTRY, ListEntry);
- ASSERT(TableEntry->Magic == EFI_ACPI_TABLE_ENTRY_MAGIC);
- if (TableEntry->Handle == Handle) {
- *FoundEntry = TableEntry;
- return EFI_SUCCESS;
- }
- CurrentEntry = CurrentEntry->Next;
- }
- return EFI_NOT_FOUND;
- }
- EFI_STATUS
- EfipReallocateAcpiTableBuffer (
- VOID
- )
- /*++
- Routine Description:
- This routine reallocates the RSDT and XSDT table arrays.
- Arguments:
- None.
- Return Value:
- EFI Status code.
- --*/
- {
- UINTN CopySize;
- UINT64 CurrentData;
- UINTN NewTableCount;
- EFI_ACPI_CONTEXT Original;
- EFI_PHYSICAL_ADDRESS PageAddress;
- UINT8 *Pointer;
- EFI_STATUS Status;
- UINTN TotalSize;
- EfiCopyMem(&Original, &EfiAcpiContext, sizeof(EFI_ACPI_CONTEXT));
- NewTableCount = Original.TableCapacity + EFI_ACPI_TABLE_EXPANSION_COUNT;
- TotalSize = sizeof(DESCRIPTION_HEADER) + (NewTableCount * sizeof(UINT32)) +
- sizeof(DESCRIPTION_HEADER) + (NewTableCount * sizeof(UINT64));
- //
- // Allocate memory in the lower 4GB.
- //
- PageAddress = 0xFFFFFFFF;
- Status = EfiAllocatePages(AllocateMaxAddress,
- EfiACPIReclaimMemory,
- EFI_SIZE_TO_PAGES(TotalSize),
- &PageAddress);
- if (EFI_ERROR(Status)) {
- return EFI_OUT_OF_RESOURCES;
- }
- Pointer = (UINT8 *)(UINTN)PageAddress;
- EfiSetMem(Pointer, TotalSize, 0);
- EfiAcpiContext.Rsdt = (PRSDT)Pointer;
- Pointer += sizeof(DESCRIPTION_HEADER) + (NewTableCount * sizeof(UINT32));
- EfiAcpiContext.Xsdt = (PXSDT)Pointer;
- //
- // Update the RSDP to point to the new RSDT and XSDT.
- //
- ASSERT(EfiAcpiContext.Rsdp != NULL);
- EfiAcpiContext.Rsdp->RsdtAddress = (UINT32)(UINTN)(EfiAcpiContext.Rsdt);
- CurrentData = (UINTN)(EfiAcpiContext.Xsdt);
- EfiCopyMem(&(EfiAcpiContext.Rsdp->XsdtAddress),
- &CurrentData,
- sizeof(UINT64));
- //
- // Copy the original structures to the new buffer.
- //
- CopySize = sizeof(DESCRIPTION_HEADER) +
- (Original.TableCount * sizeof(UINT32));
- EfiCopyMem(EfiAcpiContext.Rsdt, Original.Rsdt, CopySize);
- CopySize = sizeof(DESCRIPTION_HEADER) +
- (Original.TableCount * sizeof(UINT64));
- EfiCopyMem(EfiAcpiContext.Xsdt, Original.Xsdt, CopySize);
- //
- // Free the original buffer.
- //
- TotalSize = sizeof(DESCRIPTION_HEADER) +
- (Original.TableCapacity * sizeof(UINT32)) +
- sizeof(DESCRIPTION_HEADER) +
- (Original.TableCapacity * sizeof(UINT64));
- EfiFreePages((EFI_PHYSICAL_ADDRESS)(UINTN)(Original.Rsdt),
- EFI_SIZE_TO_PAGES(TotalSize));
- EfiAcpiContext.TableCapacity = NewTableCount;
- return EFI_SUCCESS;
- }
- EFI_STATUS
- EfipAcpiPublishTables (
- VOID
- )
- /*++
- Routine Description:
- This routine installs the ACPI tables as an EFI configuration table.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- {
- UINT32 *RsdtEntry;
- EFI_STATUS Status;
- UINT64 Value64;
- VOID *XsdtEntry;
- if (EfiAcpiContext.Fadt != NULL) {
- RsdtEntry = (UINT32 *)((UINT8 *)(EfiAcpiContext.Rsdt) +
- sizeof(DESCRIPTION_HEADER));
- *RsdtEntry = (UINT32)(UINTN)(EfiAcpiContext.Fadt);
- XsdtEntry = (VOID *)((UINT8 *)(EfiAcpiContext.Xsdt) +
- sizeof(DESCRIPTION_HEADER));
- Value64 = (UINT64)(UINTN)(EfiAcpiContext.Fadt);
- EfiCopyMem(XsdtEntry, &Value64, sizeof(UINT64));
- }
- EfipAcpiChecksumCommonTables();
- Status = EfiInstallConfigurationTable(&EfiAcpiTableGuid,
- EfiAcpiContext.Rsdp);
- if (EFI_ERROR(Status)) {
- return EFI_ABORTED;
- }
- return EFI_SUCCESS;
- }
- VOID
- EfipAcpiChecksumCommonTables (
- VOID
- )
- /*++
- Routine Description:
- This routine recomputes the checksums on everyone's favorite ACPI tables.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- {
- UINTN Offset;
- Offset = OFFSET_OF(DESCRIPTION_HEADER, Checksum);
- EfiAcpiChecksumTable(EfiAcpiContext.Rsdp,
- OFFSET_OF(RSDP, Length),
- OFFSET_OF(RSDP, Checksum));
- EfiAcpiChecksumTable(EfiAcpiContext.Rsdp,
- sizeof(RSDP),
- OFFSET_OF(RSDP, ExtendedChecksum));
- EfiAcpiChecksumTable(EfiAcpiContext.Rsdt,
- EfiAcpiContext.Rsdt->Header.Length,
- Offset);
- EfiAcpiChecksumTable(EfiAcpiContext.Xsdt,
- EfiAcpiContext.Xsdt->Header.Length,
- Offset);
- return;
- }
|