static ACPI_STATUS OslMapTable ( ACPI_SIZE Address, char *Signature, ACPI_TABLE_HEADER **Table) { ACPI_TABLE_HEADER *MappedTable; UINT32 Length; /* Map the header so we can get the table length */ MappedTable = AcpiOsMapMemory (Address, sizeof (*MappedTable)); if (!MappedTable) { return (AE_BAD_ADDRESS); } /* Check if table is valid */ if (!ApIsValidHeader (MappedTable)) { AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); return (AE_BAD_HEADER); } /* If specified, signature must match */ if (Signature && !ACPI_COMPARE_NAME (Signature, MappedTable->Signature)) { AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); return (AE_NOT_EXIST); } /* Map the entire table */ Length = MappedTable->Length; AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); MappedTable = AcpiOsMapMemory (Address, Length); if (!MappedTable) { return (AE_BAD_ADDRESS); } (void) ApIsValidChecksum (MappedTable); *Table = MappedTable; return (AE_OK); }
ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width) { void *LogicalAddress; LogicalAddress = AcpiOsMapMemory(Address, Width / 8); if (LogicalAddress == NULL) return (AE_NOT_EXIST); switch (Width) { case 8: *(volatile uint8_t *)LogicalAddress = Value; break; case 16: *(volatile uint16_t *)LogicalAddress = Value; break; case 32: *(volatile uint32_t *)LogicalAddress = Value; break; case 64: *(volatile uint64_t *)LogicalAddress = Value; break; } AcpiOsUnmapMemory(LogicalAddress, Width / 8); return (AE_OK); }
/* * AcpiOsWriteMemory: * * Write a value to a memory location. */ ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 Value, UINT32 Width) { void *LogicalAddress; ACPI_STATUS rv = AE_OK; LogicalAddress = AcpiOsMapMemory(Address, Width / 8); if (LogicalAddress == NULL) return AE_NOT_FOUND; switch (Width) { case 8: *(volatile uint8_t *) LogicalAddress = Value; break; case 16: *(volatile uint16_t *) LogicalAddress = Value; break; case 32: *(volatile uint32_t *) LogicalAddress = Value; break; default: rv = AE_BAD_PARAMETER; } AcpiOsUnmapMemory(LogicalAddress, Width / 8); return rv; }
void AcpiTbInstallTable ( ACPI_PHYSICAL_ADDRESS Address, char *Signature, UINT32 TableIndex) { ACPI_TABLE_HEADER *Table; ACPI_TABLE_HEADER *FinalTable; ACPI_TABLE_DESC *TableDesc; if (!Address) { ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]", Signature)); return; } /* Map just the table header */ Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); if (!Table) { ACPI_ERROR ((AE_INFO, "Could not map memory for table [%s] at %p", Signature, ACPI_CAST_PTR (void, Address))); return; }
ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value, UINT32 Width) { void *LogicalAddress; LogicalAddress = AcpiOsMapMemory(Address, Width / 8); if (LogicalAddress == NULL) return (AE_NOT_EXIST); switch (Width) { case 8: *(u_int8_t *)Value = (*(volatile u_int8_t *)LogicalAddress); break; case 16: *(u_int16_t *)Value = (*(volatile u_int16_t *)LogicalAddress); break; case 32: *(u_int32_t *)Value = (*(volatile u_int32_t *)LogicalAddress); break; case 64: *(u_int64_t *)Value = (*(volatile u_int64_t *)LogicalAddress); break; default: /* debug trap goes here */ break; } AcpiOsUnmapMemory(LogicalAddress, Width / 8); return (AE_OK); }
void AcpiTbParseFadt ( void) { UINT32 Length; ACPI_TABLE_HEADER *Table; /* * The FADT has multiple versions with different lengths, * and it contains pointers to both the DSDT and FACS tables. * * Get a local copy of the FADT and convert it to a common format * Map entire FADT, assumed to be smaller than one page. */ Length = AcpiGbl_RootTableList.Tables[AcpiGbl_FadtIndex].Length; Table = AcpiOsMapMemory ( AcpiGbl_RootTableList.Tables[AcpiGbl_FadtIndex].Address, Length); if (!Table) { return; } /* * Validate the FADT checksum before we copy the table. Ignore * checksum error as we want to try to get the DSDT and FACS. */ (void) AcpiTbVerifyChecksum (Table, Length); /* Create a local copy of the FADT in common ACPI 2.0+ format */ AcpiTbCreateLocalFadt (Table, Length); /* All done with the real FADT, unmap it */ AcpiOsUnmapMemory (Table, Length); /* Obtain the DSDT and FACS tables via their addresses within the FADT */ AcpiTbInstallFixedTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XDsdt, ACPI_SIG_DSDT, &AcpiGbl_DsdtIndex); /* If Hardware Reduced flag is set, there is no FACS */ if (!AcpiGbl_ReducedHardware) { if (AcpiGbl_FADT.Facs) { AcpiTbInstallFixedTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.Facs, ACPI_SIG_FACS, &AcpiGbl_FacsIndex); } if (AcpiGbl_FADT.XFacs) { AcpiTbInstallFixedTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs, ACPI_SIG_FACS, &AcpiGbl_XFacsIndex); } } }
ACPI_STATUS AcpiTbAcquireTempTable ( ACPI_TABLE_DESC *TableDesc, ACPI_PHYSICAL_ADDRESS Address, UINT8 Flags) { ACPI_TABLE_HEADER *TableHeader; switch (Flags & ACPI_TABLE_ORIGIN_MASK) { case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: /* Get the length of the full table from the header */ TableHeader = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); if (!TableHeader) { return (AE_NO_MEMORY); } AcpiTbInitTableDescriptor (TableDesc, Address, Flags, TableHeader); AcpiOsUnmapMemory (TableHeader, sizeof (ACPI_TABLE_HEADER)); return (AE_OK); case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: TableHeader = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ACPI_PHYSADDR_TO_PTR (Address)); if (!TableHeader) { return (AE_NO_MEMORY); } AcpiTbInitTableDescriptor (TableDesc, Address, Flags, TableHeader); return (AE_OK); default: break; } /* Table is not valid yet */ return (AE_NO_MEMORY); }
void AcpiTbParseFadt ( ACPI_NATIVE_UINT TableIndex, UINT8 Flags) { UINT32 Length; ACPI_TABLE_HEADER *Table; /* * The FADT has multiple versions with different lengths, * and it contains pointers to both the DSDT and FACS tables. * * Get a local copy of the FADT and convert it to a common format * Map entire FADT, assumed to be smaller than one page. */ Length = AcpiGbl_RootTableList.Tables[TableIndex].Length; Table = AcpiOsMapMemory ( AcpiGbl_RootTableList.Tables[TableIndex].Address, Length); if (!Table) { return; } /* * Validate the FADT checksum before we copy the table. Ignore * checksum error as we want to try to get the DSDT and FACS. */ (void) AcpiTbVerifyChecksum (Table, Length); /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ AcpiTbCreateLocalFadt (Table, Length); /* All done with the real FADT, unmap it */ AcpiOsUnmapMemory (Table, Length); /* Obtain the DSDT and FACS tables via their addresses within the FADT */ AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XDsdt, Flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs, Flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); }
ACPI_STATUS AcpiTbAcquireTable ( ACPI_TABLE_DESC *TableDesc, ACPI_TABLE_HEADER **TablePtr, UINT32 *TableLength, UINT8 *TableFlags) { ACPI_TABLE_HEADER *Table = NULL; switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) { case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: Table = AcpiOsMapMemory (TableDesc->Address, TableDesc->Length); break; case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ACPI_PHYSADDR_TO_PTR (TableDesc->Address)); break; default: break; } /* Table is not valid yet */ if (!Table) { return (AE_NO_MEMORY); } /* Fill the return values */ *TablePtr = Table; *TableLength = TableDesc->Length; *TableFlags = TableDesc->Flags; return (AE_OK); }
ACPI_TABLE_HEADER * AcpiTbTableOverride ( ACPI_TABLE_HEADER *TableHeader, ACPI_TABLE_DESC *TableDesc) { ACPI_STATUS Status; ACPI_TABLE_HEADER *NewTable = NULL; ACPI_PHYSICAL_ADDRESS NewAddress = 0; UINT32 NewTableLength = 0; UINT8 NewFlags; char *OverrideType; /* (1) Attempt logical override (returns a logical address) */ Status = AcpiOsTableOverride (TableHeader, &NewTable); if (ACPI_SUCCESS (Status) && NewTable) { NewAddress = ACPI_PTR_TO_PHYSADDR (NewTable); NewTableLength = NewTable->Length; NewFlags = ACPI_TABLE_ORIGIN_OVERRIDE; OverrideType = "Logical"; goto FinishOverride; } /* (2) Attempt physical override (returns a physical address) */ Status = AcpiOsPhysicalTableOverride (TableHeader, &NewAddress, &NewTableLength); if (ACPI_SUCCESS (Status) && NewAddress && NewTableLength) { /* Map the entire new table */ NewTable = AcpiOsMapMemory (NewAddress, NewTableLength); if (!NewTable) { ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, "%4.4s %p Attempted physical table override failed", TableHeader->Signature, ACPI_CAST_PTR (void, TableDesc->Address))); return (NULL); }
ACPI_STATUS AcpiTbVerifyTable ( ACPI_TABLE_DESC *TableDesc) { ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE (TbVerifyTable); /* Map the table if necessary */ if (!TableDesc->Pointer) { if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) == ACPI_TABLE_ORIGIN_MAPPED) { TableDesc->Pointer = AcpiOsMapMemory ( TableDesc->Address, TableDesc->Length); } if (!TableDesc->Pointer) { return_ACPI_STATUS (AE_NO_MEMORY); } } /* FACS is the odd table, has no standard ACPI header and no checksum */ if (!ACPI_COMPARE_NAME (&TableDesc->Signature, ACPI_SIG_FACS)) { /* Always calculate checksum, ignore bad checksum if requested */ Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExSystemMemorySpaceHandler ( UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 BitWidth, UINT64 *Value, void *HandlerContext, void *RegionContext) { ACPI_STATUS Status = AE_OK; void *LogicalAddrPtr = NULL; ACPI_MEM_SPACE_CONTEXT *MemInfo = RegionContext; UINT32 Length; ACPI_SIZE MapLength; ACPI_SIZE PageBoundaryMapLength; #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED UINT32 Remainder; #endif ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler); /* Validate and translate the bit width */ switch (BitWidth) { case 8: Length = 1; break; case 16: Length = 2; break; case 32: Length = 4; break; case 64: Length = 8; break; default: ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %u", BitWidth)); return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED /* * Hardware does not support non-aligned data transfers, we must verify * the request. */ (void) AcpiUtShortDivide ((UINT64) Address, Length, NULL, &Remainder); if (Remainder != 0) { return_ACPI_STATUS (AE_AML_ALIGNMENT); } #endif /* * Does the request fit into the cached memory mapping? * Is 1) Address below the current mapping? OR * 2) Address beyond the current mapping? */ if ((Address < MemInfo->MappedPhysicalAddress) || (((UINT64) Address + Length) > ((UINT64) MemInfo->MappedPhysicalAddress + MemInfo->MappedLength))) { /* * The request cannot be resolved by the current memory mapping; * Delete the existing mapping and create a new one. */ if (MemInfo->MappedLength) { /* Valid mapping, delete it */ AcpiOsUnmapMemory (MemInfo->MappedLogicalAddress, MemInfo->MappedLength); } /* * October 2009: Attempt to map from the requested address to the * end of the region. However, we will never map more than one * page, nor will we cross a page boundary. */ MapLength = (ACPI_SIZE) ((MemInfo->Address + MemInfo->Length) - Address); /* * If mapping the entire remaining portion of the region will cross * a page boundary, just map up to the page boundary, do not cross. * On some systems, crossing a page boundary while mapping regions * can cause warnings if the pages have different attributes * due to resource management. * * This has the added benefit of constraining a single mapping to * one page, which is similar to the original code that used a 4k * maximum window. */ PageBoundaryMapLength = (ACPI_SIZE) (ACPI_ROUND_UP (Address, ACPI_DEFAULT_PAGE_SIZE) - Address); if (PageBoundaryMapLength == 0) { PageBoundaryMapLength = ACPI_DEFAULT_PAGE_SIZE; } if (MapLength > PageBoundaryMapLength) { MapLength = PageBoundaryMapLength; } /* Create a new mapping starting at the address given */ MemInfo->MappedLogicalAddress = AcpiOsMapMemory (Address, MapLength); if (!MemInfo->MappedLogicalAddress) { ACPI_ERROR ((AE_INFO, "Could not map memory at 0x%8.8X%8.8X, size %u", ACPI_FORMAT_UINT64 (Address), (UINT32) MapLength)); MemInfo->MappedLength = 0; return_ACPI_STATUS (AE_NO_MEMORY); } /* Save the physical address and mapping size */ MemInfo->MappedPhysicalAddress = Address; MemInfo->MappedLength = MapLength; } /* * Generate a logical pointer corresponding to the address we want to * access */ LogicalAddrPtr = MemInfo->MappedLogicalAddress + ((UINT64) Address - (UINT64) MemInfo->MappedPhysicalAddress); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", BitWidth, Function, ACPI_FORMAT_UINT64 (Address))); /* * Perform the memory read or write * * Note: For machines that do not support non-aligned transfers, the target * address was checked for alignment above. We do not attempt to break the * transfer up into smaller (byte-size) chunks because the AML specifically * asked for a transfer width that the hardware may require. */ switch (Function) { case ACPI_READ: *Value = 0; switch (BitWidth) { case 8: *Value = (UINT64) ACPI_GET8 (LogicalAddrPtr); break; case 16: *Value = (UINT64) ACPI_GET16 (LogicalAddrPtr); break; case 32: *Value = (UINT64) ACPI_GET32 (LogicalAddrPtr); break; case 64: *Value = (UINT64) ACPI_GET64 (LogicalAddrPtr); break; default: /* BitWidth was already validated */ break; } break; case ACPI_WRITE: switch (BitWidth) { case 8: ACPI_SET8 (LogicalAddrPtr, *Value); break; case 16: ACPI_SET16 (LogicalAddrPtr, *Value); break; case 32: ACPI_SET32 (LogicalAddrPtr, *Value); break; case 64: ACPI_SET64 (LogicalAddrPtr, *Value); break; default: /* BitWidth was already validated */ break; } break; default: Status = AE_BAD_PARAMETER; break; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExSystemMemorySpaceHandler ( UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 BitWidth, ACPI_INTEGER *Value, void *HandlerContext, void *RegionContext) { ACPI_STATUS Status = AE_OK; void *LogicalAddrPtr = NULL; ACPI_MEM_SPACE_CONTEXT *MemInfo = RegionContext; UINT32 Length; ACPI_SIZE WindowSize; #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED UINT32 Remainder; #endif ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler); /* Validate and translate the bit width */ switch (BitWidth) { case 8: Length = 1; break; case 16: Length = 2; break; case 32: Length = 4; break; case 64: Length = 8; break; default: ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %d", BitWidth)); return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED /* * Hardware does not support non-aligned data transfers, we must verify * the request. */ (void) AcpiUtShortDivide ((ACPI_INTEGER) Address, Length, NULL, &Remainder); if (Remainder != 0) { return_ACPI_STATUS (AE_AML_ALIGNMENT); } #endif /* * Does the request fit into the cached memory mapping? * Is 1) Address below the current mapping? OR * 2) Address beyond the current mapping? */ if ((Address < MemInfo->MappedPhysicalAddress) || (((ACPI_INTEGER) Address + Length) > ((ACPI_INTEGER) MemInfo->MappedPhysicalAddress + MemInfo->MappedLength))) { /* * The request cannot be resolved by the current memory mapping; * Delete the existing mapping and create a new one. */ if (MemInfo->MappedLength) { /* Valid mapping, delete it */ AcpiOsUnmapMemory (MemInfo->MappedLogicalAddress, MemInfo->MappedLength); } /* * Don't attempt to map memory beyond the end of the region, and * constrain the maximum mapping size to something reasonable. */ WindowSize = (ACPI_SIZE) ((MemInfo->Address + MemInfo->Length) - Address); if (WindowSize > ACPI_SYSMEM_REGION_WINDOW_SIZE) { WindowSize = ACPI_SYSMEM_REGION_WINDOW_SIZE; } /* Create a new mapping starting at the address given */ MemInfo->MappedLogicalAddress = AcpiOsMapMemory ( (ACPI_PHYSICAL_ADDRESS) Address, WindowSize); if (!MemInfo->MappedLogicalAddress) { ACPI_ERROR ((AE_INFO, "Could not map memory at %8.8X%8.8X, size %X", ACPI_FORMAT_NATIVE_UINT (Address), (UINT32) WindowSize)); MemInfo->MappedLength = 0; return_ACPI_STATUS (AE_NO_MEMORY); } /* Save the physical address and mapping size */ MemInfo->MappedPhysicalAddress = Address; MemInfo->MappedLength = WindowSize; } /* * Generate a logical pointer corresponding to the address we want to * access */ LogicalAddrPtr = MemInfo->MappedLogicalAddress + ((ACPI_INTEGER) Address - (ACPI_INTEGER) MemInfo->MappedPhysicalAddress); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", BitWidth, Function, ACPI_FORMAT_NATIVE_UINT (Address))); /* * Perform the memory read or write * * Note: For machines that do not support non-aligned transfers, the target * address was checked for alignment above. We do not attempt to break the * transfer up into smaller (byte-size) chunks because the AML specifically * asked for a transfer width that the hardware may require. */ switch (Function) { case ACPI_READ: *Value = 0; switch (BitWidth) { case 8: *Value = (ACPI_INTEGER) ACPI_GET8 (LogicalAddrPtr); break; case 16: *Value = (ACPI_INTEGER) ACPI_GET16 (LogicalAddrPtr); break; case 32: *Value = (ACPI_INTEGER) ACPI_GET32 (LogicalAddrPtr); break; case 64: *Value = (ACPI_INTEGER) ACPI_GET64 (LogicalAddrPtr); break; default: /* BitWidth was already validated */ break; } break; case ACPI_WRITE: switch (BitWidth) { case 8: ACPI_SET8 (LogicalAddrPtr) = (UINT8) *Value; break; case 16: ACPI_SET16 (LogicalAddrPtr) = (UINT16) *Value; break; case 32: ACPI_SET32 ( LogicalAddrPtr) = (UINT32) *Value; break; case 64: ACPI_SET64 (LogicalAddrPtr) = (UINT64) *Value; break; default: /* BitWidth was already validated */ break; } break; default: Status = AE_BAD_PARAMETER; break; } return_ACPI_STATUS (Status); }
static ACPI_STATUS OslAddTablesToList( void) { ACPI_PHYSICAL_ADDRESS TableAddress; OSL_TABLE_INFO *Info = NULL; OSL_TABLE_INFO *NewInfo; ACPI_TABLE_HEADER *Table; UINT8 Instance; UINT8 NumberOfTables; int i; /* Initialize the table list on first invocation */ if (Gbl_TableListInitialized) { return (AE_OK); } /* Add mandatory tables to global table list first */ for (i = 0; i < 4; i++) { NewInfo = calloc (1, sizeof (*NewInfo)); if (!NewInfo) { return (AE_NO_MEMORY); } switch (i) { case 0: Gbl_TableListHead = Info = NewInfo; continue; case 1: ACPI_MOVE_NAME (NewInfo->Signature, Gbl_Revision ? ACPI_SIG_XSDT : ACPI_SIG_RSDT); break; case 2: ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_FACS); break; default: ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_DSDT); } Info->Next = NewInfo; Info = NewInfo; Gbl_TableListHead->Instance++; } /* Add normal tables from RSDT/XSDT to global list */ if (Gbl_Revision) { NumberOfTables = (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header)) / sizeof (Gbl_Xsdt->TableOffsetEntry[0]); } else { NumberOfTables = (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header)) / sizeof (Gbl_Rsdt->TableOffsetEntry[0]); } for (i = 0; i < NumberOfTables; i++) { if (Gbl_Revision) { TableAddress = Gbl_Xsdt->TableOffsetEntry[i]; } else { TableAddress = Gbl_Rsdt->TableOffsetEntry[i]; } Table = AcpiOsMapMemory (TableAddress, sizeof (*Table)); if (!Table) { return (AE_BAD_ADDRESS); } Instance = 0; NewInfo = Gbl_TableListHead; while (NewInfo->Next != NULL) { NewInfo = NewInfo->Next; if (ACPI_COMPARE_NAME (Table->Signature, NewInfo->Signature)) { Instance++; } } NewInfo = calloc (1, sizeof (*NewInfo)); if (!NewInfo) { AcpiOsUnmapMemory (Table, sizeof (*Table)); return (AE_NO_MEMORY); } ACPI_MOVE_NAME (NewInfo->Signature, Table->Signature); AcpiOsUnmapMemory (Table, sizeof (*Table)); NewInfo->Instance = Instance; NewInfo->Address = TableAddress; Info->Next = NewInfo; Info = NewInfo; Gbl_TableListHead->Instance++; } Gbl_TableListInitialized = TRUE; return (AE_OK); }
static ACPI_STATUS OslGetTableViaRoot ( char *Signature, UINT32 Instance, ACPI_TABLE_HEADER **Table, ACPI_PHYSICAL_ADDRESS *Address) { ACPI_TABLE_HEADER *LocalTable = NULL; ACPI_TABLE_HEADER *MappedTable = NULL; UINT8 NumberOfTables; UINT32 CurrentInstance = 0; ACPI_PHYSICAL_ADDRESS TableAddress = 0; ACPI_STATUS Status; UINT32 i; /* DSDT and FACS address must be extracted from the FADT */ if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) || ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) { /* * Get the appropriate address, either 32-bit or 64-bit. Be very * careful about the FADT length and validate table addresses. * Note: The 64-bit addresses have priority. */ if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT)) { if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) && Gbl_Fadt->XDsdt) { TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt; } else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) && Gbl_Fadt->Dsdt) { TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt; } } else /* FACS */ { if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) && Gbl_Fadt->XFacs) { TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs; } else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) && Gbl_Fadt->Facs) { TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs; } } } else /* Case for a normal ACPI table */ { if (Gbl_Revision) { NumberOfTables = (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header)) / sizeof (Gbl_Xsdt->TableOffsetEntry[0]); } else /* Use RSDT if XSDT is not available */ { NumberOfTables = (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header)) / sizeof (Gbl_Rsdt->TableOffsetEntry[0]); } /* Search RSDT/XSDT for the requested table */ for (i = 0; i < NumberOfTables; i++) { if (Gbl_Revision) { TableAddress = Gbl_Xsdt->TableOffsetEntry[i]; } else { TableAddress = Gbl_Rsdt->TableOffsetEntry[i]; } MappedTable = AcpiOsMapMemory (TableAddress, sizeof (*MappedTable)); if (!MappedTable) { return (AE_BAD_ADDRESS); } /* Does this table match the requested signature? */ if (ACPI_COMPARE_NAME (MappedTable->Signature, Signature)) { /* Match table instance (for SSDT/UEFI tables) */ if (CurrentInstance == Instance) { AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); break; } CurrentInstance++; } AcpiOsUnmapMemory (MappedTable, MappedTable->Length); TableAddress = 0; } } if (!TableAddress) { if (CurrentInstance) { return (AE_LIMIT); } return (AE_NOT_FOUND); } /* Now we can get the requested table */ Status = OslMapTable (TableAddress, Signature, &MappedTable); if (ACPI_FAILURE (Status)) { return (Status); } /* Copy table to local buffer and return it */ LocalTable = calloc (1, MappedTable->Length); if (!LocalTable) { AcpiOsUnmapMemory (MappedTable, MappedTable->Length); return (AE_NO_MEMORY); } ACPI_MEMCPY (LocalTable, MappedTable, MappedTable->Length); AcpiOsUnmapMemory (MappedTable, MappedTable->Length); *Table = LocalTable; *Address = TableAddress; return (AE_OK); }
static ACPI_STATUS OslTableInitialize ( void) { char Buffer[32]; ACPI_TABLE_HEADER *MappedTable; UINT8 *TableAddress; UINT8 *RsdpAddress; ACPI_PHYSICAL_ADDRESS RsdpBase; ACPI_SIZE RsdpSize; ACPI_STATUS Status; u_long Address = 0; size_t Length = sizeof (Address); /* Get main ACPI tables from memory on first invocation of this function */ if (Gbl_MainTableObtained) { return (AE_OK); } /* Attempt to use kenv or sysctl to find RSD PTR record. */ if (Gbl_RsdpBase) { Address = Gbl_RsdpBase; } else if (kenv (KENV_GET, SYSTEM_KENV, Buffer, sizeof (Buffer)) > 0) { Address = ACPI_STRTOUL (Buffer, NULL, 0); } if (!Address) { if (sysctlbyname (SYSTEM_SYSCTL, &Address, &Length, NULL, 0) != 0) { Address = 0; } } if (Address) { RsdpBase = Address; RsdpSize = sizeof (Gbl_Rsdp); } else { RsdpBase = ACPI_HI_RSDP_WINDOW_BASE; RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE; } /* Get RSDP from memory */ RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize); if (!RsdpAddress) { return (AE_BAD_ADDRESS); } /* Search low memory for the RSDP */ TableAddress = AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize); if (!TableAddress) { AcpiOsUnmapMemory (RsdpAddress, RsdpSize); return (AE_ERROR); } ACPI_MEMCPY (&Gbl_Rsdp, TableAddress, sizeof (Gbl_Rsdp)); AcpiOsUnmapMemory (RsdpAddress, RsdpSize); /* Get XSDT from memory */ if (Gbl_Rsdp.Revision) { Status = OslMapTable (Gbl_Rsdp.XsdtPhysicalAddress, ACPI_SIG_XSDT, &MappedTable); if (ACPI_FAILURE (Status)) { return (Status); } Gbl_Revision = 2; Gbl_Xsdt = calloc (1, MappedTable->Length); if (!Gbl_Xsdt) { fprintf (stderr, "XSDT: Could not allocate buffer for table of length %X\n", MappedTable->Length); AcpiOsUnmapMemory (MappedTable, MappedTable->Length); return (AE_NO_MEMORY); } ACPI_MEMCPY (Gbl_Xsdt, MappedTable, MappedTable->Length); AcpiOsUnmapMemory (MappedTable, MappedTable->Length); } /* Get RSDT from memory */ if (Gbl_Rsdp.RsdtPhysicalAddress) { Status = OslMapTable (Gbl_Rsdp.RsdtPhysicalAddress, ACPI_SIG_RSDT, &MappedTable); if (ACPI_FAILURE (Status)) { return (Status); } Gbl_Rsdt = calloc (1, MappedTable->Length); if (!Gbl_Rsdt) { fprintf (stderr, "RSDT: Could not allocate buffer for table of length %X\n", MappedTable->Length); AcpiOsUnmapMemory (MappedTable, MappedTable->Length); return (AE_NO_MEMORY); } ACPI_MEMCPY (Gbl_Rsdt, MappedTable, MappedTable->Length); AcpiOsUnmapMemory (MappedTable, MappedTable->Length); } /* Get FADT from memory */ if (Gbl_Revision) { Gbl_FadtAddress = Gbl_Xsdt->TableOffsetEntry[0]; } else { Gbl_FadtAddress = Gbl_Rsdt->TableOffsetEntry[0]; } if (!Gbl_FadtAddress) { fprintf(stderr, "FADT: Table could not be found\n"); return (AE_ERROR); } Status = OslMapTable (Gbl_FadtAddress, ACPI_SIG_FADT, &MappedTable); if (ACPI_FAILURE (Status)) { return (Status); } Gbl_Fadt = calloc (1, MappedTable->Length); if (!Gbl_Fadt) { fprintf (stderr, "FADT: Could not allocate buffer for table of length %X\n", MappedTable->Length); AcpiOsUnmapMemory (MappedTable, MappedTable->Length); return (AE_NO_MEMORY); } ACPI_MEMCPY (Gbl_Fadt, MappedTable, MappedTable->Length); AcpiOsUnmapMemory (MappedTable, MappedTable->Length); Gbl_MainTableObtained = TRUE; return (AE_OK); }
ACPI_STATUS AcpiGetFirmwareTable ( ACPI_STRING Signature, UINT32 Instance, UINT32 Flags, ACPI_TABLE_HEADER **TablePointer) { ACPI_POINTER RsdpAddress; ACPI_POINTER Address; ACPI_STATUS Status; ACPI_TABLE_HEADER Header; ACPI_TABLE_DESC TableInfo; ACPI_TABLE_DESC RsdtInfo; UINT32 TableCount; UINT32 i; UINT32 j; ACPI_FUNCTION_TRACE ("AcpiGetFirmwareTable"); /* * Ensure that at least the table manager is initialized. We don't * require that the entire ACPI subsystem is up for this interface */ /* * If we have a buffer, we must have a length too */ if ((Instance == 0) || (!Signature) || (!TablePointer)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } RsdtInfo.Pointer = NULL; if (!AcpiGbl_RSDP) { /* Get the RSDP */ Status = AcpiOsGetRootPointer (Flags, &RsdpAddress); if (ACPI_FAILURE (Status)) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n")); return_ACPI_STATUS (AE_NO_ACPI_TABLES); } /* Map and validate the RSDP */ if ((Flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { Status = AcpiOsMapMemory (RsdpAddress.Pointer.Physical, sizeof (RSDP_DESCRIPTOR), (void **) &AcpiGbl_RSDP); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } else { AcpiGbl_RSDP = RsdpAddress.Pointer.Logical; } /* * The signature and checksum must both be correct */ if (ACPI_STRNCMP ((char *) AcpiGbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { /* Nope, BAD Signature */ return_ACPI_STATUS (AE_BAD_SIGNATURE); } if (AcpiTbChecksum (AcpiGbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { /* Nope, BAD Checksum */ return_ACPI_STATUS (AE_BAD_CHECKSUM); } } /* Get the RSDT and validate it */ AcpiTbGetRsdtAddress (&Address); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", AcpiGbl_RSDP, ACPI_HIDWORD (Address.Pointer.Value), ACPI_LODWORD (Address.Pointer.Value))); /* Insert ProcessorMode flags */ Address.PointerType |= Flags; Status = AcpiTbGetTable (&Address, &RsdtInfo); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } Status = AcpiTbValidateRsdt (RsdtInfo.Pointer); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Get the number of table pointers within the RSDT */ TableCount = AcpiTbGetTableCount (AcpiGbl_RSDP, RsdtInfo.Pointer); Address.PointerType = AcpiGbl_TableFlags | Flags; /* * Search the RSDT/XSDT for the correct instance of the * requested table */ for (i = 0, j = 0; i < TableCount; i++) { /* Get the next table pointer, handle RSDT vs. XSDT */ if (AcpiGbl_RSDP->Revision < 2) { Address.Pointer.Value = ((RSDT_DESCRIPTOR *) RsdtInfo.Pointer)->TableOffsetEntry[i]; } else { Address.Pointer.Value = ACPI_GET_ADDRESS ( ((XSDT_DESCRIPTOR *) RsdtInfo.Pointer)->TableOffsetEntry[i]); } /* Get the table header */ Status = AcpiTbGetTableHeader (&Address, &Header); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Compare table signatures and table instance */ if (!ACPI_STRNCMP (Header.Signature, Signature, ACPI_NAME_SIZE)) { /* An instance of the table was found */ j++; if (j >= Instance) { /* Found the correct instance, get the entire table */ Status = AcpiTbGetTableBody (&Address, &Header, &TableInfo); if (ACPI_FAILURE (Status)) { goto Cleanup; } *TablePointer = TableInfo.Pointer; goto Cleanup; } } } /* Did not find the table */ Status = AE_NOT_EXIST; Cleanup: AcpiOsUnmapMemory (RsdtInfo.Pointer, (ACPI_SIZE) RsdtInfo.Pointer->Length); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiTbFindRsdp ( ACPI_TABLE_DESC *TableInfo, UINT32 Flags) { UINT8 *TablePtr; UINT8 *MemRover; UINT64 PhysAddr; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE ("TbFindRsdp"); /* * Scan supports either 1) Logical addressing or 2) Physical addressing */ if ((Flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { /* * 1) Search EBDA (low memory) paragraphs */ Status = AcpiOsMapMemory ((UINT64) ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE, (void **) &TablePtr); if (ACPI_FAILURE (Status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n", ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE)); return_ACPI_STATUS (Status); } MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_LO_RSDP_WINDOW_SIZE); AcpiOsUnmapMemory (TablePtr, ACPI_LO_RSDP_WINDOW_SIZE); if (MemRover) { /* Found it, return the physical address */ PhysAddr = ACPI_LO_RSDP_WINDOW_BASE; PhysAddr += ACPI_PTR_DIFF (MemRover,TablePtr); TableInfo->PhysicalAddress = PhysAddr; return_ACPI_STATUS (AE_OK); } /* * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h */ Status = AcpiOsMapMemory ((UINT64) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE, (void **) &TablePtr); if (ACPI_FAILURE (Status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n", ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); return_ACPI_STATUS (Status); } MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); AcpiOsUnmapMemory (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); if (MemRover) { /* Found it, return the physical address */ PhysAddr = ACPI_HI_RSDP_WINDOW_BASE; PhysAddr += ACPI_PTR_DIFF (MemRover, TablePtr); TableInfo->PhysicalAddress = PhysAddr; return_ACPI_STATUS (AE_OK); } } /* * Physical addressing */ else { /* * 1) Search EBDA (low memory) paragraphs */ MemRover = AcpiTbScanMemoryForRsdp (ACPI_PHYSADDR_TO_PTR (ACPI_LO_RSDP_WINDOW_BASE), ACPI_LO_RSDP_WINDOW_SIZE); if (MemRover) { /* Found it, return the physical address */ TableInfo->PhysicalAddress = ACPI_TO_INTEGER (MemRover); return_ACPI_STATUS (AE_OK); } /* * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h */ MemRover = AcpiTbScanMemoryForRsdp (ACPI_PHYSADDR_TO_PTR (ACPI_HI_RSDP_WINDOW_BASE), ACPI_HI_RSDP_WINDOW_SIZE); if (MemRover) { /* Found it, return the physical address */ TableInfo->PhysicalAddress = ACPI_TO_INTEGER (MemRover); return_ACPI_STATUS (AE_OK); } } /* RSDP signature was not found */ return_ACPI_STATUS (AE_NOT_FOUND); }
ACPI_STATUS AcpiOsWriteMemory ( ACPI_PHYSICAL_ADDRESS Address, UINT32 Value, UINT32 Width) { void *memptr; ACPI_STATUS status = AE_ERROR; // dbgprintf("%s %x, %x\n",__FUNCTION__, Address, Value); if( (UINT64)Address+Width > 0x100000000ULL) return (AE_BAD_PARAMETER); if( Address >= 0x400000) { memptr = AcpiOsMapMemory(Address, Width); if(memptr) { status = AE_OK; switch (Width) { case 8: *(UINT8*)Address = (UINT8)Value; break; case 16: *(UINT16*)Address = (UINT16)Value; break; case 32: *(UINT32*)Address = Value; break; default: status = (AE_BAD_PARAMETER); } FreeKernelSpace(memptr); } return status; } else Address+= 0x80000000; switch (Width) { case 8: *(UINT8*)Address = (UINT8)Value; break; case 16: *(UINT16*)Address = (UINT16)Value; break; case 32: *(UINT32*)Address = Value; break; default: return (AE_BAD_PARAMETER); } return (AE_OK); }
ACPI_STATUS AcpiFindRootPointer ( ACPI_SIZE *TableAddress) { UINT8 *TablePtr; UINT8 *MemRover; UINT32 PhysicalAddress; ACPI_FUNCTION_TRACE (AcpiFindRootPointer); /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ TablePtr = AcpiOsMapMemory ( (ACPI_PHYSICAL_ADDRESS) ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH); if (!TablePtr) { ACPI_ERROR ((AE_INFO, "Could not map memory at 0x%8.8X for length %u", ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); return_ACPI_STATUS (AE_NO_MEMORY); } ACPI_MOVE_16_TO_32 (&PhysicalAddress, TablePtr); /* Convert segment part to physical address */ PhysicalAddress <<= 4; AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_PTR_LENGTH); /* EBDA present? */ if (PhysicalAddress > 0x400) { /* * 1b) Search EBDA paragraphs (EBDA is required to be a * minimum of 1K length) */ TablePtr = AcpiOsMapMemory ( (ACPI_PHYSICAL_ADDRESS) PhysicalAddress, ACPI_EBDA_WINDOW_SIZE); if (!TablePtr) { ACPI_ERROR ((AE_INFO, "Could not map memory at 0x%8.8X for length %u", PhysicalAddress, ACPI_EBDA_WINDOW_SIZE)); return_ACPI_STATUS (AE_NO_MEMORY); } MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_EBDA_WINDOW_SIZE); AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_WINDOW_SIZE); if (MemRover) { /* Return the physical address */ PhysicalAddress += (UINT32) ACPI_PTR_DIFF (MemRover, TablePtr); *TableAddress = PhysicalAddress; return_ACPI_STATUS (AE_OK); } } /* * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */ TablePtr = AcpiOsMapMemory ( (ACPI_PHYSICAL_ADDRESS) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE); if (!TablePtr) { ACPI_ERROR ((AE_INFO, "Could not map memory at 0x%8.8X for length %u", ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); return_ACPI_STATUS (AE_NO_MEMORY); } MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); AcpiOsUnmapMemory (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); if (MemRover) { /* Return the physical address */ PhysicalAddress = (UINT32) (ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (MemRover, TablePtr)); *TableAddress = PhysicalAddress; return_ACPI_STATUS (AE_OK); } /* A valid RSDP was not found */ ACPI_BIOS_ERROR ((AE_INFO, "A valid RSDP was not found")); return_ACPI_STATUS (AE_NOT_FOUND); }
/* * Find the BIOS date, and return TRUE if supplied * date is same or later than the BIOS date, or FALSE * if the BIOS date can't be fetched for any reason */ static int acpica_check_bios_date(int yy, int mm, int dd) { char *datep; int bios_year, bios_month, bios_day; /* If firmware has no bios, skip the check */ if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, "efi-systab")) return (TRUE); /* * PC BIOSes contain a string in the form of * "mm/dd/yy" at absolute address 0xffff5, * where mm, dd and yy are all ASCII digits. * We map the string, pluck out the values, * and accept all BIOSes from 1 Jan 1999 on * as valid. */ if ((datep = (char *)AcpiOsMapMemory(0xffff5, 8)) == NULL) return (FALSE); /* year */ bios_year = ((int)(*(datep + 6) - '0') * 10) + (*(datep + 7) - '0'); /* month */ bios_month = ((int)(*datep - '0') * 10) + (*(datep + 1) - '0'); /* day */ bios_day = ((int)(*(datep + 3) - '0') * 10) + (*(datep + 4) - '0'); AcpiOsUnmapMemory((void *) datep, 8); if (bios_year < 0 || bios_year > 99 || bios_month < 0 || bios_month > 99 || bios_day < 0 || bios_day > 99) { /* non-digit chars in BIOS date */ return (FALSE); } /* * Adjust for 2-digit year; note to grand-children: * need a new scheme before 2080 rolls around */ bios_year += (bios_year >= 80 && bios_year <= 99) ? 1900 : 2000; if (bios_year < yy) return (FALSE); else if (bios_year > yy) return (TRUE); if (bios_month < mm) return (FALSE); else if (bios_month > mm) return (TRUE); if (bios_day < dd) return (FALSE); return (TRUE); }
ACPI_STATUS AcpiGetTableHeader ( char *Signature, UINT32 Instance, ACPI_TABLE_HEADER *OutTableHeader) { UINT32 i; UINT32 j; ACPI_TABLE_HEADER *Header; /* Parameter validation */ if (!Signature || !OutTableHeader) { return (AE_BAD_PARAMETER); } /* Walk the root table list */ for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) { if (!ACPI_COMPARE_NAME ( &(AcpiGbl_RootTableList.Tables[i].Signature), Signature)) { continue; } if (++j < Instance) { continue; } if (!AcpiGbl_RootTableList.Tables[i].Pointer) { if ((AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_ORIGIN_MASK) == ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL) { Header = AcpiOsMapMemory ( AcpiGbl_RootTableList.Tables[i].Address, sizeof (ACPI_TABLE_HEADER)); if (!Header) { return (AE_NO_MEMORY); } memcpy (OutTableHeader, Header, sizeof (ACPI_TABLE_HEADER)); AcpiOsUnmapMemory (Header, sizeof (ACPI_TABLE_HEADER)); } else { return (AE_NOT_FOUND); } } else { memcpy (OutTableHeader, AcpiGbl_RootTableList.Tables[i].Pointer, sizeof (ACPI_TABLE_HEADER)); } return (AE_OK); } return (AE_NOT_FOUND); }
ACPI_STATUS AcpiTbParseRootTable ( ACPI_PHYSICAL_ADDRESS RsdpAddress) { ACPI_TABLE_RSDP *Rsdp; UINT32 TableEntrySize; UINT32 i; UINT32 TableCount; ACPI_TABLE_HEADER *Table; ACPI_PHYSICAL_ADDRESS Address; UINT32 Length; UINT8 *TableEntry; ACPI_STATUS Status; UINT32 TableIndex; ACPI_FUNCTION_TRACE (TbParseRootTable); /* Map the entire RSDP and extract the address of the RSDT or XSDT */ Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP)); if (!Rsdp) { return_ACPI_STATUS (AE_NO_MEMORY); } AcpiTbPrintTableHeader (RsdpAddress, ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp)); /* Use XSDT if present and not overridden. Otherwise, use RSDT */ if ((Rsdp->Revision > 1) && Rsdp->XsdtPhysicalAddress && !AcpiGbl_DoNotUseXsdt) { /* * RSDP contains an XSDT (64-bit physical addresses). We must use * the XSDT if the revision is > 1 and the XSDT pointer is present, * as per the ACPI specification. */ Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress; TableEntrySize = ACPI_XSDT_ENTRY_SIZE; } else { /* Root table is an RSDT (32-bit physical addresses) */ Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress; TableEntrySize = ACPI_RSDT_ENTRY_SIZE; } /* * It is not possible to map more than one entry in some environments, * so unmap the RSDP here before mapping other tables */ AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP)); /* Map the RSDT/XSDT table header to get the full table length */ Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); if (!Table) { return_ACPI_STATUS (AE_NO_MEMORY); } AcpiTbPrintTableHeader (Address, Table); /* * Validate length of the table, and map entire table. * Minimum length table must contain at least one entry. */ Length = Table->Length; AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); if (Length < (sizeof (ACPI_TABLE_HEADER) + TableEntrySize)) { ACPI_BIOS_ERROR ((AE_INFO, "Invalid table length 0x%X in RSDT/XSDT", Length)); return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); } Table = AcpiOsMapMemory (Address, Length); if (!Table) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Validate the root table checksum */ Status = AcpiTbVerifyChecksum (Table, Length); if (ACPI_FAILURE (Status)) { AcpiOsUnmapMemory (Table, Length); return_ACPI_STATUS (Status); } /* Get the number of entries and pointer to first entry */ TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) / TableEntrySize); TableEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER)); /* Initialize the root table array from the RSDT/XSDT */ for (i = 0; i < TableCount; i++) { /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ Address = AcpiTbGetRootTableEntry (TableEntry, TableEntrySize); /* Skip NULL entries in RSDT/XSDT */ if (!Address) { goto NextTable; } Status = AcpiTbInstallStandardTable (Address, ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, FALSE, TRUE, &TableIndex); if (ACPI_SUCCESS (Status) && ACPI_COMPARE_NAME ( &AcpiGbl_RootTableList.Tables[TableIndex].Signature, ACPI_SIG_FADT)) { AcpiGbl_FadtIndex = TableIndex; AcpiTbParseFadt (); } NextTable: TableEntry += TableEntrySize; } AcpiOsUnmapMemory (Table, Length); return_ACPI_STATUS (AE_OK); }
static ACPI_STATUS AcpiTbValidateXsdt ( ACPI_PHYSICAL_ADDRESS XsdtAddress) { ACPI_TABLE_HEADER *Table; UINT8 *NextEntry; ACPI_PHYSICAL_ADDRESS Address; UINT32 Length; UINT32 EntryCount; ACPI_STATUS Status; UINT32 i; /* Get the XSDT length */ Table = AcpiOsMapMemory (XsdtAddress, sizeof (ACPI_TABLE_HEADER)); if (!Table) { return (AE_NO_MEMORY); } Length = Table->Length; AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); /* * Minimum XSDT length is the size of the standard ACPI header * plus one physical address entry */ if (Length < (sizeof (ACPI_TABLE_HEADER) + ACPI_XSDT_ENTRY_SIZE)) { return (AE_INVALID_TABLE_LENGTH); } /* Map the entire XSDT */ Table = AcpiOsMapMemory (XsdtAddress, Length); if (!Table) { return (AE_NO_MEMORY); } /* Get the number of entries and pointer to first entry */ Status = AE_OK; NextEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER)); EntryCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) / ACPI_XSDT_ENTRY_SIZE); /* Validate each entry (physical address) within the XSDT */ for (i = 0; i < EntryCount; i++) { Address = AcpiTbGetRootTableEntry (NextEntry, ACPI_XSDT_ENTRY_SIZE); if (!Address) { /* Detected a NULL entry, XSDT is invalid */ Status = AE_NULL_ENTRY; break; } NextEntry += ACPI_XSDT_ENTRY_SIZE; } /* Unmap table */ AcpiOsUnmapMemory (Table, Length); return (Status); }