1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
4 * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables
6 * Copyright (C) 2000 - 2020, Intel Corp.
8 *****************************************************************************/
12 #define _COMPONENT ACPI_OS_SERVICES
13 ACPI_MODULE_NAME("oslinuxtbl")
18 /* List of information about obtained ACPI tables */
19 typedef struct osl_table_info
{
20 struct osl_table_info
*next
;
22 char signature
[ACPI_NAMESEG_SIZE
];
26 /* Local prototypes */
28 static acpi_status
osl_table_initialize(void);
31 osl_table_name_from_file(char *filename
, char *signature
, u32
*instance
);
33 static acpi_status
osl_add_table_to_list(char *signature
, u32 instance
);
36 osl_read_table_from_file(char *filename
,
37 acpi_size file_offset
,
38 char *signature
, struct acpi_table_header
**table
);
41 osl_map_table(acpi_size address
,
42 char *signature
, struct acpi_table_header
**table
);
44 static void osl_unmap_table(struct acpi_table_header
*table
);
46 static acpi_physical_address
47 osl_find_rsdp_via_efi_by_keyword(FILE * file
, const char *keyword
);
49 static acpi_physical_address
osl_find_rsdp_via_efi(void);
51 static acpi_status
osl_load_rsdp(void);
53 static acpi_status
osl_list_customized_tables(char *directory
);
56 osl_get_customized_table(char *pathname
,
59 struct acpi_table_header
**table
,
60 acpi_physical_address
*address
);
62 static acpi_status
osl_list_bios_tables(void);
65 osl_get_bios_table(char *signature
,
67 struct acpi_table_header
**table
,
68 acpi_physical_address
*address
);
70 static acpi_status
osl_get_last_status(acpi_status default_status
);
74 #define DYNAMIC_TABLE_DIR "/sys/firmware/acpi/tables/dynamic"
75 #define STATIC_TABLE_DIR "/sys/firmware/acpi/tables"
76 #define EFI_SYSTAB "/sys/firmware/efi/systab"
78 /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */
80 u8 gbl_dump_dynamic_tables
= TRUE
;
82 /* Initialization flags */
84 u8 gbl_table_list_initialized
= FALSE
;
86 /* Local copies of main ACPI tables */
88 struct acpi_table_rsdp gbl_rsdp
;
89 struct acpi_table_fadt
*gbl_fadt
= NULL
;
90 struct acpi_table_rsdt
*gbl_rsdt
= NULL
;
91 struct acpi_table_xsdt
*gbl_xsdt
= NULL
;
95 acpi_physical_address gbl_fadt_address
= 0;
96 acpi_physical_address gbl_rsdp_address
= 0;
98 /* Revision of RSD PTR */
102 struct osl_table_info
*gbl_table_list_head
= NULL
;
103 u32 gbl_table_count
= 0;
105 /******************************************************************************
107 * FUNCTION: osl_get_last_status
109 * PARAMETERS: default_status - Default error status to return
111 * RETURN: Status; Converted from errno.
113 * DESCRIPTION: Get last errno and conver it to acpi_status.
115 *****************************************************************************/
117 static acpi_status
osl_get_last_status(acpi_status default_status
)
128 return (AE_NOT_FOUND
);
132 return (AE_NO_MEMORY
);
136 return (default_status
);
140 /******************************************************************************
142 * FUNCTION: acpi_os_get_table_by_address
144 * PARAMETERS: address - Physical address of the ACPI table
145 * table - Where a pointer to the table is returned
147 * RETURN: Status; Table buffer is returned if AE_OK.
148 * AE_NOT_FOUND: A valid table was not found at the address
150 * DESCRIPTION: Get an ACPI table via a physical memory address.
152 *****************************************************************************/
155 acpi_os_get_table_by_address(acpi_physical_address address
,
156 struct acpi_table_header
**table
)
159 struct acpi_table_header
*mapped_table
;
160 struct acpi_table_header
*local_table
= NULL
;
161 acpi_status status
= AE_OK
;
163 /* Get main ACPI tables from memory on first invocation of this function */
165 status
= osl_table_initialize();
166 if (ACPI_FAILURE(status
)) {
170 /* Map the table and validate it */
172 status
= osl_map_table(address
, NULL
, &mapped_table
);
173 if (ACPI_FAILURE(status
)) {
177 /* Copy table to local buffer and return it */
179 table_length
= ap_get_table_length(mapped_table
);
180 if (table_length
== 0) {
181 status
= AE_BAD_HEADER
;
185 local_table
= calloc(1, table_length
);
187 status
= AE_NO_MEMORY
;
191 memcpy(local_table
, mapped_table
, table_length
);
194 osl_unmap_table(mapped_table
);
195 *table
= local_table
;
199 /******************************************************************************
201 * FUNCTION: acpi_os_get_table_by_name
203 * PARAMETERS: signature - ACPI Signature for desired table. Must be
204 * a null terminated 4-character string.
205 * instance - Multiple table support for SSDT/UEFI (0...n)
206 * Must be 0 for other tables.
207 * table - Where a pointer to the table is returned
208 * address - Where the table physical address is returned
210 * RETURN: Status; Table buffer and physical address returned if AE_OK.
211 * AE_LIMIT: Instance is beyond valid limit
212 * AE_NOT_FOUND: A table with the signature was not found
214 * NOTE: Assumes the input signature is uppercase.
216 *****************************************************************************/
219 acpi_os_get_table_by_name(char *signature
,
221 struct acpi_table_header
**table
,
222 acpi_physical_address
*address
)
226 /* Get main ACPI tables from memory on first invocation of this function */
228 status
= osl_table_initialize();
229 if (ACPI_FAILURE(status
)) {
233 /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
235 if (!gbl_dump_customized_tables
) {
237 /* Attempt to get the table from the memory */
240 osl_get_bios_table(signature
, instance
, table
, address
);
242 /* Attempt to get the table from the static directory */
244 status
= osl_get_customized_table(STATIC_TABLE_DIR
, signature
,
245 instance
, table
, address
);
248 if (ACPI_FAILURE(status
) && status
== AE_LIMIT
) {
249 if (gbl_dump_dynamic_tables
) {
251 /* Attempt to get a dynamic table */
254 osl_get_customized_table(DYNAMIC_TABLE_DIR
,
255 signature
, instance
, table
,
263 /******************************************************************************
265 * FUNCTION: osl_add_table_to_list
267 * PARAMETERS: signature - Table signature
268 * instance - Table instance
270 * RETURN: Status; Successfully added if AE_OK.
271 * AE_NO_MEMORY: Memory allocation error
273 * DESCRIPTION: Insert a table structure into OSL table list.
275 *****************************************************************************/
277 static acpi_status
osl_add_table_to_list(char *signature
, u32 instance
)
279 struct osl_table_info
*new_info
;
280 struct osl_table_info
*next
;
281 u32 next_instance
= 0;
284 new_info
= calloc(1, sizeof(struct osl_table_info
));
286 return (AE_NO_MEMORY
);
289 ACPI_COPY_NAMESEG(new_info
->signature
, signature
);
291 if (!gbl_table_list_head
) {
292 gbl_table_list_head
= new_info
;
294 next
= gbl_table_list_head
;
296 if (ACPI_COMPARE_NAMESEG(next
->signature
, signature
)) {
297 if (next
->instance
== instance
) {
300 if (next
->instance
>= next_instance
) {
301 next_instance
= next
->instance
+ 1;
310 next
->next
= new_info
;
316 "%4.4s: Warning unmatched table instance %d, expected %d\n",
317 signature
, instance
, next_instance
);
319 instance
= next_instance
;
322 new_info
->instance
= instance
;
328 /******************************************************************************
330 * FUNCTION: acpi_os_get_table_by_index
332 * PARAMETERS: index - Which table to get
333 * table - Where a pointer to the table is returned
334 * instance - Where a pointer to the table instance no. is
336 * address - Where the table physical address is returned
338 * RETURN: Status; Table buffer and physical address returned if AE_OK.
339 * AE_LIMIT: Index is beyond valid limit
341 * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
342 * AE_LIMIT when an invalid index is reached. Index is not
343 * necessarily an index into the RSDT/XSDT.
345 *****************************************************************************/
348 acpi_os_get_table_by_index(u32 index
,
349 struct acpi_table_header
**table
,
350 u32
*instance
, acpi_physical_address
*address
)
352 struct osl_table_info
*info
;
356 /* Get main ACPI tables from memory on first invocation of this function */
358 status
= osl_table_initialize();
359 if (ACPI_FAILURE(status
)) {
365 if (index
>= gbl_table_count
) {
369 /* Point to the table list entry specified by the Index argument */
371 info
= gbl_table_list_head
;
372 for (i
= 0; i
< index
; i
++) {
376 /* Now we can just get the table via the signature */
378 status
= acpi_os_get_table_by_name(info
->signature
, info
->instance
,
381 if (ACPI_SUCCESS(status
)) {
382 *instance
= info
->instance
;
387 /******************************************************************************
389 * FUNCTION: osl_find_rsdp_via_efi_by_keyword
391 * PARAMETERS: keyword - Character string indicating ACPI GUID version
394 * RETURN: RSDP address if found
396 * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI
399 *****************************************************************************/
401 static acpi_physical_address
402 osl_find_rsdp_via_efi_by_keyword(FILE * file
, const char *keyword
)
405 unsigned long long address
= 0;
408 snprintf(format
, 32, "%s=%s", keyword
, "%llx");
409 fseek(file
, 0, SEEK_SET
);
410 while (fgets(buffer
, 80, file
)) {
411 if (sscanf(buffer
, format
, &address
) == 1) {
416 return ((acpi_physical_address
)(address
));
419 /******************************************************************************
421 * FUNCTION: osl_find_rsdp_via_efi
425 * RETURN: RSDP address if found
427 * DESCRIPTION: Find RSDP address via EFI.
429 *****************************************************************************/
431 static acpi_physical_address
osl_find_rsdp_via_efi(void)
434 acpi_physical_address address
= 0;
436 file
= fopen(EFI_SYSTAB
, "r");
438 address
= osl_find_rsdp_via_efi_by_keyword(file
, "ACPI20");
441 osl_find_rsdp_via_efi_by_keyword(file
, "ACPI");
449 /******************************************************************************
451 * FUNCTION: osl_load_rsdp
457 * DESCRIPTION: Scan and load RSDP.
459 *****************************************************************************/
461 static acpi_status
osl_load_rsdp(void)
463 struct acpi_table_header
*mapped_table
;
465 acpi_physical_address rsdp_base
;
468 /* Get RSDP from memory */
470 rsdp_size
= sizeof(struct acpi_table_rsdp
);
472 rsdp_base
= gbl_rsdp_base
;
474 rsdp_base
= osl_find_rsdp_via_efi();
478 rsdp_base
= ACPI_HI_RSDP_WINDOW_BASE
;
479 rsdp_size
= ACPI_HI_RSDP_WINDOW_SIZE
;
482 rsdp_address
= acpi_os_map_memory(rsdp_base
, rsdp_size
);
484 return (osl_get_last_status(AE_BAD_ADDRESS
));
487 /* Search low memory for the RSDP */
489 mapped_table
= ACPI_CAST_PTR(struct acpi_table_header
,
490 acpi_tb_scan_memory_for_rsdp(rsdp_address
,
493 acpi_os_unmap_memory(rsdp_address
, rsdp_size
);
494 return (AE_NOT_FOUND
);
498 rsdp_base
+ (ACPI_CAST8(mapped_table
) - rsdp_address
);
500 memcpy(&gbl_rsdp
, mapped_table
, sizeof(struct acpi_table_rsdp
));
501 acpi_os_unmap_memory(rsdp_address
, rsdp_size
);
506 /******************************************************************************
508 * FUNCTION: osl_can_use_xsdt
512 * RETURN: TRUE if XSDT is allowed to be used.
514 * DESCRIPTION: This function collects logic that can be used to determine if
515 * XSDT should be used instead of RSDT.
517 *****************************************************************************/
519 static u8
osl_can_use_xsdt(void)
521 if (gbl_revision
&& !acpi_gbl_do_not_use_xsdt
) {
528 /******************************************************************************
530 * FUNCTION: osl_table_initialize
536 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
537 * local variables. Main ACPI tables include RSDT, FADT, RSDT,
540 *****************************************************************************/
542 static acpi_status
osl_table_initialize(void)
545 acpi_physical_address address
;
547 if (gbl_table_list_initialized
) {
551 if (!gbl_dump_customized_tables
) {
553 /* Get RSDP from memory */
555 status
= osl_load_rsdp();
556 if (ACPI_FAILURE(status
)) {
560 /* Get XSDT from memory */
562 if (gbl_rsdp
.revision
&& !gbl_do_not_dump_xsdt
) {
569 status
= osl_get_bios_table(ACPI_SIG_XSDT
, 0,
574 if (ACPI_FAILURE(status
)) {
579 /* Get RSDT from memory */
581 if (gbl_rsdp
.rsdt_physical_address
) {
587 status
= osl_get_bios_table(ACPI_SIG_RSDT
, 0,
592 if (ACPI_FAILURE(status
)) {
597 /* Get FADT from memory */
604 status
= osl_get_bios_table(ACPI_SIG_FADT
, 0,
609 if (ACPI_FAILURE(status
)) {
613 /* Add mandatory tables to global table list first */
615 status
= osl_add_table_to_list(ACPI_RSDP_NAME
, 0);
616 if (ACPI_FAILURE(status
)) {
620 status
= osl_add_table_to_list(ACPI_SIG_RSDT
, 0);
621 if (ACPI_FAILURE(status
)) {
625 if (gbl_revision
== 2) {
626 status
= osl_add_table_to_list(ACPI_SIG_XSDT
, 0);
627 if (ACPI_FAILURE(status
)) {
632 status
= osl_add_table_to_list(ACPI_SIG_DSDT
, 0);
633 if (ACPI_FAILURE(status
)) {
637 status
= osl_add_table_to_list(ACPI_SIG_FACS
, 0);
638 if (ACPI_FAILURE(status
)) {
642 /* Add all tables found in the memory */
644 status
= osl_list_bios_tables();
645 if (ACPI_FAILURE(status
)) {
649 /* Add all tables found in the static directory */
651 status
= osl_list_customized_tables(STATIC_TABLE_DIR
);
652 if (ACPI_FAILURE(status
)) {
657 if (gbl_dump_dynamic_tables
) {
659 /* Add all dynamically loaded tables in the dynamic directory */
661 status
= osl_list_customized_tables(DYNAMIC_TABLE_DIR
);
662 if (ACPI_FAILURE(status
)) {
667 gbl_table_list_initialized
= TRUE
;
671 /******************************************************************************
673 * FUNCTION: osl_list_bios_tables
677 * RETURN: Status; Table list is initialized if AE_OK.
679 * DESCRIPTION: Add ACPI tables to the table list from memory.
681 * NOTE: This works on Linux as table customization does not modify the
682 * addresses stored in RSDP/RSDT/XSDT/FADT.
684 *****************************************************************************/
686 static acpi_status
osl_list_bios_tables(void)
688 struct acpi_table_header
*mapped_table
= NULL
;
692 acpi_physical_address table_address
= 0;
693 acpi_status status
= AE_OK
;
696 if (osl_can_use_xsdt()) {
697 item_size
= sizeof(u64
);
699 ACPI_CAST8(gbl_xsdt
) + sizeof(struct acpi_table_header
);
701 (u8
)((gbl_xsdt
->header
.length
-
702 sizeof(struct acpi_table_header
))
704 } else { /* Use RSDT if XSDT is not available */
706 item_size
= sizeof(u32
);
708 ACPI_CAST8(gbl_rsdt
) + sizeof(struct acpi_table_header
);
710 (u8
)((gbl_rsdt
->header
.length
-
711 sizeof(struct acpi_table_header
))
715 /* Search RSDT/XSDT for the requested table */
717 for (i
= 0; i
< number_of_tables
; ++i
, table_data
+= item_size
) {
718 if (osl_can_use_xsdt()) {
720 (acpi_physical_address
)(*ACPI_CAST64(table_data
));
723 (acpi_physical_address
)(*ACPI_CAST32(table_data
));
726 /* Skip NULL entries in RSDT/XSDT */
728 if (table_address
== 0) {
732 status
= osl_map_table(table_address
, NULL
, &mapped_table
);
733 if (ACPI_FAILURE(status
)) {
737 osl_add_table_to_list(mapped_table
->signature
, 0);
738 osl_unmap_table(mapped_table
);
744 /******************************************************************************
746 * FUNCTION: osl_get_bios_table
748 * PARAMETERS: signature - ACPI Signature for common table. Must be
749 * a null terminated 4-character string.
750 * instance - Multiple table support for SSDT/UEFI (0...n)
751 * Must be 0 for other tables.
752 * table - Where a pointer to the table is returned
753 * address - Where the table physical address is returned
755 * RETURN: Status; Table buffer and physical address returned if AE_OK.
756 * AE_LIMIT: Instance is beyond valid limit
757 * AE_NOT_FOUND: A table with the signature was not found
759 * DESCRIPTION: Get a BIOS provided ACPI table
761 * NOTE: Assumes the input signature is uppercase.
763 *****************************************************************************/
766 osl_get_bios_table(char *signature
,
768 struct acpi_table_header
**table
,
769 acpi_physical_address
*address
)
771 struct acpi_table_header
*local_table
= NULL
;
772 struct acpi_table_header
*mapped_table
= NULL
;
776 u32 current_instance
= 0;
777 acpi_physical_address table_address
;
778 acpi_physical_address first_table_address
= 0;
779 u32 table_length
= 0;
780 acpi_status status
= AE_OK
;
783 /* Handle special tables whose addresses are not in RSDT/XSDT */
785 if (ACPI_COMPARE_NAMESEG(signature
, ACPI_RSDP_NAME
) ||
786 ACPI_COMPARE_NAMESEG(signature
, ACPI_SIG_RSDT
) ||
787 ACPI_COMPARE_NAMESEG(signature
, ACPI_SIG_XSDT
) ||
788 ACPI_COMPARE_NAMESEG(signature
, ACPI_SIG_DSDT
) ||
789 ACPI_COMPARE_NAMESEG(signature
, ACPI_SIG_FACS
)) {
796 * Get the appropriate address, either 32-bit or 64-bit. Be very
797 * careful about the FADT length and validate table addresses.
798 * Note: The 64-bit addresses have priority.
800 if (ACPI_COMPARE_NAMESEG(signature
, ACPI_SIG_DSDT
)) {
801 if (current_instance
< 2) {
802 if ((gbl_fadt
->header
.length
>=
803 MIN_FADT_FOR_XDSDT
) && gbl_fadt
->Xdsdt
804 && current_instance
== 0) {
806 (acpi_physical_address
)gbl_fadt
->
809 if ((gbl_fadt
->header
.length
>=
812 first_table_address
) {
814 (acpi_physical_address
)gbl_fadt
->
818 } else if (ACPI_COMPARE_NAMESEG(signature
, ACPI_SIG_FACS
)) {
819 if (current_instance
< 2) {
820 if ((gbl_fadt
->header
.length
>=
821 MIN_FADT_FOR_XFACS
) && gbl_fadt
->Xfacs
822 && current_instance
== 0) {
824 (acpi_physical_address
)gbl_fadt
->
827 if ((gbl_fadt
->header
.length
>=
830 first_table_address
) {
832 (acpi_physical_address
)gbl_fadt
->
836 } else if (ACPI_COMPARE_NAMESEG(signature
, ACPI_SIG_XSDT
)) {
838 return (AE_BAD_SIGNATURE
);
840 if (current_instance
== 0) {
842 (acpi_physical_address
)gbl_rsdp
.
843 xsdt_physical_address
;
845 } else if (ACPI_COMPARE_NAMESEG(signature
, ACPI_SIG_RSDT
)) {
846 if (current_instance
== 0) {
848 (acpi_physical_address
)gbl_rsdp
.
849 rsdt_physical_address
;
852 if (current_instance
== 0) {
854 (acpi_physical_address
)gbl_rsdp_address
;
855 signature
= ACPI_SIG_RSDP
;
859 if (table_address
== 0) {
860 goto exit_find_table
;
863 /* Now we can get the requested special table */
865 status
= osl_map_table(table_address
, signature
, &mapped_table
);
866 if (ACPI_FAILURE(status
)) {
870 table_length
= ap_get_table_length(mapped_table
);
871 if (first_table_address
== 0) {
872 first_table_address
= table_address
;
875 /* Match table instance */
877 if (current_instance
!= instance
) {
878 osl_unmap_table(mapped_table
);
881 goto find_next_instance
;
883 } else { /* Case for a normal ACPI table */
885 if (osl_can_use_xsdt()) {
886 item_size
= sizeof(u64
);
888 ACPI_CAST8(gbl_xsdt
) +
889 sizeof(struct acpi_table_header
);
891 (u8
)((gbl_xsdt
->header
.length
-
892 sizeof(struct acpi_table_header
))
894 } else { /* Use RSDT if XSDT is not available */
896 item_size
= sizeof(u32
);
898 ACPI_CAST8(gbl_rsdt
) +
899 sizeof(struct acpi_table_header
);
901 (u8
)((gbl_rsdt
->header
.length
-
902 sizeof(struct acpi_table_header
))
906 /* Search RSDT/XSDT for the requested table */
908 for (i
= 0; i
< number_of_tables
; ++i
, table_data
+= item_size
) {
909 if (osl_can_use_xsdt()) {
911 (acpi_physical_address
)(*ACPI_CAST64
915 (acpi_physical_address
)(*ACPI_CAST32
919 /* Skip NULL entries in RSDT/XSDT */
921 if (table_address
== 0) {
926 osl_map_table(table_address
, NULL
, &mapped_table
);
927 if (ACPI_FAILURE(status
)) {
930 table_length
= mapped_table
->length
;
932 /* Does this table match the requested signature? */
934 if (!ACPI_COMPARE_NAMESEG
935 (mapped_table
->signature
, signature
)) {
936 osl_unmap_table(mapped_table
);
941 /* Match table instance (for SSDT/UEFI tables) */
943 if (current_instance
!= instance
) {
944 osl_unmap_table(mapped_table
);
960 if (table_length
== 0) {
961 status
= AE_BAD_HEADER
;
965 /* Copy table to local buffer and return it */
967 local_table
= calloc(1, table_length
);
969 status
= AE_NO_MEMORY
;
973 memcpy(local_table
, mapped_table
, table_length
);
974 *address
= table_address
;
975 *table
= local_table
;
978 osl_unmap_table(mapped_table
);
982 /******************************************************************************
984 * FUNCTION: osl_list_customized_tables
986 * PARAMETERS: directory - Directory that contains the tables
988 * RETURN: Status; Table list is initialized if AE_OK.
990 * DESCRIPTION: Add ACPI tables to the table list from a directory.
992 *****************************************************************************/
994 static acpi_status
osl_list_customized_tables(char *directory
)
998 char temp_name
[ACPI_NAMESEG_SIZE
];
1000 acpi_status status
= AE_OK
;
1002 /* Open the requested directory */
1004 table_dir
= acpi_os_open_directory(directory
, "*", REQUEST_FILE_ONLY
);
1006 return (osl_get_last_status(AE_NOT_FOUND
));
1009 /* Examine all entries in this directory */
1011 while ((filename
= acpi_os_get_next_filename(table_dir
))) {
1013 /* Extract table name and instance number */
1016 osl_table_name_from_file(filename
, temp_name
, &instance
);
1018 /* Ignore meaningless files */
1020 if (ACPI_FAILURE(status
)) {
1024 /* Add new info node to global table list */
1026 status
= osl_add_table_to_list(temp_name
, instance
);
1027 if (ACPI_FAILURE(status
)) {
1032 acpi_os_close_directory(table_dir
);
1036 /******************************************************************************
1038 * FUNCTION: osl_map_table
1040 * PARAMETERS: address - Address of the table in memory
1041 * signature - Optional ACPI Signature for desired table.
1042 * Null terminated 4-character string.
1043 * table - Where a pointer to the mapped table is
1046 * RETURN: Status; Mapped table is returned if AE_OK.
1047 * AE_NOT_FOUND: A valid table was not found at the address
1049 * DESCRIPTION: Map entire ACPI table into caller's address space.
1051 *****************************************************************************/
1054 osl_map_table(acpi_size address
,
1055 char *signature
, struct acpi_table_header
**table
)
1057 struct acpi_table_header
*mapped_table
;
1061 return (AE_BAD_ADDRESS
);
1065 * Map the header so we can get the table length.
1066 * Use sizeof (struct acpi_table_header) as:
1067 * 1. it is bigger than 24 to include RSDP->Length
1068 * 2. it is smaller than sizeof (struct acpi_table_rsdp)
1071 acpi_os_map_memory(address
, sizeof(struct acpi_table_header
));
1072 if (!mapped_table
) {
1073 fprintf(stderr
, "Could not map table header at 0x%8.8X%8.8X\n",
1074 ACPI_FORMAT_UINT64(address
));
1075 return (osl_get_last_status(AE_BAD_ADDRESS
));
1078 /* If specified, signature must match */
1081 if (ACPI_VALIDATE_RSDP_SIG(signature
)) {
1082 if (!ACPI_VALIDATE_RSDP_SIG(mapped_table
->signature
)) {
1083 acpi_os_unmap_memory(mapped_table
,
1085 acpi_table_header
));
1086 return (AE_BAD_SIGNATURE
);
1089 if (!ACPI_COMPARE_NAMESEG
1090 (signature
, mapped_table
->signature
)) {
1091 acpi_os_unmap_memory(mapped_table
,
1092 sizeof(struct acpi_table_header
));
1093 return (AE_BAD_SIGNATURE
);
1097 /* Map the entire table */
1099 length
= ap_get_table_length(mapped_table
);
1100 acpi_os_unmap_memory(mapped_table
, sizeof(struct acpi_table_header
));
1102 return (AE_BAD_HEADER
);
1105 mapped_table
= acpi_os_map_memory(address
, length
);
1106 if (!mapped_table
) {
1108 "Could not map table at 0x%8.8X%8.8X length %8.8X\n",
1109 ACPI_FORMAT_UINT64(address
), length
);
1110 return (osl_get_last_status(AE_INVALID_TABLE_LENGTH
));
1113 (void)ap_is_valid_checksum(mapped_table
);
1115 *table
= mapped_table
;
1119 /******************************************************************************
1121 * FUNCTION: osl_unmap_table
1123 * PARAMETERS: table - A pointer to the mapped table
1127 * DESCRIPTION: Unmap entire ACPI table.
1129 *****************************************************************************/
1131 static void osl_unmap_table(struct acpi_table_header
*table
)
1134 acpi_os_unmap_memory(table
, ap_get_table_length(table
));
1138 /******************************************************************************
1140 * FUNCTION: osl_table_name_from_file
1142 * PARAMETERS: filename - File that contains the desired table
1143 * signature - Pointer to 4-character buffer to store
1144 * extracted table signature.
1145 * instance - Pointer to integer to store extracted
1146 * table instance number.
1148 * RETURN: Status; Table name is extracted if AE_OK.
1150 * DESCRIPTION: Extract table signature and instance number from a table file
1153 *****************************************************************************/
1156 osl_table_name_from_file(char *filename
, char *signature
, u32
*instance
)
1159 /* Ignore meaningless files */
1161 if (strlen(filename
) < ACPI_NAMESEG_SIZE
) {
1162 return (AE_BAD_SIGNATURE
);
1165 /* Extract instance number */
1167 if (isdigit((int)filename
[ACPI_NAMESEG_SIZE
])) {
1168 sscanf(&filename
[ACPI_NAMESEG_SIZE
], "%u", instance
);
1169 } else if (strlen(filename
) != ACPI_NAMESEG_SIZE
) {
1170 return (AE_BAD_SIGNATURE
);
1175 /* Extract signature */
1177 ACPI_COPY_NAMESEG(signature
, filename
);
1181 /******************************************************************************
1183 * FUNCTION: osl_read_table_from_file
1185 * PARAMETERS: filename - File that contains the desired table
1186 * file_offset - Offset of the table in file
1187 * signature - Optional ACPI Signature for desired table.
1188 * A null terminated 4-character string.
1189 * table - Where a pointer to the table is returned
1191 * RETURN: Status; Table buffer is returned if AE_OK.
1193 * DESCRIPTION: Read a ACPI table from a file.
1195 *****************************************************************************/
1198 osl_read_table_from_file(char *filename
,
1199 acpi_size file_offset
,
1200 char *signature
, struct acpi_table_header
**table
)
1203 struct acpi_table_header header
;
1204 struct acpi_table_header
*local_table
= NULL
;
1207 acpi_status status
= AE_OK
;
1211 table_file
= fopen(filename
, "rb");
1212 if (table_file
== NULL
) {
1213 fprintf(stderr
, "Could not open table file: %s\n", filename
);
1214 return (osl_get_last_status(AE_NOT_FOUND
));
1217 fseek(table_file
, file_offset
, SEEK_SET
);
1219 /* Read the Table header to get the table length */
1221 count
= fread(&header
, 1, sizeof(struct acpi_table_header
), table_file
);
1222 if (count
!= sizeof(struct acpi_table_header
)) {
1223 fprintf(stderr
, "Could not read table header: %s\n", filename
);
1224 status
= AE_BAD_HEADER
;
1228 /* If signature is specified, it must match the table */
1231 if (ACPI_VALIDATE_RSDP_SIG(signature
)) {
1232 if (!ACPI_VALIDATE_RSDP_SIG(header
.signature
)) {
1234 "Incorrect RSDP signature: found %8.8s\n",
1236 status
= AE_BAD_SIGNATURE
;
1239 } else if (!ACPI_COMPARE_NAMESEG(signature
, header
.signature
)) {
1241 "Incorrect signature: Expecting %4.4s, found %4.4s\n",
1242 signature
, header
.signature
);
1243 status
= AE_BAD_SIGNATURE
;
1248 table_length
= ap_get_table_length(&header
);
1249 if (table_length
== 0) {
1250 status
= AE_BAD_HEADER
;
1254 /* Read the entire table into a local buffer */
1256 local_table
= calloc(1, table_length
);
1259 "%4.4s: Could not allocate buffer for table of length %X\n",
1260 header
.signature
, table_length
);
1261 status
= AE_NO_MEMORY
;
1265 fseek(table_file
, file_offset
, SEEK_SET
);
1267 count
= fread(local_table
, 1, table_length
, table_file
);
1268 if (count
!= table_length
) {
1269 fprintf(stderr
, "%4.4s: Could not read table content\n",
1271 status
= AE_INVALID_TABLE_LENGTH
;
1275 /* Validate checksum */
1277 (void)ap_is_valid_checksum(local_table
);
1281 *table
= local_table
;
1285 /******************************************************************************
1287 * FUNCTION: osl_get_customized_table
1289 * PARAMETERS: pathname - Directory to find Linux customized table
1290 * signature - ACPI Signature for desired table. Must be
1291 * a null terminated 4-character string.
1292 * instance - Multiple table support for SSDT/UEFI (0...n)
1293 * Must be 0 for other tables.
1294 * table - Where a pointer to the table is returned
1295 * address - Where the table physical address is returned
1297 * RETURN: Status; Table buffer is returned if AE_OK.
1298 * AE_LIMIT: Instance is beyond valid limit
1299 * AE_NOT_FOUND: A table with the signature was not found
1301 * DESCRIPTION: Get an OS customized table.
1303 *****************************************************************************/
1306 osl_get_customized_table(char *pathname
,
1309 struct acpi_table_header
**table
,
1310 acpi_physical_address
*address
)
1313 u32 current_instance
= 0;
1314 char temp_name
[ACPI_NAMESEG_SIZE
];
1315 char table_filename
[PATH_MAX
];
1319 /* Open the directory for customized tables */
1321 table_dir
= acpi_os_open_directory(pathname
, "*", REQUEST_FILE_ONLY
);
1323 return (osl_get_last_status(AE_NOT_FOUND
));
1326 /* Attempt to find the table in the directory */
1328 while ((filename
= acpi_os_get_next_filename(table_dir
))) {
1330 /* Ignore meaningless files */
1332 if (!ACPI_COMPARE_NAMESEG(filename
, signature
)) {
1336 /* Extract table name and instance number */
1339 osl_table_name_from_file(filename
, temp_name
,
1342 /* Ignore meaningless files */
1344 if (ACPI_FAILURE(status
) || current_instance
!= instance
) {
1348 /* Create the table pathname */
1350 if (instance
!= 0) {
1351 sprintf(table_filename
, "%s/%4.4s%d", pathname
,
1352 temp_name
, instance
);
1354 sprintf(table_filename
, "%s/%4.4s", pathname
,
1360 acpi_os_close_directory(table_dir
);
1366 /* There is no physical address saved for customized tables, use zero */
1369 status
= osl_read_table_from_file(table_filename
, 0, NULL
, table
);