3 * Module Name: osillumostbl - illumos OSL for obtaining ACPI tables
4 * This file is derived from the Intel oslinuxtbl source file.
9 * Copyright (C) 2000 - 2016, Intel Corp.
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
46 * Copyright 2016 Joyent, Inc.
53 #include <libdevinfo.h>
56 #define _COMPONENT ACPI_OS_SERVICES
57 ACPI_MODULE_NAME("osillumostbl")
59 /* List of information about obtained ACPI tables */
61 typedef struct osl_table_info
63 struct osl_table_info
*Next
;
65 char Signature
[ACPI_NAME_SIZE
];
68 /* Local prototypes */
70 OslTableInitialize(void);
71 static ACPI_STATUS
OslTableNameFromFile(char *, char *, UINT32
*);
72 static ACPI_STATUS
OslAddTableToList(char *);
73 static ACPI_STATUS
OslMapTable(ACPI_SIZE
, char *, ACPI_TABLE_HEADER
**);
74 static void OslUnmapTable(ACPI_TABLE_HEADER
*);
75 static ACPI_STATUS
OslLoadRsdp(void);
76 static ACPI_STATUS
OslListBiosTables(void);
77 static ACPI_STATUS
OslGetBiosTable(char *, UINT32
, ACPI_TABLE_HEADER
**,
78 ACPI_PHYSICAL_ADDRESS
*);
79 static ACPI_STATUS
OslGetLastStatus(ACPI_STATUS
);
83 /* Initialization flags */
84 UINT8 Gbl_TableListInitialized
= FALSE
;
86 /* Local copies of main ACPI tables */
87 ACPI_TABLE_RSDP Gbl_Rsdp
;
88 ACPI_TABLE_FADT
*Gbl_Fadt
= NULL
;
89 ACPI_TABLE_RSDT
*Gbl_Rsdt
= NULL
;
90 ACPI_TABLE_XSDT
*Gbl_Xsdt
= NULL
;
93 ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress
= 0;
94 ACPI_PHYSICAL_ADDRESS Gbl_RsdpAddress
= 0;
96 /* Revision of RSD PTR */
97 UINT8 Gbl_Revision
= 0;
99 OSL_TABLE_INFO
*Gbl_TableListHead
= NULL
;
100 UINT32 Gbl_TableCount
= 0;
104 * FUNCTION: OslGetLastStatus
106 * PARAMETERS: DefaultStatus - Default error status to return
108 * RETURN: Status; Converted from errno.
110 * DESCRIPTION: Get last errno and conver it to ACPI_STATUS.
114 OslGetLastStatus(ACPI_STATUS DefaultStatus
)
122 return (AE_NOT_FOUND
);
125 return (AE_NO_MEMORY
);
128 return (DefaultStatus
);
134 * FUNCTION: AcpiOsGetTableByAddress
136 * PARAMETERS: Address - Physical address of the ACPI table
137 * Table - Where a pointer to the table is returned
139 * RETURN: Status; Table buffer is returned if AE_OK.
140 * AE_NOT_FOUND: A valid table was not found at the address
142 * DESCRIPTION: Get an ACPI table via a physical memory address.
146 AcpiOsGetTableByAddress(ACPI_PHYSICAL_ADDRESS Address
,
147 ACPI_TABLE_HEADER
**Table
)
150 ACPI_TABLE_HEADER
*MappedTable
;
151 ACPI_TABLE_HEADER
*LocalTable
= NULL
;
152 ACPI_STATUS Status
= AE_OK
;
155 * Get main ACPI tables from memory on first invocation of this
158 Status
= OslTableInitialize();
159 if (ACPI_FAILURE(Status
)) {
163 /* Map the table and validate it */
165 Status
= OslMapTable(Address
, NULL
, &MappedTable
);
166 if (ACPI_FAILURE(Status
)) {
170 /* Copy table to local buffer and return it */
172 TableLength
= ApGetTableLength(MappedTable
);
173 if (TableLength
== 0) {
174 Status
= AE_BAD_HEADER
;
178 LocalTable
= calloc(1, TableLength
);
180 Status
= AE_NO_MEMORY
;
184 memcpy(LocalTable
, MappedTable
, TableLength
);
187 OslUnmapTable(MappedTable
);
194 * FUNCTION: AcpiOsGetTableByName
196 * PARAMETERS: Signature - ACPI Signature for desired table. Must be
197 * a null terminated 4-character string.
198 * Instance - Multiple table support for SSDT/UEFI (0...n)
199 * Must be 0 for other tables.
200 * Table - Where a pointer to the table is returned
201 * Address - Where the table physical address is returned
203 * RETURN: Status; Table buffer and physical address returned if AE_OK.
204 * AE_LIMIT: Instance is beyond valid limit
205 * AE_NOT_FOUND: A table with the signature was not found
207 * NOTE: Assumes the input signature is uppercase.
211 AcpiOsGetTableByName(char *Signature
, UINT32 Instance
,
212 ACPI_TABLE_HEADER
**Table
, ACPI_PHYSICAL_ADDRESS
*Address
)
217 * Get main ACPI tables from memory on first invocation of this
220 Status
= OslTableInitialize();
221 if (ACPI_FAILURE(Status
)) {
225 /* attempt to extract it from the RSDT/XSDT */
226 Status
= OslGetBiosTable(Signature
, Instance
, Table
, Address
);
233 * FUNCTION: OslAddTableToList
235 * PARAMETERS: Signature - Table signature
237 * RETURN: Status; Successfully added if AE_OK.
238 * AE_NO_MEMORY: Memory allocation error
240 * DESCRIPTION: Insert a table structure into OSL table list.
244 OslAddTableToList(char *Signature
)
246 OSL_TABLE_INFO
*NewInfo
;
247 OSL_TABLE_INFO
*Next
;
248 UINT32 NextInstance
= 0;
250 BOOLEAN Found
= FALSE
;
252 NewInfo
= calloc(1, sizeof (OSL_TABLE_INFO
));
253 if (NewInfo
== NULL
) {
254 return (AE_NO_MEMORY
);
257 ACPI_MOVE_NAME(NewInfo
->Signature
, Signature
);
259 if (!Gbl_TableListHead
) {
260 Gbl_TableListHead
= NewInfo
;
262 Next
= Gbl_TableListHead
;
265 if (ACPI_COMPARE_NAME(Next
->Signature
, Signature
)) {
266 if (Next
->Instance
== 0) {
269 if (Next
->Instance
>= NextInstance
) {
270 NextInstance
= Next
->Instance
+ 1;
279 Next
->Next
= NewInfo
;
283 Instance
= NextInstance
;
286 NewInfo
->Instance
= Instance
;
294 * FUNCTION: AcpiOsGetTableByIndex
296 * PARAMETERS: Index - Which table to get
297 * Table - Where a pointer to the table is returned
298 * Instance - Where a pointer to the table instance no. is
300 * Address - Where the table physical address is returned
302 * RETURN: Status; Table buffer and physical address returned if AE_OK.
303 * AE_LIMIT: Index is beyond valid limit
305 * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
306 * AE_LIMIT when an invalid index is reached. Index is not
307 * necessarily an index into the RSDT/XSDT.
311 AcpiOsGetTableByIndex(UINT32 Index
, ACPI_TABLE_HEADER
**Table
,
312 UINT32
*Instance
, ACPI_PHYSICAL_ADDRESS
*Address
)
314 OSL_TABLE_INFO
*Info
;
319 * Get main ACPI tables from memory on first invocation of this
323 Status
= OslTableInitialize();
324 if (ACPI_FAILURE(Status
)) {
330 if (Index
>= Gbl_TableCount
) {
334 /* Point to the table list entry specified by the Index argument */
336 Info
= Gbl_TableListHead
;
337 for (i
= 0; i
< Index
; i
++) {
341 /* Now we can just get the table via the signature */
343 Status
= AcpiOsGetTableByName(Info
->Signature
, Info
->Instance
,
346 if (ACPI_SUCCESS(Status
)) {
347 *Instance
= Info
->Instance
;
354 * FUNCTION: OslLoadRsdp
360 * DESCRIPTION: Scan and load RSDP.
361 * See the find_rsdp() function in usr/src/uts/i86pc/os/fakebop.c, which is how
362 * the kernel finds the RSDP. That algorithm matches AcpiFindRootPointer().
364 * If the system is not using BIOS, and ACPI information was passed to the
365 * system from the boot loader, then the RSDP is recorded in the "acpi-root-tab"
368 * The code here is derived from AcpiFindRootPointer, except that we will
369 * try the "acpi-root-tab" property first. If the property does not exist or
370 * we do not find the root, then we scan the EBDA. Finally, we will search
371 * the BIOS and copy the table if found.
377 ACPI_TABLE_HEADER
*tblp
;
378 ACPI_SIZE mapsize
= sizeof (ACPI_TABLE_RSDP
);
379 ACPI_PHYSICAL_ADDRESS physaddr
;
383 if ((root
= di_init("/", DINFOPROP
)) != DI_NODE_NIL
) {
384 if (di_prop_lookup_int64(DDI_DEV_T_ANY
, root
,
385 "acpi-root-tab", &val64
) == 1) {
386 physaddr
= (ACPI_PHYSICAL_ADDRESS
)*val64
;
387 mapp
= AcpiOsMapMemory(physaddr
, mapsize
);
393 tblp
= ACPI_CAST_PTR(ACPI_TABLE_HEADER
,
394 AcpiTbScanMemoryForRsdp(mapp
, mapsize
));
396 physaddr
+= (ACPI_PHYSICAL_ADDRESS
)
397 ACPI_PTR_DIFF(tblp
, mapp
);
398 Gbl_RsdpAddress
= physaddr
;
399 memcpy(&Gbl_Rsdp
, tblp
, sizeof (ACPI_TABLE_RSDP
));
400 AcpiOsUnmapMemory(mapp
, mapsize
);
403 AcpiOsUnmapMemory(mapp
, mapsize
);
406 /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
407 mapp
= AcpiOsMapMemory((ACPI_PHYSICAL_ADDRESS
)ACPI_EBDA_PTR_LOCATION
,
408 ACPI_EBDA_PTR_LENGTH
);
412 ACPI_MOVE_16_TO_32(&physaddr
, mapp
);
414 /* Convert segment part to physical address */
416 AcpiOsUnmapMemory(mapp
, ACPI_EBDA_PTR_LENGTH
);
419 if (physaddr
<= 0x400)
423 * 1b) Search EBDA paragraphs (EBDA is required to be a minimum of 1K
426 mapp
= AcpiOsMapMemory(physaddr
, ACPI_EBDA_WINDOW_SIZE
);
428 (void) fprintf(stderr
, "EBDA (0x%p) found, but is not "
429 "mappable\n", physaddr
);
433 tblp
= ACPI_CAST_PTR(ACPI_TABLE_HEADER
,
434 AcpiTbScanMemoryForRsdp(mapp
, ACPI_EBDA_WINDOW_SIZE
));
436 physaddr
+= (ACPI_PHYSICAL_ADDRESS
) ACPI_PTR_DIFF(tblp
, mapp
);
437 Gbl_RsdpAddress
= physaddr
;
438 memcpy(&Gbl_Rsdp
, tblp
, sizeof (ACPI_TABLE_RSDP
));
439 AcpiOsUnmapMemory(mapp
, ACPI_EBDA_WINDOW_SIZE
);
443 AcpiOsUnmapMemory(mapp
, ACPI_EBDA_WINDOW_SIZE
);
446 /* Try to get RSDP from BIOS memory */
447 if (Gbl_RsdpBase
!= NULL
) {
448 physaddr
= Gbl_RsdpBase
;
449 mapsize
= sizeof (ACPI_TABLE_RSDP
);
451 physaddr
= ACPI_HI_RSDP_WINDOW_BASE
;
452 mapsize
= ACPI_HI_RSDP_WINDOW_SIZE
;
455 mapp
= AcpiOsMapMemory(physaddr
, mapsize
);
457 return (OslGetLastStatus(AE_BAD_ADDRESS
));
459 /* Search low memory for the RSDP */
460 tblp
= ACPI_CAST_PTR(ACPI_TABLE_HEADER
,
461 AcpiTbScanMemoryForRsdp(mapp
, mapsize
));
463 AcpiOsUnmapMemory(mapp
, mapsize
);
464 return (AE_NOT_FOUND
);
467 physaddr
+= (ACPI_PHYSICAL_ADDRESS
) ACPI_PTR_DIFF(tblp
, mapp
);
468 Gbl_RsdpAddress
= physaddr
;
469 memcpy(&Gbl_Rsdp
, tblp
, sizeof (ACPI_TABLE_RSDP
));
470 AcpiOsUnmapMemory(mapp
, mapsize
);
477 * FUNCTION: OslCanUseXsdt
481 * RETURN: TRUE if XSDT is allowed to be used.
483 * DESCRIPTION: This function collects logic that can be used to determine if
484 * XSDT should be used instead of RSDT.
490 if (Gbl_Revision
&& !AcpiGbl_DoNotUseXsdt
) {
499 * FUNCTION: OslTableInitialize
505 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
506 * local variables. Main ACPI tables include RSDT, FADT, RSDT,
511 OslTableInitialize(void)
514 ACPI_PHYSICAL_ADDRESS Address
;
516 if (Gbl_TableListInitialized
) {
520 /* Get RSDP from memory */
522 Status
= OslLoadRsdp();
523 if (ACPI_FAILURE(Status
)) {
527 /* Get XSDT from memory */
529 if (Gbl_Rsdp
.Revision
&& !Gbl_DoNotDumpXsdt
) {
536 Status
= OslGetBiosTable(ACPI_SIG_XSDT
, 0,
537 ACPI_CAST_PTR(ACPI_TABLE_HEADER
*, &Gbl_Xsdt
), &Address
);
538 if (ACPI_FAILURE(Status
)) {
543 /* Get RSDT from memory */
545 if (Gbl_Rsdp
.RsdtPhysicalAddress
) {
551 Status
= OslGetBiosTable(ACPI_SIG_RSDT
, 0,
552 ACPI_CAST_PTR(ACPI_TABLE_HEADER
*, &Gbl_Rsdt
), &Address
);
553 if (ACPI_FAILURE(Status
)) {
558 /* Get FADT from memory */
565 Status
= OslGetBiosTable(ACPI_SIG_FADT
, 0,
566 ACPI_CAST_PTR(ACPI_TABLE_HEADER
*, &Gbl_Fadt
), &Gbl_FadtAddress
);
567 if (ACPI_FAILURE(Status
)) {
571 /* Add mandatory tables to global table list first */
573 Status
= OslAddTableToList(ACPI_RSDP_NAME
);
574 if (ACPI_FAILURE(Status
)) {
578 Status
= OslAddTableToList(ACPI_SIG_RSDT
);
579 if (ACPI_FAILURE(Status
)) {
583 if (Gbl_Revision
== 2) {
584 Status
= OslAddTableToList(ACPI_SIG_XSDT
);
585 if (ACPI_FAILURE(Status
)) {
590 Status
= OslAddTableToList(ACPI_SIG_DSDT
);
591 if (ACPI_FAILURE(Status
)) {
595 Status
= OslAddTableToList(ACPI_SIG_FACS
);
596 if (ACPI_FAILURE(Status
)) {
600 /* Add all tables found in the memory */
602 Status
= OslListBiosTables();
603 if (ACPI_FAILURE(Status
)) {
607 Gbl_TableListInitialized
= TRUE
;
614 * FUNCTION: OslListBiosTables
618 * RETURN: Status; Table list is initialized if AE_OK.
620 * DESCRIPTION: Add ACPI tables to the table list from memory.
623 OslListBiosTables(void)
625 ACPI_TABLE_HEADER
*MappedTable
= NULL
;
627 UINT32 NumberOfTables
;
629 ACPI_PHYSICAL_ADDRESS TableAddress
= 0;
630 ACPI_STATUS Status
= AE_OK
;
633 if (OslCanUseXsdt()) {
634 ItemSize
= sizeof (UINT64
);
635 TableData
= ACPI_CAST8(Gbl_Xsdt
) + sizeof (ACPI_TABLE_HEADER
);
636 NumberOfTables
= (UINT32
)
637 ((Gbl_Xsdt
->Header
.Length
- sizeof (ACPI_TABLE_HEADER
))
641 /* Use RSDT if XSDT is not available */
642 ItemSize
= sizeof (UINT32
);
643 TableData
= ACPI_CAST8(Gbl_Rsdt
) + sizeof (ACPI_TABLE_HEADER
);
644 NumberOfTables
= (UINT32
)
645 ((Gbl_Rsdt
->Header
.Length
- sizeof (ACPI_TABLE_HEADER
))
649 /* Search RSDT/XSDT for the requested table */
651 for (i
= 0; i
< NumberOfTables
; ++i
, TableData
+= ItemSize
) {
652 if (OslCanUseXsdt()) {
654 (ACPI_PHYSICAL_ADDRESS
) (*ACPI_CAST64(TableData
));
657 (ACPI_PHYSICAL_ADDRESS
) (*ACPI_CAST32(TableData
));
660 /* Skip NULL entries in RSDT/XSDT */
661 if (TableAddress
== NULL
) {
665 Status
= OslMapTable(TableAddress
, NULL
, &MappedTable
);
666 if (ACPI_FAILURE(Status
)) {
670 OslAddTableToList(MappedTable
->Signature
);
671 OslUnmapTable(MappedTable
);
679 * FUNCTION: OslGetBiosTable
681 * PARAMETERS: Signature - ACPI Signature for common table. Must be
682 * a null terminated 4-character string.
683 * Instance - Multiple table support for SSDT/UEFI (0...n)
684 * Must be 0 for other tables.
685 * Table - Where a pointer to the table is returned
686 * Address - Where the table physical address is returned
688 * RETURN: Status; Table buffer and physical address returned if AE_OK.
689 * AE_LIMIT: Instance is beyond valid limit
690 * AE_NOT_FOUND: A table with the signature was not found
692 * DESCRIPTION: Get a BIOS provided ACPI table
694 * NOTE: Assumes the input signature is uppercase.
698 OslGetBiosTable(char *Signature
, UINT32 Instance
, ACPI_TABLE_HEADER
**Table
,
699 ACPI_PHYSICAL_ADDRESS
*Address
)
701 ACPI_TABLE_HEADER
*LocalTable
= NULL
;
702 ACPI_TABLE_HEADER
*MappedTable
= NULL
;
704 UINT8 NumberOfTables
;
706 UINT32 CurrentInstance
= 0;
707 ACPI_PHYSICAL_ADDRESS TableAddress
= 0;
708 UINT32 TableLength
= 0;
709 ACPI_STATUS Status
= AE_OK
;
712 /* Handle special tables whose addresses are not in RSDT/XSDT */
714 if (ACPI_COMPARE_NAME(Signature
, ACPI_RSDP_NAME
) ||
715 ACPI_COMPARE_NAME(Signature
, ACPI_SIG_RSDT
) ||
716 ACPI_COMPARE_NAME(Signature
, ACPI_SIG_XSDT
) ||
717 ACPI_COMPARE_NAME(Signature
, ACPI_SIG_DSDT
) ||
718 ACPI_COMPARE_NAME(Signature
, ACPI_SIG_FACS
)) {
724 * Get the appropriate address, either 32-bit or 64-bit. Be very
725 * careful about the FADT length and validate table addresses.
726 * Note: The 64-bit addresses have priority.
728 if (ACPI_COMPARE_NAME(Signature
, ACPI_SIG_DSDT
)) {
729 if ((Gbl_Fadt
->Header
.Length
>= MIN_FADT_FOR_XDSDT
) &&
732 (ACPI_PHYSICAL_ADDRESS
) Gbl_Fadt
->XDsdt
;
734 } else if (Gbl_Fadt
->Header
.Length
>=
735 MIN_FADT_FOR_DSDT
&& Gbl_Fadt
->Dsdt
) {
737 (ACPI_PHYSICAL_ADDRESS
) Gbl_Fadt
->Dsdt
;
740 } else if (ACPI_COMPARE_NAME(Signature
, ACPI_SIG_FACS
)) {
741 if ((Gbl_Fadt
->Header
.Length
>= MIN_FADT_FOR_XFACS
) &&
744 (ACPI_PHYSICAL_ADDRESS
) Gbl_Fadt
->XFacs
;
746 } else if (Gbl_Fadt
->Header
.Length
>=
747 MIN_FADT_FOR_FACS
&& Gbl_Fadt
->Facs
) {
749 (ACPI_PHYSICAL_ADDRESS
) Gbl_Fadt
->Facs
;
752 } else if (ACPI_COMPARE_NAME(Signature
, ACPI_SIG_XSDT
)) {
754 return (AE_BAD_SIGNATURE
);
756 TableAddress
= (ACPI_PHYSICAL_ADDRESS
)
757 Gbl_Rsdp
.XsdtPhysicalAddress
;
759 } else if (ACPI_COMPARE_NAME(Signature
, ACPI_SIG_RSDT
)) {
760 TableAddress
= (ACPI_PHYSICAL_ADDRESS
)
761 Gbl_Rsdp
.RsdtPhysicalAddress
;
764 TableAddress
= (ACPI_PHYSICAL_ADDRESS
) Gbl_RsdpAddress
;
765 Signature
= ACPI_SIG_RSDP
;
768 /* Now we can get the requested special table */
770 Status
= OslMapTable(TableAddress
, Signature
, &MappedTable
);
771 if (ACPI_FAILURE(Status
)) {
775 TableLength
= ApGetTableLength(MappedTable
);
778 /* Case for a normal ACPI table */
779 if (OslCanUseXsdt()) {
780 ItemSize
= sizeof (UINT64
);
781 TableData
= ACPI_CAST8(Gbl_Xsdt
) +
782 sizeof (ACPI_TABLE_HEADER
);
783 NumberOfTables
= (UINT8
) ((Gbl_Xsdt
->Header
.Length
-
784 sizeof (ACPI_TABLE_HEADER
))
788 /* Use RSDT if XSDT is not available */
789 ItemSize
= sizeof (UINT32
);
790 TableData
= ACPI_CAST8(Gbl_Rsdt
) +
791 sizeof (ACPI_TABLE_HEADER
);
792 NumberOfTables
= (UINT8
) ((Gbl_Rsdt
->Header
.Length
-
793 sizeof (ACPI_TABLE_HEADER
))
797 /* Search RSDT/XSDT for the requested table */
799 for (i
= 0; i
< NumberOfTables
; ++i
, TableData
+= ItemSize
) {
800 if (OslCanUseXsdt()) {
801 TableAddress
= (ACPI_PHYSICAL_ADDRESS
)
802 (*ACPI_CAST64(TableData
));
804 TableAddress
= (ACPI_PHYSICAL_ADDRESS
)
805 (*ACPI_CAST32(TableData
));
808 /* Skip NULL entries in RSDT/XSDT */
810 if (TableAddress
== NULL
) {
814 Status
= OslMapTable(TableAddress
, NULL
, &MappedTable
);
815 if (ACPI_FAILURE(Status
)) {
818 TableLength
= MappedTable
->Length
;
820 /* Does this table match the requested signature? */
822 if (!ACPI_COMPARE_NAME(MappedTable
->Signature
,
824 OslUnmapTable(MappedTable
);
829 /* Match table instance (for SSDT/UEFI tables) */
831 if (CurrentInstance
!= Instance
) {
832 OslUnmapTable(MappedTable
);
842 if (MappedTable
== NULL
) {
846 if (TableLength
== 0) {
847 Status
= AE_BAD_HEADER
;
851 /* Copy table to local buffer and return it */
853 LocalTable
= calloc(1, TableLength
);
854 if (LocalTable
== NULL
) {
855 Status
= AE_NO_MEMORY
;
859 memcpy(LocalTable
, MappedTable
, TableLength
);
860 *Address
= TableAddress
;
864 OslUnmapTable(MappedTable
);
870 * FUNCTION: OslMapTable
872 * PARAMETERS: Address - Address of the table in memory
873 * Signature - Optional ACPI Signature for desired table.
874 * Null terminated 4-character string.
875 * Table - Where a pointer to the mapped table is
878 * RETURN: Status; Mapped table is returned if AE_OK.
879 * AE_NOT_FOUND: A valid table was not found at the address
881 * DESCRIPTION: Map entire ACPI table into caller's address space.
885 OslMapTable(ACPI_SIZE Address
, char *Signature
, ACPI_TABLE_HEADER
**Table
)
887 ACPI_TABLE_HEADER
*MappedTable
;
890 if (Address
== NULL
) {
891 return (AE_BAD_ADDRESS
);
895 * Map the header so we can get the table length.
896 * Use sizeof (ACPI_TABLE_HEADER) as:
897 * 1. it is bigger than 24 to include RSDP->Length
898 * 2. it is smaller than sizeof (ACPI_TABLE_RSDP)
900 MappedTable
= AcpiOsMapMemory(Address
, sizeof (ACPI_TABLE_HEADER
));
901 if (MappedTable
== NULL
) {
902 (void) fprintf(stderr
, "Could not map table header at "
903 "0x%8.8X%8.8X\n", ACPI_FORMAT_UINT64(Address
));
904 return (OslGetLastStatus(AE_BAD_ADDRESS
));
907 /* If specified, signature must match */
909 if (Signature
!= NULL
) {
910 if (ACPI_VALIDATE_RSDP_SIG(Signature
)) {
911 if (!ACPI_VALIDATE_RSDP_SIG(MappedTable
->Signature
)) {
912 AcpiOsUnmapMemory(MappedTable
,
913 sizeof (ACPI_TABLE_HEADER
));
914 return (AE_BAD_SIGNATURE
);
916 } else if (!ACPI_COMPARE_NAME(Signature
,
917 MappedTable
->Signature
)) {
918 AcpiOsUnmapMemory(MappedTable
,
919 sizeof (ACPI_TABLE_HEADER
));
920 return (AE_BAD_SIGNATURE
);
924 /* Map the entire table */
926 Length
= ApGetTableLength(MappedTable
);
927 AcpiOsUnmapMemory(MappedTable
, sizeof (ACPI_TABLE_HEADER
));
929 return (AE_BAD_HEADER
);
932 MappedTable
= AcpiOsMapMemory(Address
, Length
);
933 if (MappedTable
== NULL
) {
934 (void) fprintf(stderr
, "Could not map table at 0x%8.8X%8.8X "
935 "length %8.8X\n", ACPI_FORMAT_UINT64(Address
), Length
);
936 return (OslGetLastStatus(AE_INVALID_TABLE_LENGTH
));
939 (void) ApIsValidChecksum(MappedTable
);
941 *Table
= MappedTable
;
948 * FUNCTION: OslUnmapTable
950 * PARAMETERS: Table - A pointer to the mapped table
954 * DESCRIPTION: Unmap entire ACPI table.
958 OslUnmapTable(ACPI_TABLE_HEADER
*Table
)
961 AcpiOsUnmapMemory(Table
, ApGetTableLength(Table
));
967 * FUNCTION: OslTableNameFromFile
969 * PARAMETERS: Filename - File that contains the desired table
970 * Signature - Pointer to 4-character buffer to store
971 * extracted table signature.
972 * Instance - Pointer to integer to store extracted
973 * table instance number.
975 * RETURN: Status; Table name is extracted if AE_OK.
977 * DESCRIPTION: Extract table signature and instance number from a table file
982 OslTableNameFromFile(char *Filename
, char *Signature
, UINT32
*Instance
)
984 /* Ignore meaningless files */
986 if (strlen(Filename
) < ACPI_NAME_SIZE
) {
987 return (AE_BAD_SIGNATURE
);
990 /* Extract instance number */
992 if (isdigit((int)Filename
[ACPI_NAME_SIZE
])) {
993 sscanf(&Filename
[ACPI_NAME_SIZE
], "%u", Instance
);
994 } else if (strlen(Filename
) != ACPI_NAME_SIZE
) {
995 return (AE_BAD_SIGNATURE
);
1000 /* Extract signature */
1002 ACPI_MOVE_NAME(Signature
, Filename
);
1007 CmGetFileSize(ACPI_FILE File
)
1013 if (fstat(fd
, &sb
) != 0)
1014 return (ACPI_UINT32_MAX
);
1015 return ((UINT32
)sb
.st_size
);
1019 AcpiOsAllocateZeroed(ACPI_SIZE Size
)
1021 return (calloc(1, Size
));
1031 AcpiOsOpenFile(const char *Path
, UINT8 Modes
)
1035 bzero(mode
, sizeof (mode
));
1036 if ((Modes
& ACPI_FILE_READING
) != 0)
1037 (void) strlcat(mode
, "r", sizeof (mode
));
1039 if ((Modes
& ACPI_FILE_WRITING
) != 0)
1040 (void) strlcat(mode
, "w", sizeof (mode
));
1042 return (fopen(Path
, mode
));
1046 AcpiOsCloseFile(ACPI_FILE File
)
1052 AcpiOsReadFile(ACPI_FILE File
, void *Buffer
, ACPI_SIZE Size
, ACPI_SIZE Count
)
1054 return (fread(Buffer
, Size
, Count
, File
));
1058 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS Where
, ACPI_SIZE Length
)
1064 if ((fd
= open("/dev/xsvc", O_RDONLY
)) < 0)
1067 if (pagesize
== 0) {
1068 pagesize
= getpagesize();
1071 offset
= Where
% pagesize
;
1072 p
= mmap(NULL
, Length
+ offset
, PROT_READ
, MAP_SHARED
| MAP_NORESERVE
,
1073 fd
, Where
- offset
);
1077 if (p
== MAP_FAILED
)
1079 p
= (char *)p
+ offset
;
1084 AcpiOsUnmapMemory(void *LogicalAddress
, ACPI_SIZE Size
)
1089 offset
= (ulong_t
)LogicalAddress
% pagesize
;
1090 p
= (void *)((char *)LogicalAddress
- offset
);
1092 (void) munmap(p
, Size
+ offset
);