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