1 /******************************************************************************
2 *
3 * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2023, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #include "acpidump.h"
45
46
47 #define _COMPONENT ACPI_OS_SERVICES
48 ACPI_MODULE_NAME ("oslinuxtbl")
49
50
51 #ifndef PATH_MAX
52 #define PATH_MAX 256
53 #endif
54
55
56 /* List of information about obtained ACPI tables */
57
58 typedef struct osl_table_info
59 {
60 struct osl_table_info *Next;
61 UINT32 Instance;
62 char Signature[ACPI_NAMESEG_SIZE];
63
64 } OSL_TABLE_INFO;
65
66 /* Local prototypes */
67
68 static ACPI_STATUS
69 OslTableInitialize (
70 void);
71
72 static ACPI_STATUS
73 OslTableNameFromFile (
74 char *Filename,
75 char *Signature,
76 UINT32 *Instance);
77
78 static ACPI_STATUS
79 OslAddTableToList (
80 char *Signature,
81 UINT32 Instance);
82
83 static ACPI_STATUS
84 OslReadTableFromFile (
85 char *Filename,
86 ACPI_SIZE FileOffset,
87 ACPI_TABLE_HEADER **Table);
88
89 static ACPI_STATUS
90 OslMapTable (
91 ACPI_SIZE Address,
92 char *Signature,
93 ACPI_TABLE_HEADER **Table);
94
95 static void
96 OslUnmapTable (
97 ACPI_TABLE_HEADER *Table);
98
99 static ACPI_PHYSICAL_ADDRESS
100 OslFindRsdpViaEfiByKeyword (
101 FILE *File,
102 const char *Keyword);
103
104 static ACPI_PHYSICAL_ADDRESS
105 OslFindRsdpViaEfi (
106 void);
107
108 static ACPI_STATUS
109 OslLoadRsdp (
110 void);
111
112 static ACPI_STATUS
113 OslListCustomizedTables (
114 char *Directory);
115
116 static ACPI_STATUS
117 OslGetCustomizedTable (
118 char *Pathname,
119 char *Signature,
120 UINT32 Instance,
121 ACPI_TABLE_HEADER **Table,
122 ACPI_PHYSICAL_ADDRESS *Address);
123
124 static ACPI_STATUS
125 OslListBiosTables (
126 void);
127
128 static ACPI_STATUS
129 OslGetBiosTable (
130 char *Signature,
131 UINT32 Instance,
132 ACPI_TABLE_HEADER **Table,
133 ACPI_PHYSICAL_ADDRESS *Address);
134
135 static ACPI_STATUS
136 OslGetLastStatus (
137 ACPI_STATUS DefaultStatus);
138
139
140 /* File locations */
141
142 #define DYNAMIC_TABLE_DIR "/sys/firmware/acpi/tables/dynamic"
143 #define STATIC_TABLE_DIR "/sys/firmware/acpi/tables"
144 #define EFI_SYSTAB "/sys/firmware/efi/systab"
145
146 /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */
147
148 UINT8 Gbl_DumpDynamicTables = TRUE;
149
150 /* Initialization flags */
151
152 UINT8 Gbl_TableListInitialized = FALSE;
153
154 /* Local copies of main ACPI tables */
155
156 ACPI_TABLE_RSDP Gbl_Rsdp;
157 ACPI_TABLE_FADT *Gbl_Fadt = NULL;
158 ACPI_TABLE_RSDT *Gbl_Rsdt = NULL;
159 ACPI_TABLE_XSDT *Gbl_Xsdt = NULL;
160
161 /* Table addresses */
162
163 ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress = 0;
164 ACPI_PHYSICAL_ADDRESS Gbl_RsdpAddress = 0;
165
166 /* Revision of RSD PTR */
167
168 UINT8 Gbl_Revision = 0;
169
170 OSL_TABLE_INFO *Gbl_TableListHead = NULL;
171 UINT32 Gbl_TableCount = 0;
172
173
174 /******************************************************************************
175 *
176 * FUNCTION: OslGetLastStatus
177 *
178 * PARAMETERS: DefaultStatus - Default error status to return
179 *
180 * RETURN: Status; Converted from errno.
181 *
182 * DESCRIPTION: Get last errno and convert it to ACPI_STATUS.
183 *
184 *****************************************************************************/
185
186 static ACPI_STATUS
OslGetLastStatus(ACPI_STATUS DefaultStatus)187 OslGetLastStatus (
188 ACPI_STATUS DefaultStatus)
189 {
190
191 switch (errno)
192 {
193 case EACCES:
194 case EPERM:
195
196 return (AE_ACCESS);
197
198 case ENOENT:
199
200 return (AE_NOT_FOUND);
201
202 case ENOMEM:
203
204 return (AE_NO_MEMORY);
205
206 default:
207
208 return (DefaultStatus);
209 }
210 }
211
212
213 /******************************************************************************
214 *
215 * FUNCTION: AcpiOsGetTableByAddress
216 *
217 * PARAMETERS: Address - Physical address of the ACPI table
218 * Table - Where a pointer to the table is returned
219 *
220 * RETURN: Status; Table buffer is returned if AE_OK.
221 * AE_NOT_FOUND: A valid table was not found at the address
222 *
223 * DESCRIPTION: Get an ACPI table via a physical memory address.
224 *
225 *****************************************************************************/
226
227 ACPI_STATUS
AcpiOsGetTableByAddress(ACPI_PHYSICAL_ADDRESS Address,ACPI_TABLE_HEADER ** Table)228 AcpiOsGetTableByAddress (
229 ACPI_PHYSICAL_ADDRESS Address,
230 ACPI_TABLE_HEADER **Table)
231 {
232 UINT32 TableLength;
233 ACPI_TABLE_HEADER *MappedTable;
234 ACPI_TABLE_HEADER *LocalTable = NULL;
235 ACPI_STATUS Status = AE_OK;
236
237
238 /* Get main ACPI tables from memory on first invocation of this function */
239
240 Status = OslTableInitialize ();
241 if (ACPI_FAILURE (Status))
242 {
243 return (Status);
244 }
245
246 /* Map the table and validate it */
247
248 Status = OslMapTable (Address, NULL, &MappedTable);
249 if (ACPI_FAILURE (Status))
250 {
251 return (Status);
252 }
253
254 /* Copy table to local buffer and return it */
255
256 TableLength = ApGetTableLength (MappedTable);
257 if (TableLength == 0)
258 {
259 Status = AE_BAD_HEADER;
260 goto Exit;
261 }
262
263 LocalTable = calloc (1, TableLength);
264 if (!LocalTable)
265 {
266 Status = AE_NO_MEMORY;
267 goto Exit;
268 }
269
270 memcpy (LocalTable, MappedTable, TableLength);
271
272 Exit:
273 OslUnmapTable (MappedTable);
274 *Table = LocalTable;
275 return (Status);
276 }
277
278
279 /******************************************************************************
280 *
281 * FUNCTION: AcpiOsGetTableByName
282 *
283 * PARAMETERS: Signature - ACPI Signature for desired table. Must be
284 * a null terminated 4-character string.
285 * Instance - Multiple table support for SSDT/UEFI (0...n)
286 * Must be 0 for other tables.
287 * Table - Where a pointer to the table is returned
288 * Address - Where the table physical address is returned
289 *
290 * RETURN: Status; Table buffer and physical address returned if AE_OK.
291 * AE_LIMIT: Instance is beyond valid limit
292 * AE_NOT_FOUND: A table with the signature was not found
293 *
294 * NOTE: Assumes the input signature is uppercase.
295 *
296 *****************************************************************************/
297
298 ACPI_STATUS
AcpiOsGetTableByName(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)299 AcpiOsGetTableByName (
300 char *Signature,
301 UINT32 Instance,
302 ACPI_TABLE_HEADER **Table,
303 ACPI_PHYSICAL_ADDRESS *Address)
304 {
305 ACPI_STATUS Status;
306
307
308 /* Get main ACPI tables from memory on first invocation of this function */
309
310 Status = OslTableInitialize ();
311 if (ACPI_FAILURE (Status))
312 {
313 return (Status);
314 }
315
316 /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
317
318 if (!Gbl_DumpCustomizedTables)
319 {
320 /* Attempt to get the table from the memory */
321
322 Status = OslGetBiosTable (Signature, Instance, Table, Address);
323 }
324 else
325 {
326 /* Attempt to get the table from the static directory */
327
328 Status = OslGetCustomizedTable (STATIC_TABLE_DIR, Signature,
329 Instance, Table, Address);
330 }
331
332 if (ACPI_FAILURE (Status) && Status == AE_LIMIT)
333 {
334 if (Gbl_DumpDynamicTables)
335 {
336 /* Attempt to get a dynamic table */
337
338 Status = OslGetCustomizedTable (DYNAMIC_TABLE_DIR, Signature,
339 Instance, Table, Address);
340 }
341 }
342
343 return (Status);
344 }
345
346
347 /******************************************************************************
348 *
349 * FUNCTION: OslAddTableToList
350 *
351 * PARAMETERS: Signature - Table signature
352 * Instance - Table instance
353 *
354 * RETURN: Status; Successfully added if AE_OK.
355 * AE_NO_MEMORY: Memory allocation error
356 *
357 * DESCRIPTION: Insert a table structure into OSL table list.
358 *
359 *****************************************************************************/
360
361 static ACPI_STATUS
OslAddTableToList(char * Signature,UINT32 Instance)362 OslAddTableToList (
363 char *Signature,
364 UINT32 Instance)
365 {
366 OSL_TABLE_INFO *NewInfo;
367 OSL_TABLE_INFO *Next;
368 UINT32 NextInstance = 0;
369 BOOLEAN Found = FALSE;
370
371
372 NewInfo = calloc (1, sizeof (OSL_TABLE_INFO));
373 if (!NewInfo)
374 {
375 return (AE_NO_MEMORY);
376 }
377
378 ACPI_COPY_NAMESEG (NewInfo->Signature, Signature);
379
380 if (!Gbl_TableListHead)
381 {
382 Gbl_TableListHead = NewInfo;
383 }
384 else
385 {
386 Next = Gbl_TableListHead;
387 while (1)
388 {
389 if (ACPI_COMPARE_NAMESEG (Next->Signature, Signature))
390 {
391 if (Next->Instance == Instance)
392 {
393 Found = TRUE;
394 }
395 if (Next->Instance >= NextInstance)
396 {
397 NextInstance = Next->Instance + 1;
398 }
399 }
400
401 if (!Next->Next)
402 {
403 break;
404 }
405 Next = Next->Next;
406 }
407 Next->Next = NewInfo;
408 }
409
410 if (Found)
411 {
412 if (Instance)
413 {
414 fprintf (stderr,
415 "%4.4s: Warning unmatched table instance %d, expected %d\n",
416 Signature, Instance, NextInstance);
417 }
418 Instance = NextInstance;
419 }
420
421 NewInfo->Instance = Instance;
422 Gbl_TableCount++;
423
424 return (AE_OK);
425 }
426
427
428 /******************************************************************************
429 *
430 * FUNCTION: AcpiOsGetTableByIndex
431 *
432 * PARAMETERS: Index - Which table to get
433 * Table - Where a pointer to the table is returned
434 * Instance - Where a pointer to the table instance no. is
435 * returned
436 * Address - Where the table physical address is returned
437 *
438 * RETURN: Status; Table buffer and physical address returned if AE_OK.
439 * AE_LIMIT: Index is beyond valid limit
440 *
441 * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
442 * AE_LIMIT when an invalid index is reached. Index is not
443 * necessarily an index into the RSDT/XSDT.
444 *
445 *****************************************************************************/
446
447 ACPI_STATUS
AcpiOsGetTableByIndex(UINT32 Index,ACPI_TABLE_HEADER ** Table,UINT32 * Instance,ACPI_PHYSICAL_ADDRESS * Address)448 AcpiOsGetTableByIndex (
449 UINT32 Index,
450 ACPI_TABLE_HEADER **Table,
451 UINT32 *Instance,
452 ACPI_PHYSICAL_ADDRESS *Address)
453 {
454 OSL_TABLE_INFO *Info;
455 ACPI_STATUS Status;
456 UINT32 i;
457
458
459 /* Get main ACPI tables from memory on first invocation of this function */
460
461 Status = OslTableInitialize ();
462 if (ACPI_FAILURE (Status))
463 {
464 return (Status);
465 }
466
467 /* Validate Index */
468
469 if (Index >= Gbl_TableCount)
470 {
471 return (AE_LIMIT);
472 }
473
474 /* Point to the table list entry specified by the Index argument */
475
476 Info = Gbl_TableListHead;
477 for (i = 0; i < Index; i++)
478 {
479 Info = Info->Next;
480 }
481
482 /* Now we can just get the table via the signature */
483
484 Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
485 Table, Address);
486
487 if (ACPI_SUCCESS (Status))
488 {
489 *Instance = Info->Instance;
490 }
491 return (Status);
492 }
493
494
495 /******************************************************************************
496 *
497 * FUNCTION: OslFindRsdpViaEfiByKeyword
498 *
499 * PARAMETERS: Keyword - Character string indicating ACPI GUID version
500 * in the EFI table
501 *
502 * RETURN: RSDP address if found
503 *
504 * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI
505 * GUID version.
506 *
507 *****************************************************************************/
508
509 static ACPI_PHYSICAL_ADDRESS
OslFindRsdpViaEfiByKeyword(FILE * File,const char * Keyword)510 OslFindRsdpViaEfiByKeyword (
511 FILE *File,
512 const char *Keyword)
513 {
514 char Buffer[80];
515 unsigned long long Address = 0;
516 char Format[32];
517
518
519 snprintf (Format, 32, "%s=%s", Keyword, "%llx");
520 fseek (File, 0, SEEK_SET);
521 while (fgets (Buffer, 80, File))
522 {
523 if (sscanf (Buffer, Format, &Address) == 1)
524 {
525 break;
526 }
527 }
528
529 return ((ACPI_PHYSICAL_ADDRESS) (Address));
530 }
531
532
533 /******************************************************************************
534 *
535 * FUNCTION: OslFindRsdpViaEfi
536 *
537 * PARAMETERS: None
538 *
539 * RETURN: RSDP address if found
540 *
541 * DESCRIPTION: Find RSDP address via EFI.
542 *
543 *****************************************************************************/
544
545 static ACPI_PHYSICAL_ADDRESS
OslFindRsdpViaEfi(void)546 OslFindRsdpViaEfi (
547 void)
548 {
549 FILE *File;
550 ACPI_PHYSICAL_ADDRESS Address = 0;
551
552
553 File = fopen (EFI_SYSTAB, "r");
554 if (File)
555 {
556 Address = OslFindRsdpViaEfiByKeyword (File, "ACPI20");
557 if (!Address)
558 {
559 Address = OslFindRsdpViaEfiByKeyword (File, "ACPI");
560 }
561 fclose (File);
562 }
563
564 return (Address);
565 }
566
567
568 /******************************************************************************
569 *
570 * FUNCTION: OslLoadRsdp
571 *
572 * PARAMETERS: None
573 *
574 * RETURN: Status
575 *
576 * DESCRIPTION: Scan and load RSDP.
577 *
578 *****************************************************************************/
579
580 static ACPI_STATUS
OslLoadRsdp(void)581 OslLoadRsdp (
582 void)
583 {
584 ACPI_TABLE_HEADER *MappedTable;
585 UINT8 *RsdpAddress;
586 ACPI_PHYSICAL_ADDRESS RsdpBase;
587 ACPI_SIZE RsdpSize;
588
589
590 /* Get RSDP from memory */
591
592 RsdpSize = sizeof (ACPI_TABLE_RSDP);
593 if (Gbl_RsdpBase)
594 {
595 RsdpBase = Gbl_RsdpBase;
596 }
597 else
598 {
599 RsdpBase = OslFindRsdpViaEfi ();
600 }
601
602 if (!RsdpBase)
603 {
604 RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
605 RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
606 }
607
608 RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
609 if (!RsdpAddress)
610 {
611 return (OslGetLastStatus (AE_BAD_ADDRESS));
612 }
613
614 /* Search low memory for the RSDP */
615
616 MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER,
617 AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize));
618 if (!MappedTable)
619 {
620 AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
621 return (AE_NOT_FOUND);
622 }
623
624 Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress);
625
626 memcpy (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP));
627 AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
628
629 return (AE_OK);
630 }
631
632
633 /******************************************************************************
634 *
635 * FUNCTION: OslCanUseXsdt
636 *
637 * PARAMETERS: None
638 *
639 * RETURN: TRUE if XSDT is allowed to be used.
640 *
641 * DESCRIPTION: This function collects logic that can be used to determine if
642 * XSDT should be used instead of RSDT.
643 *
644 *****************************************************************************/
645
646 static BOOLEAN
OslCanUseXsdt(void)647 OslCanUseXsdt (
648 void)
649 {
650 if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt)
651 {
652 return (TRUE);
653 }
654 else
655 {
656 return (FALSE);
657 }
658 }
659
660
661 /******************************************************************************
662 *
663 * FUNCTION: OslTableInitialize
664 *
665 * PARAMETERS: None
666 *
667 * RETURN: Status
668 *
669 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
670 * local variables. Main ACPI tables include RSDT, FADT, RSDT,
671 * and/or XSDT.
672 *
673 *****************************************************************************/
674
675 static ACPI_STATUS
OslTableInitialize(void)676 OslTableInitialize (
677 void)
678 {
679 ACPI_STATUS Status;
680 ACPI_PHYSICAL_ADDRESS Address;
681
682
683 if (Gbl_TableListInitialized)
684 {
685 return (AE_OK);
686 }
687
688 if (!Gbl_DumpCustomizedTables)
689 {
690 /* Get RSDP from memory */
691
692 Status = OslLoadRsdp ();
693 if (ACPI_FAILURE (Status))
694 {
695 return (Status);
696 }
697
698 /* Get XSDT from memory */
699
700 if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt)
701 {
702 if (Gbl_Xsdt)
703 {
704 free (Gbl_Xsdt);
705 Gbl_Xsdt = NULL;
706 }
707
708 Gbl_Revision = 2;
709 Status = OslGetBiosTable (ACPI_SIG_XSDT, 0,
710 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address);
711 if (ACPI_FAILURE (Status))
712 {
713 return (Status);
714 }
715 }
716
717 /* Get RSDT from memory */
718
719 if (Gbl_Rsdp.RsdtPhysicalAddress)
720 {
721 if (Gbl_Rsdt)
722 {
723 free (Gbl_Rsdt);
724 Gbl_Rsdt = NULL;
725 }
726
727 Status = OslGetBiosTable (ACPI_SIG_RSDT, 0,
728 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address);
729 if (ACPI_FAILURE (Status))
730 {
731 return (Status);
732 }
733 }
734
735 /* Get FADT from memory */
736
737 if (Gbl_Fadt)
738 {
739 free (Gbl_Fadt);
740 Gbl_Fadt = NULL;
741 }
742
743 Status = OslGetBiosTable (ACPI_SIG_FADT, 0,
744 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress);
745 if (ACPI_FAILURE (Status))
746 {
747 return (Status);
748 }
749
750 /* Add mandatory tables to global table list first */
751
752 Status = OslAddTableToList (ACPI_RSDP_NAME, 0);
753 if (ACPI_FAILURE (Status))
754 {
755 return (Status);
756 }
757
758 Status = OslAddTableToList (ACPI_SIG_RSDT, 0);
759 if (ACPI_FAILURE (Status))
760 {
761 return (Status);
762 }
763
764 if (Gbl_Revision == 2)
765 {
766 Status = OslAddTableToList (ACPI_SIG_XSDT, 0);
767 if (ACPI_FAILURE (Status))
768 {
769 return (Status);
770 }
771 }
772
773 Status = OslAddTableToList (ACPI_SIG_DSDT, 0);
774 if (ACPI_FAILURE (Status))
775 {
776 return (Status);
777 }
778
779 Status = OslAddTableToList (ACPI_SIG_FACS, 0);
780 if (ACPI_FAILURE (Status))
781 {
782 return (Status);
783 }
784
785 /* Add all tables found in the memory */
786
787 Status = OslListBiosTables ();
788 if (ACPI_FAILURE (Status))
789 {
790 return (Status);
791 }
792 }
793 else
794 {
795 /* Add all tables found in the static directory */
796
797 Status = OslListCustomizedTables (STATIC_TABLE_DIR);
798 if (ACPI_FAILURE (Status))
799 {
800 return (Status);
801 }
802 }
803
804 if (Gbl_DumpDynamicTables)
805 {
806 /* Add all dynamically loaded tables in the dynamic directory */
807
808 Status = OslListCustomizedTables (DYNAMIC_TABLE_DIR);
809 if (ACPI_FAILURE (Status))
810 {
811 return (Status);
812 }
813 }
814
815 Gbl_TableListInitialized = TRUE;
816 return (AE_OK);
817 }
818
819
820 /******************************************************************************
821 *
822 * FUNCTION: OslListBiosTables
823 *
824 * PARAMETERS: None
825 *
826 * RETURN: Status; Table list is initialized if AE_OK.
827 *
828 * DESCRIPTION: Add ACPI tables to the table list from memory.
829 *
830 * NOTE: This works on Linux as table customization does not modify the
831 * addresses stored in RSDP/RSDT/XSDT/FADT.
832 *
833 *****************************************************************************/
834
835 static ACPI_STATUS
OslListBiosTables(void)836 OslListBiosTables (
837 void)
838 {
839 ACPI_TABLE_HEADER *MappedTable = NULL;
840 UINT8 *TableData;
841 UINT8 NumberOfTables;
842 UINT8 ItemSize;
843 ACPI_PHYSICAL_ADDRESS TableAddress = 0;
844 ACPI_STATUS Status = AE_OK;
845 UINT32 i;
846
847
848 if (OslCanUseXsdt ())
849 {
850 ItemSize = sizeof (UINT64);
851 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
852 NumberOfTables =
853 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
854 / ItemSize);
855 }
856 else /* Use RSDT if XSDT is not available */
857 {
858 ItemSize = sizeof (UINT32);
859 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
860 NumberOfTables =
861 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
862 / ItemSize);
863 }
864
865 /* Search RSDT/XSDT for the requested table */
866
867 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
868 {
869 if (OslCanUseXsdt ())
870 {
871 TableAddress =
872 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
873 }
874 else
875 {
876 TableAddress =
877 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
878 }
879
880 /* Skip NULL entries in RSDT/XSDT */
881
882 if (TableAddress == 0)
883 {
884 continue;
885 }
886
887 Status = OslMapTable (TableAddress, NULL, &MappedTable);
888 if (ACPI_FAILURE (Status))
889 {
890 return (Status);
891 }
892
893 OslAddTableToList (MappedTable->Signature, 0);
894 OslUnmapTable (MappedTable);
895 }
896
897 return (AE_OK);
898 }
899
900
901 /******************************************************************************
902 *
903 * FUNCTION: OslGetBiosTable
904 *
905 * PARAMETERS: Signature - ACPI Signature for common table. Must be
906 * a null terminated 4-character string.
907 * Instance - Multiple table support for SSDT/UEFI (0...n)
908 * Must be 0 for other tables.
909 * Table - Where a pointer to the table is returned
910 * Address - Where the table physical address is returned
911 *
912 * RETURN: Status; Table buffer and physical address returned if AE_OK.
913 * AE_LIMIT: Instance is beyond valid limit
914 * AE_NOT_FOUND: A table with the signature was not found
915 *
916 * DESCRIPTION: Get a BIOS provided ACPI table
917 *
918 * NOTE: Assumes the input signature is uppercase.
919 *
920 *****************************************************************************/
921
922 static ACPI_STATUS
OslGetBiosTable(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)923 OslGetBiosTable (
924 char *Signature,
925 UINT32 Instance,
926 ACPI_TABLE_HEADER **Table,
927 ACPI_PHYSICAL_ADDRESS *Address)
928 {
929 ACPI_TABLE_HEADER *LocalTable = NULL;
930 ACPI_TABLE_HEADER *MappedTable = NULL;
931 UINT8 *TableData;
932 UINT8 NumberOfTables;
933 UINT8 ItemSize;
934 UINT32 CurrentInstance = 0;
935 ACPI_PHYSICAL_ADDRESS TableAddress;
936 ACPI_PHYSICAL_ADDRESS FirstTableAddress = 0;
937 UINT32 TableLength = 0;
938 ACPI_STATUS Status = AE_OK;
939 UINT32 i;
940
941
942 /* Handle special tables whose addresses are not in RSDT/XSDT */
943
944 if (ACPI_COMPARE_NAMESEG (Signature, ACPI_RSDP_NAME) ||
945 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT) ||
946 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT) ||
947 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT) ||
948 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
949 {
950
951 FindNextInstance:
952
953 TableAddress = 0;
954
955 /*
956 * Get the appropriate address, either 32-bit or 64-bit. Be very
957 * careful about the FADT length and validate table addresses.
958 * Note: The 64-bit addresses have priority.
959 */
960 if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT))
961 {
962 if (CurrentInstance < 2)
963 {
964 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
965 Gbl_Fadt->XDsdt && CurrentInstance == 0)
966 {
967 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
968 }
969 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
970 Gbl_Fadt->Dsdt != FirstTableAddress)
971 {
972 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
973 }
974 }
975 }
976 else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
977 {
978 if (CurrentInstance < 2)
979 {
980 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
981 Gbl_Fadt->XFacs && CurrentInstance == 0)
982 {
983 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
984 }
985 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
986 Gbl_Fadt->Facs != FirstTableAddress)
987 {
988 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
989 }
990 }
991 }
992 else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT))
993 {
994 if (!Gbl_Revision)
995 {
996 return (AE_BAD_SIGNATURE);
997 }
998 if (CurrentInstance == 0)
999 {
1000 TableAddress =
1001 (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
1002 }
1003 }
1004 else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT))
1005 {
1006 if (CurrentInstance == 0)
1007 {
1008 TableAddress =
1009 (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
1010 }
1011 }
1012 else
1013 {
1014 if (CurrentInstance == 0)
1015 {
1016 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
1017 Signature = ACPI_SIG_RSDP;
1018 }
1019 }
1020
1021 if (TableAddress == 0)
1022 {
1023 goto ExitFindTable;
1024 }
1025
1026 /* Now we can get the requested special table */
1027
1028 Status = OslMapTable (TableAddress, Signature, &MappedTable);
1029 if (ACPI_FAILURE (Status))
1030 {
1031 return (Status);
1032 }
1033
1034 TableLength = ApGetTableLength (MappedTable);
1035 if (FirstTableAddress == 0)
1036 {
1037 FirstTableAddress = TableAddress;
1038 }
1039
1040 /* Match table instance */
1041
1042 if (CurrentInstance != Instance)
1043 {
1044 OslUnmapTable (MappedTable);
1045 MappedTable = NULL;
1046 CurrentInstance++;
1047 goto FindNextInstance;
1048 }
1049 }
1050 else /* Case for a normal ACPI table */
1051 {
1052 if (OslCanUseXsdt ())
1053 {
1054 ItemSize = sizeof (UINT64);
1055 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER);
1056 NumberOfTables =
1057 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
1058 / ItemSize);
1059 }
1060 else /* Use RSDT if XSDT is not available */
1061 {
1062 ItemSize = sizeof (UINT32);
1063 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER);
1064 NumberOfTables =
1065 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER))
1066 / ItemSize);
1067 }
1068
1069 /* Search RSDT/XSDT for the requested table */
1070
1071 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize)
1072 {
1073 if (OslCanUseXsdt ())
1074 {
1075 TableAddress =
1076 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData));
1077 }
1078 else
1079 {
1080 TableAddress =
1081 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData));
1082 }
1083
1084 /* Skip NULL entries in RSDT/XSDT */
1085
1086 if (TableAddress == 0)
1087 {
1088 continue;
1089 }
1090
1091 Status = OslMapTable (TableAddress, NULL, &MappedTable);
1092 if (ACPI_FAILURE (Status))
1093 {
1094 return (Status);
1095 }
1096 TableLength = MappedTable->Length;
1097
1098 /* Does this table match the requested signature? */
1099
1100 if (!ACPI_COMPARE_NAMESEG (MappedTable->Signature, Signature))
1101 {
1102 OslUnmapTable (MappedTable);
1103 MappedTable = NULL;
1104 continue;
1105 }
1106
1107 /* Match table instance (for SSDT/UEFI tables) */
1108
1109 if (CurrentInstance != Instance)
1110 {
1111 OslUnmapTable (MappedTable);
1112 MappedTable = NULL;
1113 CurrentInstance++;
1114 continue;
1115 }
1116
1117 break;
1118 }
1119 }
1120
1121 ExitFindTable:
1122
1123 if (!MappedTable)
1124 {
1125 return (AE_LIMIT);
1126 }
1127
1128 if (TableLength == 0)
1129 {
1130 Status = AE_BAD_HEADER;
1131 goto Exit;
1132 }
1133
1134 /* Copy table to local buffer and return it */
1135
1136 LocalTable = calloc (1, TableLength);
1137 if (!LocalTable)
1138 {
1139 Status = AE_NO_MEMORY;
1140 goto Exit;
1141 }
1142
1143 memcpy (LocalTable, MappedTable, TableLength);
1144 *Address = TableAddress;
1145 *Table = LocalTable;
1146
1147 Exit:
1148 OslUnmapTable (MappedTable);
1149 return (Status);
1150 }
1151
1152
1153 /******************************************************************************
1154 *
1155 * FUNCTION: OslListCustomizedTables
1156 *
1157 * PARAMETERS: Directory - Directory that contains the tables
1158 *
1159 * RETURN: Status; Table list is initialized if AE_OK.
1160 *
1161 * DESCRIPTION: Add ACPI tables to the table list from a directory.
1162 *
1163 *****************************************************************************/
1164
1165 static ACPI_STATUS
OslListCustomizedTables(char * Directory)1166 OslListCustomizedTables (
1167 char *Directory)
1168 {
1169 void *TableDir;
1170 UINT32 Instance;
1171 char TempName[ACPI_NAMESEG_SIZE];
1172 char *Filename;
1173 ACPI_STATUS Status = AE_OK;
1174
1175
1176 /* Open the requested directory */
1177
1178 TableDir = AcpiOsOpenDirectory (Directory, "*", REQUEST_FILE_ONLY);
1179 if (!TableDir)
1180 {
1181 return (OslGetLastStatus (AE_NOT_FOUND));
1182 }
1183
1184 /* Examine all entries in this directory */
1185
1186 while ((Filename = AcpiOsGetNextFilename (TableDir)))
1187 {
1188 /* Extract table name and instance number */
1189
1190 Status = OslTableNameFromFile (Filename, TempName, &Instance);
1191
1192 /* Ignore meaningless files */
1193
1194 if (ACPI_FAILURE (Status))
1195 {
1196 continue;
1197 }
1198
1199 /* Add new info node to global table list */
1200
1201 Status = OslAddTableToList (TempName, Instance);
1202 if (ACPI_FAILURE (Status))
1203 {
1204 break;
1205 }
1206 }
1207
1208 AcpiOsCloseDirectory (TableDir);
1209 return (Status);
1210 }
1211
1212
1213 /******************************************************************************
1214 *
1215 * FUNCTION: OslMapTable
1216 *
1217 * PARAMETERS: Address - Address of the table in memory
1218 * Signature - Optional ACPI Signature for desired table.
1219 * Null terminated 4-character string.
1220 * Table - Where a pointer to the mapped table is
1221 * returned
1222 *
1223 * RETURN: Status; Mapped table is returned if AE_OK.
1224 * AE_NOT_FOUND: A valid table was not found at the address
1225 *
1226 * DESCRIPTION: Map entire ACPI table into caller's address space.
1227 *
1228 *****************************************************************************/
1229
1230 static ACPI_STATUS
OslMapTable(ACPI_SIZE Address,char * Signature,ACPI_TABLE_HEADER ** Table)1231 OslMapTable (
1232 ACPI_SIZE Address,
1233 char *Signature,
1234 ACPI_TABLE_HEADER **Table)
1235 {
1236 ACPI_TABLE_HEADER *MappedTable;
1237 UINT32 Length;
1238
1239
1240 if (!Address)
1241 {
1242 return (AE_BAD_ADDRESS);
1243 }
1244
1245 /*
1246 * Map the header so we can get the table length.
1247 * Use sizeof (ACPI_TABLE_HEADER) as:
1248 * 1. it is bigger than 24 to include RSDP->Length
1249 * 2. it is smaller than sizeof (ACPI_TABLE_RSDP)
1250 */
1251 MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
1252 if (!MappedTable)
1253 {
1254 fprintf (stderr, "Could not map table header at 0x%8.8X%8.8X\n",
1255 ACPI_FORMAT_UINT64 (Address));
1256 return (OslGetLastStatus (AE_BAD_ADDRESS));
1257 }
1258
1259 /* If specified, signature must match */
1260
1261 if (Signature)
1262 {
1263 if (ACPI_VALIDATE_RSDP_SIG (Signature))
1264 {
1265 if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature))
1266 {
1267 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1268 return (AE_BAD_SIGNATURE);
1269 }
1270 }
1271 else if (!ACPI_COMPARE_NAMESEG (Signature, MappedTable->Signature))
1272 {
1273 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1274 return (AE_BAD_SIGNATURE);
1275 }
1276 }
1277
1278 /* Map the entire table */
1279
1280 Length = ApGetTableLength (MappedTable);
1281 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
1282 if (Length == 0)
1283 {
1284 return (AE_BAD_HEADER);
1285 }
1286
1287 MappedTable = AcpiOsMapMemory (Address, Length);
1288 if (!MappedTable)
1289 {
1290 fprintf (stderr, "Could not map table at 0x%8.8X%8.8X length %8.8X\n",
1291 ACPI_FORMAT_UINT64 (Address), Length);
1292 return (OslGetLastStatus (AE_INVALID_TABLE_LENGTH));
1293 }
1294
1295 (void) ApIsValidChecksum (MappedTable);
1296
1297 *Table = MappedTable;
1298 return (AE_OK);
1299 }
1300
1301
1302 /******************************************************************************
1303 *
1304 * FUNCTION: OslUnmapTable
1305 *
1306 * PARAMETERS: Table - A pointer to the mapped table
1307 *
1308 * RETURN: None
1309 *
1310 * DESCRIPTION: Unmap entire ACPI table.
1311 *
1312 *****************************************************************************/
1313
1314 static void
OslUnmapTable(ACPI_TABLE_HEADER * Table)1315 OslUnmapTable (
1316 ACPI_TABLE_HEADER *Table)
1317 {
1318 if (Table)
1319 {
1320 AcpiOsUnmapMemory (Table, ApGetTableLength (Table));
1321 }
1322 }
1323
1324
1325 /******************************************************************************
1326 *
1327 * FUNCTION: OslTableNameFromFile
1328 *
1329 * PARAMETERS: Filename - File that contains the desired table
1330 * Signature - Pointer to 4-character buffer to store
1331 * extracted table signature.
1332 * Instance - Pointer to integer to store extracted
1333 * table instance number.
1334 *
1335 * RETURN: Status; Table name is extracted if AE_OK.
1336 *
1337 * DESCRIPTION: Extract table signature and instance number from a table file
1338 * name.
1339 *
1340 *****************************************************************************/
1341
1342 static ACPI_STATUS
OslTableNameFromFile(char * Filename,char * Signature,UINT32 * Instance)1343 OslTableNameFromFile (
1344 char *Filename,
1345 char *Signature,
1346 UINT32 *Instance)
1347 {
1348
1349 /* Ignore meaningless files */
1350
1351 if (strlen (Filename) < ACPI_NAMESEG_SIZE)
1352 {
1353 return (AE_BAD_SIGNATURE);
1354 }
1355
1356 /* Extract instance number */
1357
1358 if (isdigit ((int) Filename[ACPI_NAMESEG_SIZE]))
1359 {
1360 sscanf (&Filename[ACPI_NAMESEG_SIZE], "%u", Instance);
1361 }
1362 else if (strlen (Filename) != ACPI_NAMESEG_SIZE)
1363 {
1364 return (AE_BAD_SIGNATURE);
1365 }
1366 else
1367 {
1368 *Instance = 0;
1369 }
1370
1371 /* Extract signature */
1372
1373 ACPI_COPY_NAMESEG (Signature, Filename);
1374 return (AE_OK);
1375 }
1376
1377
1378 /******************************************************************************
1379 *
1380 * FUNCTION: OslReadTableFromFile
1381 *
1382 * PARAMETERS: Filename - File that contains the desired table
1383 * FileOffset - Offset of the table in file
1384 * Table - Where a pointer to the table is returned
1385 *
1386 * RETURN: Status; Table buffer is returned if AE_OK.
1387 *
1388 * DESCRIPTION: Read a ACPI table from a file.
1389 *
1390 *****************************************************************************/
1391
1392 static ACPI_STATUS
OslReadTableFromFile(char * Filename,ACPI_SIZE FileOffset,ACPI_TABLE_HEADER ** Table)1393 OslReadTableFromFile (
1394 char *Filename,
1395 ACPI_SIZE FileOffset,
1396 ACPI_TABLE_HEADER **Table)
1397 {
1398 FILE *TableFile;
1399 ACPI_TABLE_HEADER Header;
1400 ACPI_TABLE_HEADER *LocalTable = NULL;
1401 UINT32 TableLength;
1402 INT32 Count;
1403 ACPI_STATUS Status = AE_OK;
1404
1405
1406 /* Open the file */
1407
1408 TableFile = fopen (Filename, "rb");
1409 if (TableFile == NULL)
1410 {
1411 fprintf (stderr, "Could not open table file: %s\n", Filename);
1412 return (OslGetLastStatus (AE_NOT_FOUND));
1413 }
1414
1415 fseek (TableFile, FileOffset, SEEK_SET);
1416
1417 /* Read the Table header to get the table length */
1418
1419 Count = fread (&Header, 1, sizeof (ACPI_TABLE_HEADER), TableFile);
1420 if (Count != sizeof (ACPI_TABLE_HEADER))
1421 {
1422 fprintf (stderr, "Could not read table header: %s\n", Filename);
1423 Status = AE_BAD_HEADER;
1424 goto Exit;
1425 }
1426
1427 #ifdef ACPI_OBSOLETE_FUNCTIONS
1428
1429 /* If signature is specified, it must match the table */
1430
1431 if (Signature)
1432 {
1433 if (ACPI_VALIDATE_RSDP_SIG (Signature))
1434 {
1435 if (!ACPI_VALIDATE_RSDP_SIG (Header.Signature)) {
1436 fprintf (stderr, "Incorrect RSDP signature: found %8.8s\n",
1437 Header.Signature);
1438 Status = AE_BAD_SIGNATURE;
1439 goto Exit;
1440 }
1441 }
1442 else if (!ACPI_COMPARE_NAMESEG (Signature, Header.Signature))
1443 {
1444 fprintf (stderr, "Incorrect signature: Expecting %4.4s, found %4.4s\n",
1445 Signature, Header.Signature);
1446 Status = AE_BAD_SIGNATURE;
1447 goto Exit;
1448 }
1449 }
1450 #endif
1451
1452 TableLength = ApGetTableLength (&Header);
1453 if (TableLength == 0)
1454 {
1455 Status = AE_BAD_HEADER;
1456 goto Exit;
1457 }
1458
1459 /* Read the entire table into a local buffer */
1460
1461 LocalTable = calloc (1, TableLength);
1462 if (!LocalTable)
1463 {
1464 fprintf (stderr,
1465 "%4.4s: Could not allocate buffer for table of length %X\n",
1466 Header.Signature, TableLength);
1467 Status = AE_NO_MEMORY;
1468 goto Exit;
1469 }
1470
1471 fseek (TableFile, FileOffset, SEEK_SET);
1472
1473 Count = fread (LocalTable, 1, TableLength, TableFile);
1474 if (Count != TableLength)
1475 {
1476 fprintf (stderr, "%4.4s: Could not read table content\n",
1477 Header.Signature);
1478 Status = AE_INVALID_TABLE_LENGTH;
1479 goto Exit;
1480 }
1481
1482 /* Validate checksum */
1483
1484 (void) ApIsValidChecksum (LocalTable);
1485
1486 Exit:
1487 fclose (TableFile);
1488 *Table = LocalTable;
1489 return (Status);
1490 }
1491
1492
1493 /******************************************************************************
1494 *
1495 * FUNCTION: OslGetCustomizedTable
1496 *
1497 * PARAMETERS: Pathname - Directory to find Linux customized table
1498 * Signature - ACPI Signature for desired table. Must be
1499 * a null terminated 4-character string.
1500 * Instance - Multiple table support for SSDT/UEFI (0...n)
1501 * Must be 0 for other tables.
1502 * Table - Where a pointer to the table is returned
1503 * Address - Where the table physical address is returned
1504 *
1505 * RETURN: Status; Table buffer is returned if AE_OK.
1506 * AE_LIMIT: Instance is beyond valid limit
1507 * AE_NOT_FOUND: A table with the signature was not found
1508 *
1509 * DESCRIPTION: Get an OS customized table.
1510 *
1511 *****************************************************************************/
1512
1513 static ACPI_STATUS
OslGetCustomizedTable(char * Pathname,char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)1514 OslGetCustomizedTable (
1515 char *Pathname,
1516 char *Signature,
1517 UINT32 Instance,
1518 ACPI_TABLE_HEADER **Table,
1519 ACPI_PHYSICAL_ADDRESS *Address)
1520 {
1521 void *TableDir;
1522 UINT32 CurrentInstance = 0;
1523 char TempName[ACPI_NAMESEG_SIZE];
1524 char TableFilename[PATH_MAX];
1525 char *Filename;
1526 ACPI_STATUS Status;
1527
1528
1529 /* Open the directory for customized tables */
1530
1531 TableDir = AcpiOsOpenDirectory (Pathname, "*", REQUEST_FILE_ONLY);
1532 if (!TableDir)
1533 {
1534 return (OslGetLastStatus (AE_NOT_FOUND));
1535 }
1536
1537 /* Attempt to find the table in the directory */
1538
1539 while ((Filename = AcpiOsGetNextFilename (TableDir)))
1540 {
1541 /* Ignore meaningless files */
1542
1543 if (!ACPI_COMPARE_NAMESEG (Filename, Signature))
1544 {
1545 continue;
1546 }
1547
1548 /* Extract table name and instance number */
1549
1550 Status = OslTableNameFromFile (Filename, TempName, &CurrentInstance);
1551
1552 /* Ignore meaningless files */
1553
1554 if (ACPI_FAILURE (Status) || CurrentInstance != Instance)
1555 {
1556 continue;
1557 }
1558
1559 /* Create the table pathname */
1560
1561 if (Instance != 0)
1562 {
1563 snprintf (TableFilename, sizeof(TableFilename), "%s/%4.4s%d",
1564 Pathname, TempName, Instance);
1565 }
1566 else
1567 {
1568 snprintf (TableFilename, sizeof(TableFilename), "%s/%4.4s",
1569 Pathname, TempName);
1570 }
1571 break;
1572 }
1573
1574 AcpiOsCloseDirectory (TableDir);
1575
1576 if (!Filename)
1577 {
1578 return (AE_LIMIT);
1579 }
1580
1581 /* There is no physical address saved for customized tables, use zero */
1582
1583 *Address = 0;
1584 Status = OslReadTableFromFile (TableFilename, 0, Table);
1585
1586 return (Status);
1587 }
1588