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 - 2023, 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 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 convert 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 * table - Where a pointer to the table is returned
1189 * RETURN: Status; Table buffer is returned if AE_OK.
1191 * DESCRIPTION: Read a ACPI table from a file.
1193 *****************************************************************************/
1196 osl_read_table_from_file(char *filename,
1197 acpi_size file_offset,
1198 struct acpi_table_header **table)
1201 struct acpi_table_header header;
1202 struct acpi_table_header *local_table = NULL;
1205 acpi_status status = AE_OK;
1209 table_file = fopen(filename, "rb");
1210 if (table_file == NULL) {
1211 fprintf(stderr, "Could not open table file: %s\n", filename);
1212 return (osl_get_last_status(AE_NOT_FOUND));
1215 fseek(table_file, file_offset, SEEK_SET);
1217 /* Read the Table header to get the table length */
1219 count = fread(&header, 1, sizeof(struct acpi_table_header), table_file);
1220 if (count != sizeof(struct acpi_table_header)) {
1221 fprintf(stderr, "Could not read table header: %s\n", filename);
1222 status = AE_BAD_HEADER;
1226 #ifdef ACPI_OBSOLETE_FUNCTIONS
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;
1249 table_length = ap_get_table_length(&header);
1250 if (table_length == 0) {
1251 status = AE_BAD_HEADER;
1255 /* Read the entire table into a local buffer */
1257 local_table = calloc(1, table_length);
1260 "%4.4s: Could not allocate buffer for table of length %X\n",
1261 header.signature, table_length);
1262 status = AE_NO_MEMORY;
1266 fseek(table_file, file_offset, SEEK_SET);
1268 count = fread(local_table, 1, table_length, table_file);
1269 if (count != table_length) {
1270 fprintf(stderr, "%4.4s: Could not read table content\n",
1272 status = AE_INVALID_TABLE_LENGTH;
1276 /* Validate checksum */
1278 (void)ap_is_valid_checksum(local_table);
1282 *table = local_table;
1286 /******************************************************************************
1288 * FUNCTION: osl_get_customized_table
1290 * PARAMETERS: pathname - Directory to find Linux customized table
1291 * signature - ACPI Signature for desired table. Must be
1292 * a null terminated 4-character string.
1293 * instance - Multiple table support for SSDT/UEFI (0...n)
1294 * Must be 0 for other tables.
1295 * table - Where a pointer to the table is returned
1296 * address - Where the table physical address is returned
1298 * RETURN: Status; Table buffer is returned if AE_OK.
1299 * AE_LIMIT: Instance is beyond valid limit
1300 * AE_NOT_FOUND: A table with the signature was not found
1302 * DESCRIPTION: Get an OS customized table.
1304 *****************************************************************************/
1307 osl_get_customized_table(char *pathname,
1310 struct acpi_table_header **table,
1311 acpi_physical_address *address)
1314 u32 current_instance = 0;
1315 char temp_name[ACPI_NAMESEG_SIZE];
1316 char table_filename[PATH_MAX];
1320 /* Open the directory for customized tables */
1322 table_dir = acpi_os_open_directory(pathname, "*", REQUEST_FILE_ONLY);
1324 return (osl_get_last_status(AE_NOT_FOUND));
1327 /* Attempt to find the table in the directory */
1329 while ((filename = acpi_os_get_next_filename(table_dir))) {
1331 /* Ignore meaningless files */
1333 if (!ACPI_COMPARE_NAMESEG(filename, signature)) {
1337 /* Extract table name and instance number */
1340 osl_table_name_from_file(filename, temp_name,
1343 /* Ignore meaningless files */
1345 if (ACPI_FAILURE(status) || current_instance != instance) {
1349 /* Create the table pathname */
1351 if (instance != 0) {
1352 sprintf(table_filename, "%s/%4.4s%d", pathname,
1353 temp_name, instance);
1355 sprintf(table_filename, "%s/%4.4s", pathname,
1361 acpi_os_close_directory(table_dir);
1367 /* There is no physical address saved for customized tables, use zero */
1370 status = osl_read_table_from_file(table_filename, 0, table);