1 /******************************************************************************
2 *
3 * Module Name: osbsdtbl - BSD 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 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__)
47 #include <kenv.h>
48 #endif
49 #include <unistd.h>
50 #include <sys/param.h>
51 #include <sys/sysctl.h>
52
53
54 #define _COMPONENT ACPI_OS_SERVICES
55 ACPI_MODULE_NAME ("osbsdtbl")
56
57
58 /* Local prototypes */
59
60 static ACPI_STATUS
61 OslTableInitialize (
62 void);
63
64 static ACPI_STATUS
65 OslMapTable (
66 ACPI_SIZE Address,
67 char *Signature,
68 ACPI_TABLE_HEADER **Table);
69
70 static ACPI_STATUS
71 OslAddTablesToList (
72 void);
73
74 static ACPI_STATUS
75 OslGetTableViaRoot (
76 char *Signature,
77 UINT32 Instance,
78 ACPI_TABLE_HEADER **Table,
79 ACPI_PHYSICAL_ADDRESS *Address);
80
81
82 /* Hints for RSDP */
83 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
84 #define SYSTEM_KENV "hint.acpi.0.rsdp"
85 #define SYSTEM_SYSCTL "machdep.acpi_root"
86 #elif defined(__NetBSD__)
87 #define SYSTEM_SYSCTL "hw.acpi.root"
88 #endif
89
90 /* Initialization flags */
91
92 UINT8 Gbl_TableListInitialized = FALSE;
93 UINT8 Gbl_MainTableObtained = FALSE;
94
95 /* Local copies of main ACPI tables */
96
97 ACPI_TABLE_RSDP Gbl_Rsdp;
98 ACPI_TABLE_FADT *Gbl_Fadt;
99 ACPI_TABLE_RSDT *Gbl_Rsdt;
100 ACPI_TABLE_XSDT *Gbl_Xsdt;
101
102 /* Fadt address */
103
104 ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress;
105
106 /* Revision of RSD PTR */
107
108 UINT8 Gbl_Revision;
109
110 /* List of information about obtained ACPI tables */
111
112 typedef struct table_info
113 {
114 struct table_info *Next;
115 char Signature[4];
116 UINT32 Instance;
117 ACPI_PHYSICAL_ADDRESS Address;
118
119 } OSL_TABLE_INFO;
120
121 OSL_TABLE_INFO *Gbl_TableListHead = NULL;
122
123
124 /******************************************************************************
125 *
126 * FUNCTION: AcpiOsGetTableByAddress
127 *
128 * PARAMETERS: Address - Physical address of the ACPI table
129 * Table - Where a pointer to the table is returned
130 *
131 * RETURN: Status; Table buffer is returned if AE_OK.
132 * AE_NOT_FOUND: A valid table was not found at the address
133 *
134 * DESCRIPTION: Get an ACPI table via a physical memory address.
135 *
136 *****************************************************************************/
137
138 ACPI_STATUS
AcpiOsGetTableByAddress(ACPI_PHYSICAL_ADDRESS Address,ACPI_TABLE_HEADER ** Table)139 AcpiOsGetTableByAddress (
140 ACPI_PHYSICAL_ADDRESS Address,
141 ACPI_TABLE_HEADER **Table)
142 {
143 ACPI_TABLE_HEADER *MappedTable;
144 ACPI_TABLE_HEADER *LocalTable;
145 ACPI_STATUS Status;
146
147
148 /* Validate the input physical address to avoid program crash */
149
150 if (Address < ACPI_HI_RSDP_WINDOW_BASE)
151 {
152 fprintf (stderr, "Invalid table address: 0x%8.8X%8.8X\n",
153 ACPI_FORMAT_UINT64 (Address));
154 return (AE_BAD_ADDRESS);
155 }
156
157 /* Map the table and validate it */
158
159 Status = OslMapTable (Address, NULL, &MappedTable);
160 if (ACPI_FAILURE (Status))
161 {
162 return (Status);
163 }
164
165 /* Copy table to local buffer and return it */
166
167 LocalTable = calloc (1, MappedTable->Length);
168 if (!LocalTable)
169 {
170 AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
171 return (AE_NO_MEMORY);
172 }
173
174 memcpy (LocalTable, MappedTable, MappedTable->Length);
175 AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
176
177 *Table = LocalTable;
178 return (AE_OK);
179 }
180
181
182 /******************************************************************************
183 *
184 * FUNCTION: AcpiOsGetTableByName
185 *
186 * PARAMETERS: Signature - ACPI Signature for desired table. Must be
187 * a null terminated 4-character string.
188 * Instance - Multiple table support for SSDT/UEFI (0...n)
189 * Must be 0 for other tables.
190 * Table - Where a pointer to the table is returned
191 * Address - Where the table physical address is returned
192 *
193 * RETURN: Status; Table buffer and physical address returned if AE_OK.
194 * AE_LIMIT: Instance is beyond valid limit
195 * AE_NOT_FOUND: A table with the signature was not found
196 *
197 * NOTE: Assumes the input signature is uppercase.
198 *
199 *****************************************************************************/
200
201 ACPI_STATUS
AcpiOsGetTableByName(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)202 AcpiOsGetTableByName (
203 char *Signature,
204 UINT32 Instance,
205 ACPI_TABLE_HEADER **Table,
206 ACPI_PHYSICAL_ADDRESS *Address)
207 {
208 ACPI_STATUS Status;
209
210
211 /* Instance is only valid for SSDT/UEFI tables */
212
213 if (Instance &&
214 !ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_SSDT) &&
215 !ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_UEFI))
216 {
217 return (AE_LIMIT);
218 }
219
220 /* Initialize main tables */
221
222 Status = OslTableInitialize ();
223 if (ACPI_FAILURE (Status))
224 {
225 return (Status);
226 }
227
228 /*
229 * If one of the main ACPI tables was requested (RSDT/XSDT/FADT),
230 * simply return it immediately.
231 */
232 if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT))
233 {
234 if (!Gbl_Revision)
235 {
236 return (AE_NOT_FOUND);
237 }
238
239 *Address = Gbl_Rsdp.XsdtPhysicalAddress;
240 *Table = (ACPI_TABLE_HEADER *) Gbl_Xsdt;
241 return (AE_OK);
242 }
243
244 if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT))
245 {
246 if (!Gbl_Rsdp.RsdtPhysicalAddress)
247 {
248 return (AE_NOT_FOUND);
249 }
250
251 *Address = Gbl_Rsdp.RsdtPhysicalAddress;
252 *Table = (ACPI_TABLE_HEADER *) Gbl_Rsdt;
253 return (AE_OK);
254 }
255
256 if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FADT))
257 {
258 *Address = Gbl_FadtAddress;
259 *Table = (ACPI_TABLE_HEADER *) Gbl_Fadt;
260 return (AE_OK);
261 }
262
263 /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
264
265 Status = OslGetTableViaRoot (Signature, Instance, Table, Address);
266 if (ACPI_FAILURE (Status))
267 {
268 return (Status);
269 }
270
271 return (AE_OK);
272 }
273
274
275 /******************************************************************************
276 *
277 * FUNCTION: AcpiOsGetTableByIndex
278 *
279 * PARAMETERS: Index - Which table to get
280 * Table - Where a pointer to the table is returned
281 * Instance - Where a pointer to the table instance no. is
282 * returned
283 * Address - Where the table physical address is returned
284 *
285 * RETURN: Status; Table buffer and physical address returned if AE_OK.
286 * AE_LIMIT: Index is beyond valid limit
287 *
288 * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
289 * AE_LIMIT when an invalid index is reached. Index is not
290 * necessarily an index into the RSDT/XSDT.
291 *
292 *****************************************************************************/
293
294 ACPI_STATUS
AcpiOsGetTableByIndex(UINT32 Index,ACPI_TABLE_HEADER ** Table,UINT32 * Instance,ACPI_PHYSICAL_ADDRESS * Address)295 AcpiOsGetTableByIndex (
296 UINT32 Index,
297 ACPI_TABLE_HEADER **Table,
298 UINT32 *Instance,
299 ACPI_PHYSICAL_ADDRESS *Address)
300 {
301 OSL_TABLE_INFO *Info;
302 ACPI_STATUS Status;
303 UINT32 i;
304
305
306 /* Initialize main tables */
307
308 Status = OslTableInitialize ();
309 if (ACPI_FAILURE (Status))
310 {
311 return (Status);
312 }
313
314 /* Add all tables to list */
315
316 Status = OslAddTablesToList ();
317 if (ACPI_FAILURE (Status))
318 {
319 return (Status);
320 }
321
322 /* Validate Index */
323
324 if (Index >= Gbl_TableListHead->Instance)
325 {
326 return (AE_LIMIT);
327 }
328
329 /* Point to the table list entry specified by the Index argument */
330
331 Info = Gbl_TableListHead;
332 for (i = 0; i <= Index; i++)
333 {
334 Info = Info->Next;
335 }
336
337 /* Now we can just get the table via the address or name */
338
339 if (Info->Address)
340 {
341 Status = AcpiOsGetTableByAddress (Info->Address, Table);
342 if (ACPI_SUCCESS (Status))
343 {
344 *Address = Info->Address;
345 }
346 }
347 else
348 {
349 Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
350 Table, Address);
351 }
352
353 if (ACPI_SUCCESS (Status))
354 {
355 *Instance = Info->Instance;
356 }
357 return (Status);
358 }
359
360
361 /******************************************************************************
362 *
363 * FUNCTION: OslTableInitialize
364 *
365 * PARAMETERS: None
366 *
367 * RETURN: Status
368 *
369 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
370 * local variables. Main ACPI tables include RSDP, FADT, RSDT,
371 * and/or XSDT.
372 *
373 *****************************************************************************/
374
375 static ACPI_STATUS
OslTableInitialize(void)376 OslTableInitialize (
377 void)
378 {
379 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
380 char Buffer[32];
381 #endif
382 ACPI_TABLE_HEADER *MappedTable;
383 UINT8 *TableAddress;
384 UINT8 *RsdpAddress;
385 ACPI_PHYSICAL_ADDRESS RsdpBase;
386 ACPI_SIZE RsdpSize;
387 ACPI_STATUS Status;
388 u_long Address = 0;
389 #if defined(SYSTEM_SYSCTL)
390 size_t Length = sizeof (Address);
391 #endif
392
393
394 /* Get main ACPI tables from memory on first invocation of this function */
395
396 if (Gbl_MainTableObtained)
397 {
398 return (AE_OK);
399 }
400
401 /* Attempt to use kenv or sysctl to find RSD PTR record. */
402
403 if (Gbl_RsdpBase)
404 {
405 Address = Gbl_RsdpBase;
406 }
407 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__)
408 else if (kenv (KENV_GET, SYSTEM_KENV, Buffer, sizeof (Buffer)) > 0)
409 {
410 Address = strtoul (Buffer, NULL, 0);
411 }
412 #endif
413 #if defined(SYSTEM_SYSCTL)
414 if (!Address)
415 {
416 if (sysctlbyname (SYSTEM_SYSCTL, &Address, &Length, NULL, 0) != 0)
417 {
418 Address = 0;
419 }
420 }
421 #endif
422 if (Address)
423 {
424 RsdpBase = Address;
425 RsdpSize = sizeof (Gbl_Rsdp);
426 }
427 else
428 {
429 RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
430 RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
431 }
432
433 /* Get RSDP from memory */
434
435 RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
436 if (!RsdpAddress)
437 {
438 return (AE_BAD_ADDRESS);
439 }
440
441 /* Search low memory for the RSDP */
442
443 TableAddress = AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize);
444 if (!TableAddress)
445 {
446 AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
447 return (AE_ERROR);
448 }
449
450 memcpy (&Gbl_Rsdp, TableAddress, sizeof (Gbl_Rsdp));
451 AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
452
453 /* Get XSDT from memory */
454
455 if (Gbl_Rsdp.Revision)
456 {
457 Status = OslMapTable (Gbl_Rsdp.XsdtPhysicalAddress,
458 ACPI_SIG_XSDT, &MappedTable);
459 if (ACPI_FAILURE (Status))
460 {
461 return (Status);
462 }
463
464 Gbl_Revision = 2;
465 Gbl_Xsdt = calloc (1, MappedTable->Length);
466 if (!Gbl_Xsdt)
467 {
468 fprintf (stderr,
469 "XSDT: Could not allocate buffer for table of length %X\n",
470 MappedTable->Length);
471 AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
472 return (AE_NO_MEMORY);
473 }
474
475 memcpy (Gbl_Xsdt, MappedTable, MappedTable->Length);
476 AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
477 }
478
479 /* Get RSDT from memory */
480
481 if (Gbl_Rsdp.RsdtPhysicalAddress)
482 {
483 Status = OslMapTable (Gbl_Rsdp.RsdtPhysicalAddress,
484 ACPI_SIG_RSDT, &MappedTable);
485 if (ACPI_FAILURE (Status))
486 {
487 return (Status);
488 }
489
490 Gbl_Rsdt = calloc (1, MappedTable->Length);
491 if (!Gbl_Rsdt)
492 {
493 fprintf (stderr,
494 "RSDT: Could not allocate buffer for table of length %X\n",
495 MappedTable->Length);
496 AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
497 return (AE_NO_MEMORY);
498 }
499
500 memcpy (Gbl_Rsdt, MappedTable, MappedTable->Length);
501 AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
502 }
503
504 /* Get FADT from memory */
505
506 if (Gbl_Revision)
507 {
508 Gbl_FadtAddress = Gbl_Xsdt->TableOffsetEntry[0];
509 }
510 else
511 {
512 Gbl_FadtAddress = Gbl_Rsdt->TableOffsetEntry[0];
513 }
514
515 if (!Gbl_FadtAddress)
516 {
517 fprintf(stderr, "FADT: Table could not be found\n");
518 return (AE_ERROR);
519 }
520
521 Status = OslMapTable (Gbl_FadtAddress, ACPI_SIG_FADT, &MappedTable);
522 if (ACPI_FAILURE (Status))
523 {
524 return (Status);
525 }
526
527 Gbl_Fadt = calloc (1, MappedTable->Length);
528 if (!Gbl_Fadt)
529 {
530 fprintf (stderr,
531 "FADT: Could not allocate buffer for table of length %X\n",
532 MappedTable->Length);
533 AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
534 return (AE_NO_MEMORY);
535 }
536
537 memcpy (Gbl_Fadt, MappedTable, MappedTable->Length);
538 AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
539 Gbl_MainTableObtained = TRUE;
540 return (AE_OK);
541 }
542
543
544 /******************************************************************************
545 *
546 * FUNCTION: OslGetTableViaRoot
547 *
548 * PARAMETERS: Signature - ACPI Signature for common table. Must be
549 * a null terminated 4-character string.
550 * Instance - Multiple table support for SSDT/UEFI (0...n)
551 * Must be 0 for other tables.
552 * Table - Where a pointer to the table is returned
553 * Address - Where the table physical address is returned
554 *
555 * RETURN: Status; Table buffer and physical address returned if AE_OK.
556 * AE_LIMIT: Instance is beyond valid limit
557 * AE_NOT_FOUND: A table with the signature was not found
558 *
559 * DESCRIPTION: Get an ACPI table via the root table (RSDT/XSDT)
560 *
561 * NOTE: Assumes the input signature is uppercase.
562 *
563 *****************************************************************************/
564
565 static ACPI_STATUS
OslGetTableViaRoot(char * Signature,UINT32 Instance,ACPI_TABLE_HEADER ** Table,ACPI_PHYSICAL_ADDRESS * Address)566 OslGetTableViaRoot (
567 char *Signature,
568 UINT32 Instance,
569 ACPI_TABLE_HEADER **Table,
570 ACPI_PHYSICAL_ADDRESS *Address)
571 {
572 ACPI_TABLE_HEADER *LocalTable = NULL;
573 ACPI_TABLE_HEADER *MappedTable = NULL;
574 UINT8 NumberOfTables;
575 UINT32 CurrentInstance = 0;
576 ACPI_PHYSICAL_ADDRESS TableAddress = 0;
577 ACPI_STATUS Status;
578 UINT32 i;
579
580
581 /* DSDT and FACS address must be extracted from the FADT */
582
583 if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT) ||
584 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
585 {
586 /*
587 * Get the appropriate address, either 32-bit or 64-bit. Be very
588 * careful about the FADT length and validate table addresses.
589 * Note: The 64-bit addresses have priority.
590 */
591 if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT))
592 {
593 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
594 Gbl_Fadt->XDsdt)
595 {
596 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
597 }
598 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
599 Gbl_Fadt->Dsdt)
600 {
601 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
602 }
603 }
604 else /* FACS */
605 {
606 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
607 Gbl_Fadt->XFacs)
608 {
609 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
610 }
611 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
612 Gbl_Fadt->Facs)
613 {
614 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
615 }
616 }
617 }
618 else /* Case for a normal ACPI table */
619 {
620 if (Gbl_Revision)
621 {
622 NumberOfTables =
623 (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
624 / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
625 }
626 else /* Use RSDT if XSDT is not available */
627 {
628 NumberOfTables =
629 (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
630 / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
631 }
632
633 /* Search RSDT/XSDT for the requested table */
634
635 for (i = 0; i < NumberOfTables; i++)
636 {
637 if (Gbl_Revision)
638 {
639 TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
640 }
641 else
642 {
643 TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
644 }
645
646 MappedTable = AcpiOsMapMemory (TableAddress, sizeof (*MappedTable));
647 if (!MappedTable)
648 {
649 return (AE_BAD_ADDRESS);
650 }
651
652 /* Does this table match the requested signature? */
653
654 if (ACPI_COMPARE_NAMESEG (MappedTable->Signature, Signature))
655 {
656
657 /* Match table instance (for SSDT/UEFI tables) */
658
659 if (CurrentInstance == Instance)
660 {
661 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
662 break;
663 }
664
665 CurrentInstance++;
666 }
667
668 AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
669 TableAddress = 0;
670 }
671 }
672
673 if (!TableAddress)
674 {
675 if (CurrentInstance)
676 {
677 return (AE_LIMIT);
678 }
679 return (AE_NOT_FOUND);
680 }
681
682 /* Now we can get the requested table */
683
684 Status = OslMapTable (TableAddress, Signature, &MappedTable);
685 if (ACPI_FAILURE (Status))
686 {
687 return (Status);
688 }
689
690 /* Copy table to local buffer and return it */
691
692 LocalTable = calloc (1, MappedTable->Length);
693 if (!LocalTable)
694 {
695 AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
696 return (AE_NO_MEMORY);
697 }
698
699 memcpy (LocalTable, MappedTable, MappedTable->Length);
700 AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
701 *Table = LocalTable;
702 *Address = TableAddress;
703 return (AE_OK);
704 }
705
706
707 /******************************************************************************
708 *
709 * FUNCTION: OslAddTablesToList
710 *
711 * PARAMETERS: None
712 *
713 * RETURN: Status; Table list is initialized if AE_OK.
714 *
715 * DESCRIPTION: Add ACPI tables to the table list.
716 *
717 *****************************************************************************/
718
719 static ACPI_STATUS
OslAddTablesToList(void)720 OslAddTablesToList(
721 void)
722 {
723 ACPI_PHYSICAL_ADDRESS TableAddress;
724 OSL_TABLE_INFO *Info = NULL;
725 OSL_TABLE_INFO *NewInfo;
726 ACPI_TABLE_HEADER *Table;
727 UINT8 Instance;
728 UINT8 NumberOfTables;
729 int i;
730
731
732 /* Initialize the table list on first invocation */
733
734 if (Gbl_TableListInitialized)
735 {
736 return (AE_OK);
737 }
738
739 /* Add mandatory tables to global table list first */
740
741 for (i = 0; i < 4; i++)
742 {
743 NewInfo = calloc (1, sizeof (*NewInfo));
744 if (!NewInfo)
745 {
746 return (AE_NO_MEMORY);
747 }
748
749 switch (i) {
750 case 0:
751
752 Gbl_TableListHead = Info = NewInfo;
753 continue;
754
755 case 1:
756
757 ACPI_COPY_NAMESEG (NewInfo->Signature,
758 Gbl_Revision ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
759 break;
760
761 case 2:
762
763 ACPI_COPY_NAMESEG (NewInfo->Signature, ACPI_SIG_FACS);
764 break;
765
766 default:
767
768 ACPI_COPY_NAMESEG (NewInfo->Signature, ACPI_SIG_DSDT);
769
770 }
771
772 Info->Next = NewInfo;
773 Info = NewInfo;
774 Gbl_TableListHead->Instance++;
775 }
776
777 /* Add normal tables from RSDT/XSDT to global list */
778
779 if (Gbl_Revision)
780 {
781 NumberOfTables =
782 (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
783 / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
784 }
785 else
786 {
787 NumberOfTables =
788 (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
789 / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
790 }
791
792 for (i = 0; i < NumberOfTables; i++)
793 {
794 if (Gbl_Revision)
795 {
796 TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
797 }
798 else
799 {
800 TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
801 }
802
803 Table = AcpiOsMapMemory (TableAddress, sizeof (*Table));
804 if (!Table)
805 {
806 return (AE_BAD_ADDRESS);
807 }
808
809 Instance = 0;
810 NewInfo = Gbl_TableListHead;
811 while (NewInfo->Next != NULL)
812 {
813 NewInfo = NewInfo->Next;
814 if (ACPI_COMPARE_NAMESEG (Table->Signature, NewInfo->Signature))
815 {
816 Instance++;
817 }
818 }
819
820 NewInfo = calloc (1, sizeof (*NewInfo));
821 if (!NewInfo)
822 {
823 AcpiOsUnmapMemory (Table, sizeof (*Table));
824 return (AE_NO_MEMORY);
825 }
826
827 ACPI_COPY_NAMESEG (NewInfo->Signature, Table->Signature);
828
829 AcpiOsUnmapMemory (Table, sizeof (*Table));
830
831 NewInfo->Instance = Instance;
832 NewInfo->Address = TableAddress;
833 Info->Next = NewInfo;
834 Info = NewInfo;
835 Gbl_TableListHead->Instance++;
836 }
837
838 Gbl_TableListInitialized = TRUE;
839 return (AE_OK);
840 }
841
842
843 /******************************************************************************
844 *
845 * FUNCTION: OslMapTable
846 *
847 * PARAMETERS: Address - Address of the table in memory
848 * Signature - Optional ACPI Signature for desired table.
849 * Null terminated 4-character string.
850 * Table - Where a pointer to the mapped table is
851 * returned
852 *
853 * RETURN: Status; Mapped table is returned if AE_OK.
854 *
855 * DESCRIPTION: Map entire ACPI table into caller's address space. Also
856 * validates the table and checksum.
857 *
858 *****************************************************************************/
859
860 static ACPI_STATUS
OslMapTable(ACPI_SIZE Address,char * Signature,ACPI_TABLE_HEADER ** Table)861 OslMapTable (
862 ACPI_SIZE Address,
863 char *Signature,
864 ACPI_TABLE_HEADER **Table)
865 {
866 ACPI_TABLE_HEADER *MappedTable;
867 UINT32 Length;
868
869
870 /* Map the header so we can get the table length */
871
872 MappedTable = AcpiOsMapMemory (Address, sizeof (*MappedTable));
873 if (!MappedTable)
874 {
875 return (AE_BAD_ADDRESS);
876 }
877
878 /* Check if table is valid */
879
880 if (!ApIsValidHeader (MappedTable))
881 {
882 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
883 return (AE_BAD_HEADER);
884 }
885
886 /* If specified, signature must match */
887
888 if (Signature &&
889 !ACPI_COMPARE_NAMESEG (Signature, MappedTable->Signature))
890 {
891 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
892 return (AE_NOT_EXIST);
893 }
894
895 /* Map the entire table */
896
897 Length = MappedTable->Length;
898 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
899
900 MappedTable = AcpiOsMapMemory (Address, Length);
901 if (!MappedTable)
902 {
903 return (AE_BAD_ADDRESS);
904 }
905
906 (void) ApIsValidChecksum (MappedTable);
907
908 *Table = MappedTable;
909
910 return (AE_OK);
911 }
912