]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
Add support of ACPI Table Version 3.0 in implementation of EFI_ACPI_TABLE_PROTOCOL...
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / AcpiTableDxe / AcpiTableProtocol.c
1 /** @file
2 ACPI Table Protocol Implementation
3
4 Copyright (c) 2006, 2008, 2009, Intel Corporation<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 //
16 // Includes
17 //
18 #include "AcpiTable.h"
19
20
21 /**
22 This function adds an ACPI table to the table list. It will detect FACS and
23 allocate the correct type of memory and properly align the table.
24
25 @param AcpiTableInstance Instance of the protocol.
26 @param Table Table to add.
27 @param Checksum Does the table require checksumming.
28 @param Version The version of the list to add the table to.
29 @param Handle Pointer for returning the handle.
30
31 @return EFI_SUCCESS The function completed successfully.
32 @return EFI_OUT_OF_RESOURCES Could not allocate a required resource.
33 @return EFI_ABORTED The table is a duplicate of a table that is required
34 to be unique.
35
36 **/
37 EFI_STATUS
38 AddTableToList (
39 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
40 IN VOID *Table,
41 IN BOOLEAN Checksum,
42 IN EFI_ACPI_TABLE_VERSION Version,
43 OUT UINTN *Handle
44 );
45
46 /**
47 This function finds and removes the table specified by the handle.
48
49 @param AcpiTableInstance Instance of the protocol.
50 @param Version Bitmask of which versions to remove.
51 @param Handle Table to remove.
52
53 @return EFI_SUCCESS The function completed successfully.
54 @return EFI_ABORTED An error occurred.
55 @return EFI_NOT_FOUND Handle not found in table list.
56
57 **/
58 EFI_STATUS
59 RemoveTableFromList (
60 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
61 IN EFI_ACPI_TABLE_VERSION Version,
62 IN UINTN Handle
63 );
64
65 /**
66 This function calculates and updates an UINT8 checksum.
67
68 @param Buffer Pointer to buffer to checksum
69 @param Size Number of bytes to checksum
70 @param ChecksumOffset Offset to place the checksum result in
71
72 @return EFI_SUCCESS The function completed successfully.
73
74 **/
75 EFI_STATUS
76 AcpiPlatformChecksum (
77 IN VOID *Buffer,
78 IN UINTN Size,
79 IN UINTN ChecksumOffset
80 );
81
82 /**
83 Checksum all versions of the common tables, RSDP, RSDT, XSDT.
84
85 @param AcpiTableInstance Protocol instance private data.
86
87 @return EFI_SUCCESS The function completed successfully.
88
89 **/
90 EFI_STATUS
91 ChecksumCommonTables (
92 IN OUT EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance
93 );
94
95 //
96 // Protocol function implementations.
97 //
98
99 /**
100 This function adds, removes, or updates ACPI tables. If the address is not
101 null and the handle value is null, the table is added. If both the address and
102 handle are not null, the table at handle is updated with the table at address.
103 If the address is null and the handle is not, the table at handle is deleted.
104
105 @param AcpiTableInstance Instance of the protocol.
106 @param Table Pointer to a table.
107 @param Checksum Boolean indicating if the checksum should be calculated.
108 @param Version Version(s) to set.
109 @param Handle Handle of the table.
110
111 @return EFI_SUCCESS The function completed successfully.
112 @return EFI_INVALID_PARAMETER Both the Table and *Handle were NULL.
113 @return EFI_ABORTED Could not complete the desired request.
114
115 **/
116 EFI_STATUS
117 EFIAPI
118 SetAcpiTable (
119 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
120 IN VOID *Table OPTIONAL,
121 IN BOOLEAN Checksum,
122 IN EFI_ACPI_TABLE_VERSION Version,
123 IN OUT UINTN *Handle
124 )
125 {
126 UINTN SavedHandle;
127 EFI_STATUS Status;
128
129 //
130 // Check for invalid input parameters
131 //
132 ASSERT (Handle);
133
134 //
135 // Initialize locals
136 //
137 //
138 // Determine desired action
139 //
140 if (*Handle == 0) {
141 if (Table == NULL) {
142 //
143 // Invalid parameter combination
144 //
145 return EFI_INVALID_PARAMETER;
146 } else {
147 //
148 // Add table
149 //
150 Status = AddTableToList (AcpiTableInstance, Table, Checksum, Version, Handle);
151 }
152 } else {
153 if (Table != NULL) {
154 //
155 // Update table
156 //
157 //
158 // Delete the table list entry
159 //
160 Status = RemoveTableFromList (AcpiTableInstance, Version, *Handle);
161 if (EFI_ERROR (Status)) {
162 //
163 // Should not get an error here ever, but abort if we do.
164 //
165 return EFI_ABORTED;
166 }
167 //
168 // Set the handle to replace the table at the same handle
169 //
170 SavedHandle = AcpiTableInstance->CurrentHandle;
171 AcpiTableInstance->CurrentHandle = *Handle;
172
173 //
174 // Add the table
175 //
176 Status = AddTableToList (AcpiTableInstance, Table, Checksum, Version, Handle);
177
178 //
179 // Restore the saved current handle
180 //
181 AcpiTableInstance->CurrentHandle = SavedHandle;
182 } else {
183 //
184 // Delete table
185 //
186 Status = RemoveTableFromList (AcpiTableInstance, Version, *Handle);
187 }
188 }
189
190 if (EFI_ERROR (Status)) {
191 //
192 // Should not get an error here ever, but abort if we do.
193 //
194 return EFI_ABORTED;
195 }
196 //
197 // Done
198 //
199 return EFI_SUCCESS;
200 }
201
202 /**
203 This function publishes the specified versions of the ACPI tables by
204 installing EFI configuration table entries for them. Any combination of
205 table versions can be published.
206
207 @param AcpiTableInstance Instance of the protocol.
208 @param Version Version(s) to publish.
209
210 @return EFI_SUCCESS The function completed successfully.
211 @return EFI_ABORTED The function could not complete successfully.
212
213 **/
214 EFI_STATUS
215 EFIAPI
216 PublishTables (
217 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
218 IN EFI_ACPI_TABLE_VERSION Version
219 )
220 {
221 EFI_STATUS Status;
222 UINT32 *CurrentRsdtEntry;
223 VOID *CurrentXsdtEntry;
224 UINT64 Buffer64;
225
226 //
227 // Reorder tables as some operating systems don't seem to find the
228 // FADT correctly if it is not in the first few entries
229 //
230
231 //
232 // Add FADT as the first entry
233 //
234 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
235 CurrentRsdtEntry = (UINT32 *) ((UINT8 *) AcpiTableInstance->Rsdt1 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
236 *CurrentRsdtEntry = (UINT32) (UINTN) AcpiTableInstance->Fadt1;
237 }
238 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
239 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
240 CurrentRsdtEntry = (UINT32 *) ((UINT8 *) AcpiTableInstance->Rsdt3 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
241 *CurrentRsdtEntry = (UINT32) (UINTN) AcpiTableInstance->Fadt3;
242 CurrentXsdtEntry = (VOID *) ((UINT8 *) AcpiTableInstance->Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
243 //
244 // Add entry to XSDT, XSDT expects 64 bit pointers, but
245 // the table pointers in XSDT are not aligned on 8 byte boundary.
246 //
247 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Fadt3;
248 CopyMem (
249 CurrentXsdtEntry,
250 &Buffer64,
251 sizeof (UINT64)
252 );
253 }
254
255 //
256 // Do checksum again because Dsdt/Xsdt is updated.
257 //
258 ChecksumCommonTables (AcpiTableInstance);
259
260 //
261 // Add the RSD_PTR to the system table and store that we have installed the
262 // tables.
263 //
264 if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) &&
265 !AcpiTableInstance->TablesInstalled1) {
266 Status = gBS->InstallConfigurationTable (&gEfiAcpi10TableGuid, AcpiTableInstance->Rsdp1);
267 if (EFI_ERROR (Status)) {
268 return EFI_ABORTED;
269 }
270
271 AcpiTableInstance->TablesInstalled1 = TRUE;
272 }
273
274 if (((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
275 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) &&
276 !AcpiTableInstance->TablesInstalled3) {
277 Status = gBS->InstallConfigurationTable (&gEfiAcpiTableGuid, AcpiTableInstance->Rsdp3);
278 if (EFI_ERROR (Status)) {
279 return EFI_ABORTED;
280 }
281
282 AcpiTableInstance->TablesInstalled3= TRUE;
283 }
284
285 return EFI_SUCCESS;
286 }
287
288
289 /**
290 Installs an ACPI table into the RSDT/XSDT.
291
292 @param This Protocol instance pointer.
293 @param AcpiTableBuffer A pointer to a buffer containing the ACPI table to be installed.
294 @param AcpiTableBufferSize Specifies the size, in bytes, of the AcpiTableBuffer buffer.
295 @param TableKey Reurns a key to refer to the ACPI table.
296
297 @return EFI_SUCCESS The table was successfully inserted.
298 @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableKey is NULL, or AcpiTableBufferSize
299 and the size field embedded in the ACPI table pointed to by AcpiTableBuffer
300 are not in sync.
301 @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
302
303 **/
304 EFI_STATUS
305 EFIAPI
306 InstallAcpiTable (
307 IN CONST EFI_ACPI_TABLE_PROTOCOL *This,
308 IN CONST VOID *AcpiTableBuffer,
309 IN UINTN AcpiTableBufferSize,
310 OUT UINTN *TableKey
311 )
312 {
313 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance;
314 EFI_STATUS Status;
315 VOID *AcpiTableBufferConst;
316
317 //
318 // Check for invalid input parameters
319 //
320 if ((AcpiTableBuffer == NULL) || (TableKey == NULL)
321 || (((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer)->Length != AcpiTableBufferSize)) {
322 return EFI_INVALID_PARAMETER;
323 }
324
325 //
326 // Get the instance of the ACPI table protocol
327 //
328 AcpiTableInstance = EFI_ACPI_TABLE_INSTANCE_FROM_THIS (This);
329
330 //
331 // Install the ACPI table
332 //
333 AcpiTableBufferConst = AllocateCopyPool (AcpiTableBufferSize,AcpiTableBuffer);
334 *TableKey = 0;
335 Status = SetAcpiTable (
336 AcpiTableInstance,
337 AcpiTableBufferConst,
338 FALSE,
339 EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0,
340 TableKey
341 );
342 if (!EFI_ERROR (Status)) {
343 Status = PublishTables (
344 AcpiTableInstance,
345 EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0
346 );
347 }
348 FreePool (AcpiTableBufferConst);
349
350 return Status;
351 }
352
353
354 /**
355 Removes an ACPI table from the RSDT/XSDT.
356
357 @param This Protocol instance pointer.
358 @param TableKey Specifies the table to uninstall. The key was returned from InstallAcpiTable().
359
360 @return EFI_SUCCESS The table was successfully uninstalled.
361 @return EFI_NOT_FOUND TableKey does not refer to a valid key for a table entry.
362
363 **/
364 EFI_STATUS
365 EFIAPI
366 UninstallAcpiTable (
367 IN CONST EFI_ACPI_TABLE_PROTOCOL *This,
368 IN UINTN TableKey
369 )
370 {
371 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance;
372 EFI_STATUS Status;
373
374 //
375 // Get the instance of the ACPI table protocol
376 //
377 AcpiTableInstance = EFI_ACPI_TABLE_INSTANCE_FROM_THIS (This);
378
379 //
380 // Uninstall the ACPI table
381 //
382 Status = SetAcpiTable (
383 AcpiTableInstance,
384 NULL,
385 FALSE,
386 EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0,
387 &TableKey
388 );
389 if (!EFI_ERROR (Status)) {
390 Status = PublishTables (
391 AcpiTableInstance,
392 EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0
393 );
394 }
395
396 if (EFI_ERROR (Status)) {
397 return EFI_NOT_FOUND;
398 } else {
399 return EFI_SUCCESS;
400 }
401 }
402
403
404 /**
405 This function adds an ACPI table to the table list. It will detect FACS and
406 allocate the correct type of memory and properly align the table.
407
408 @param AcpiTableInstance Instance of the protocol.
409 @param Table Table to add.
410 @param Checksum Does the table require checksumming.
411 @param Version The version of the list to add the table to.
412 @param Handle Pointer for returning the handle.
413
414 @return EFI_SUCCESS The function completed successfully.
415 @return EFI_OUT_OF_RESOURCES Could not allocate a required resource.
416 @return EFI_ABORTED The table is a duplicate of a table that is required
417 to be unique.
418
419 **/
420 EFI_STATUS
421 AddTableToList (
422 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
423 IN VOID *Table,
424 IN BOOLEAN Checksum,
425 IN EFI_ACPI_TABLE_VERSION Version,
426 OUT UINTN *Handle
427 )
428 {
429 EFI_STATUS Status;
430 EFI_ACPI_TABLE_LIST *CurrentTableList;
431 UINT32 CurrentTableSignature;
432 UINT32 CurrentTableSize;
433 UINT32 *CurrentRsdtEntry;
434 VOID *CurrentXsdtEntry;
435 UINT64 Buffer64;
436 BOOLEAN AddToRsdt;
437
438 //
439 // Check for invalid input parameters
440 //
441 ASSERT (AcpiTableInstance);
442 ASSERT (Table);
443 ASSERT (Handle);
444
445 //
446 // Init locals
447 //
448 AddToRsdt = TRUE;
449
450 //
451 // Create a new list entry
452 //
453 CurrentTableList = AllocatePool (sizeof (EFI_ACPI_TABLE_LIST));
454 ASSERT (CurrentTableList);
455
456 //
457 // Determine table type and size
458 //
459 CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table)->Signature;
460 CurrentTableSize = ((EFI_ACPI_COMMON_HEADER *) Table)->Length;
461
462 //
463 // Allocate a buffer for the table. All tables are allocated in the lower 32 bits of address space
464 // for backwards compatibility with ACPI 1.0 OS.
465 //
466 // This is done because ACPI 1.0 pointers are 32 bit values.
467 // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
468 // There is no architectural reason these should be below 4GB, it is purely
469 // for convenience of implementation that we force memory below 4GB.
470 //
471 CurrentTableList->PageAddress = 0xFFFFFFFF;
472 CurrentTableList->NumberOfPages = EFI_SIZE_TO_PAGES (CurrentTableSize);
473
474 //
475 // Allocation memory type depends on the type of the table
476 //
477 if (CurrentTableSignature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE ||
478 CurrentTableSignature == EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
479 //
480 // Allocate memory for the FACS. This structure must be aligned
481 // on a 64 byte boundary and must be ACPI NVS memory.
482 // Using AllocatePages should ensure that it is always aligned.
483 //
484 ASSERT ((EFI_PAGE_SIZE % 64) == 0);
485 Status = gBS->AllocatePages (
486 AllocateMaxAddress,
487 EfiACPIMemoryNVS,
488 CurrentTableList->NumberOfPages,
489 &CurrentTableList->PageAddress
490 );
491 } else {
492 //
493 // All other tables are ACPI reclaim memory, no alignment requirements.
494 //
495 Status = gBS->AllocatePages (
496 AllocateMaxAddress,
497 EfiACPIReclaimMemory,
498 CurrentTableList->NumberOfPages,
499 &CurrentTableList->PageAddress
500 );
501 }
502 //
503 // Check return value from memory alloc.
504 //
505 if (EFI_ERROR (Status)) {
506 gBS->FreePool (CurrentTableList);
507 return EFI_OUT_OF_RESOURCES;
508 }
509 //
510 // Update the table pointer with the allocated memory start
511 //
512 CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *) (UINTN) CurrentTableList->PageAddress;
513
514 //
515 // Initialize the table contents
516 //
517 CurrentTableList->Signature = EFI_ACPI_TABLE_LIST_SIGNATURE;
518 CopyMem (CurrentTableList->Table, Table, CurrentTableSize);
519 CurrentTableList->Handle = AcpiTableInstance->CurrentHandle++;
520 *Handle = CurrentTableList->Handle;
521 CurrentTableList->Version = Version;
522
523 //
524 // Update internal pointers if this is a required table. If it is a required
525 // table and a table of that type already exists, return an error.
526 //
527 // Calculate the checksum if the table is not FACS.
528 //
529 switch (CurrentTableSignature) {
530
531 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
532 //
533 // We don't add the FADT in the standard way because some
534 // OS expect the FADT to be early in the table list.
535 // So we always add it as the first element in the list.
536 //
537 AddToRsdt = FALSE;
538
539 //
540 // Check that the table has not been previously added.
541 //
542 if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Fadt1 != NULL) ||
543 ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiTableInstance->Fadt3 != NULL) ||
544 ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiTableInstance->Fadt3 != NULL)
545 ) {
546 gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
547 gBS->FreePool (CurrentTableList);
548 return EFI_ABORTED;
549 }
550 //
551 // Add the table to the appropriate table version
552 //
553 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
554 //
555 // Save a pointer to the table
556 //
557 AcpiTableInstance->Fadt1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table;
558
559 //
560 // Update pointers in FADT. If tables don't exist this will put NULL pointers there.
561 //
562 AcpiTableInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs1;
563 AcpiTableInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt1;
564
565 //
566 // RSDP OEM information is updated to match the FADT OEM information
567 //
568 CopyMem (
569 &AcpiTableInstance->Rsdp1->OemId,
570 &AcpiTableInstance->Fadt1->Header.OemId,
571 6
572 );
573
574 //
575 // RSDT OEM information is updated to match the FADT OEM information.
576 //
577 CopyMem (
578 &AcpiTableInstance->Rsdt1->OemId,
579 &AcpiTableInstance->Fadt1->Header.OemId,
580 6
581 );
582
583 CopyMem (
584 &AcpiTableInstance->Rsdt1->OemTableId,
585 &AcpiTableInstance->Fadt1->Header.OemTableId,
586 sizeof (UINT64)
587 );
588 AcpiTableInstance->Rsdt1->OemRevision = AcpiTableInstance->Fadt1->Header.OemRevision;
589 }
590
591 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
592 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
593 //
594 // Save a pointer to the table
595 //
596 AcpiTableInstance->Fadt3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table;
597
598 //
599 // Update pointers in FADT. If tables don't exist this will put NULL pointers there.
600 //
601 if (AcpiTableInstance->Fadt3 != NULL) {
602 AcpiTableInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs3;
603 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;
604 CopyMem (
605 &AcpiTableInstance->Fadt3->XFirmwareCtrl,
606 &Buffer64,
607 sizeof (UINT64)
608 );
609 AcpiTableInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;
610 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;
611 CopyMem (
612 &AcpiTableInstance->Fadt3->XDsdt,
613 &Buffer64,
614 sizeof (UINT64)
615 );
616 }
617 //
618 // RSDP OEM information is updated to match the FADT OEM information
619 //
620 CopyMem (
621 &AcpiTableInstance->Rsdp3->OemId,
622 &AcpiTableInstance->Fadt3->Header.OemId,
623 6
624 );
625
626 //
627 // RSDT OEM information is updated to match FADT OEM information.
628 //
629 CopyMem (
630 &AcpiTableInstance->Rsdt3->OemId,
631 &AcpiTableInstance->Fadt3->Header.OemId,
632 6
633 );
634 CopyMem (
635 &AcpiTableInstance->Rsdt3->OemTableId,
636 &AcpiTableInstance->Fadt3->Header.OemTableId,
637 sizeof (UINT64)
638 );
639 AcpiTableInstance->Rsdt3->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;
640
641 //
642 // XSDT OEM information is updated to match FADT OEM information.
643 //
644 CopyMem (
645 &AcpiTableInstance->Xsdt->OemId,
646 &AcpiTableInstance->Fadt3->Header.OemId,
647 6
648 );
649 CopyMem (
650 &AcpiTableInstance->Xsdt->OemTableId,
651 &AcpiTableInstance->Fadt3->Header.OemTableId,
652 sizeof (UINT64)
653 );
654 AcpiTableInstance->Xsdt->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;
655 }
656 //
657 // Checksum the table
658 //
659 if (Checksum) {
660 AcpiPlatformChecksum (
661 CurrentTableList->Table,
662 CurrentTableList->Table->Length,
663 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
664 Checksum)
665 );
666 }
667 break;
668
669 case EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
670 //
671 // Check that the table has not been previously added.
672 //
673 if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Facs1 != NULL) ||
674 ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiTableInstance->Facs3 != NULL) ||
675 ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiTableInstance->Facs3 != NULL)
676 ) {
677 gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
678 gBS->FreePool (CurrentTableList);
679 return EFI_ABORTED;
680 }
681 //
682 // FACS is referenced by FADT and is not part of RSDT
683 //
684 AddToRsdt = FALSE;
685
686 //
687 // Add the table to the appropriate table version
688 //
689 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
690 //
691 // Save a pointer to the table
692 //
693 AcpiTableInstance->Facs1 = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;
694
695 //
696 // If FADT already exists, update table pointers.
697 //
698 if (AcpiTableInstance->Fadt1 != NULL) {
699 AcpiTableInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs1;
700
701 //
702 // Checksum FADT table
703 //
704 AcpiPlatformChecksum (
705 AcpiTableInstance->Fadt1,
706 AcpiTableInstance->Fadt1->Header.Length,
707 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
708 Checksum)
709 );
710 }
711 }
712
713 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
714 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
715 //
716 // Save a pointer to the table
717 //
718 AcpiTableInstance->Facs3 = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;
719
720 //
721 // If FADT already exists, update table pointers.
722 //
723 if (AcpiTableInstance->Fadt3 != NULL) {
724 AcpiTableInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs3;
725 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;
726 CopyMem (
727 &AcpiTableInstance->Fadt3->XFirmwareCtrl,
728 &Buffer64,
729 sizeof (UINT64)
730 );
731
732 //
733 // Checksum FADT table
734 //
735 AcpiPlatformChecksum (
736 AcpiTableInstance->Fadt3,
737 AcpiTableInstance->Fadt3->Header.Length,
738 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
739 Checksum)
740 );
741 }
742 }
743
744 break;
745
746 case EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
747 //
748 // Check that the table has not been previously added.
749 //
750 if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Dsdt1 != NULL) ||
751 ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiTableInstance->Dsdt3 != NULL) ||
752 ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiTableInstance->Dsdt3 != NULL)
753 ) {
754 gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
755 gBS->FreePool (CurrentTableList);
756 return EFI_ABORTED;
757 }
758 //
759 // DSDT is referenced by FADT and is not part of RSDT
760 //
761 AddToRsdt = FALSE;
762
763 //
764 // Add the table to the appropriate table version
765 //
766 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
767 //
768 // Save a pointer to the table
769 //
770 AcpiTableInstance->Dsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;
771
772 //
773 // If FADT already exists, update table pointers.
774 //
775 if (AcpiTableInstance->Fadt1 != NULL) {
776 AcpiTableInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt1;
777
778 //
779 // Checksum FADT table
780 //
781 AcpiPlatformChecksum (
782 AcpiTableInstance->Fadt1,
783 AcpiTableInstance->Fadt1->Header.Length,
784 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
785 Checksum)
786 );
787 }
788 }
789
790 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
791 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
792 //
793 // Save a pointer to the table
794 //
795 AcpiTableInstance->Dsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;
796
797 //
798 // If FADT already exists, update table pointers.
799 //
800 if (AcpiTableInstance->Fadt3 != NULL) {
801 AcpiTableInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;
802 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;
803 CopyMem (
804 &AcpiTableInstance->Fadt3->XDsdt,
805 &Buffer64,
806 sizeof (UINT64)
807 );
808
809 //
810 // Checksum FADT table
811 //
812 AcpiPlatformChecksum (
813 AcpiTableInstance->Fadt3,
814 AcpiTableInstance->Fadt3->Header.Length,
815 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
816 Checksum)
817 );
818 }
819 }
820 //
821 // Checksum the table
822 //
823 if (Checksum) {
824 AcpiPlatformChecksum (
825 CurrentTableList->Table,
826 CurrentTableList->Table->Length,
827 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
828 Checksum)
829 );
830 }
831 break;
832
833 default:
834 //
835 // Checksum the table
836 //
837 if (Checksum) {
838 AcpiPlatformChecksum (
839 CurrentTableList->Table,
840 CurrentTableList->Table->Length,
841 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
842 Checksum)
843 );
844 }
845 break;
846 }
847 //
848 // Add the table to the current list of tables
849 //
850 InsertTailList (&AcpiTableInstance->TableList, &CurrentTableList->Link);
851
852 //
853 // Add the table to RSDT and/or XSDT table entry lists.
854 //
855 //
856 // Add to ACPI 1.0b table tree
857 //
858 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
859 CurrentRsdtEntry = (UINT32 *)
860 (
861 (UINT8 *) AcpiTableInstance->Rsdt1 +
862 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
863 AcpiTableInstance->NumberOfTableEntries1 *
864 sizeof (UINT32)
865 );
866
867 //
868 // Add entry to the RSDT unless its the FACS or DSDT
869 //
870 if (AddToRsdt) {
871 *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;
872
873 //
874 // Update RSDT length
875 //
876 AcpiTableInstance->Rsdt1->Length = AcpiTableInstance->Rsdt1->Length + sizeof (UINT32);
877
878 AcpiTableInstance->NumberOfTableEntries1++;
879 }
880
881 ASSERT (AcpiTableInstance->NumberOfTableEntries1 <= EFI_ACPI_MAX_NUM_TABLES);
882 }
883 //
884 // Add to ACPI 2.0/3.0 table tree
885 //
886 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
887 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
888 if (AddToRsdt) {
889 //
890 // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
891 // If it becomes necessary to maintain separate table lists, changes will be required.
892 //
893 CurrentRsdtEntry = (UINT32 *)
894 (
895 (UINT8 *) AcpiTableInstance->Rsdt3 +
896 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
897 AcpiTableInstance->NumberOfTableEntries3 *
898 sizeof (UINT32)
899 );
900
901 //
902 // This pointer must not be directly dereferenced as the XSDT entries may not
903 // be 64 bit aligned resulting in a possible fault. Use CopyMem to update.
904 //
905 CurrentXsdtEntry = (VOID *)
906 (
907 (UINT8 *) AcpiTableInstance->Xsdt +
908 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
909 AcpiTableInstance->NumberOfTableEntries3 *
910 sizeof (UINT64)
911 );
912
913 //
914 // Add entry to the RSDT
915 //
916 *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;
917
918 //
919 // Update RSDT length
920 //
921 AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof (UINT32);
922
923 //
924 // Add entry to XSDT, XSDT expects 64 bit pointers, but
925 // the table pointers in XSDT are not aligned on 8 byte boundary.
926 //
927 Buffer64 = (UINT64) (UINTN) CurrentTableList->Table;
928 CopyMem (
929 CurrentXsdtEntry,
930 &Buffer64,
931 sizeof (UINT64)
932 );
933
934 //
935 // Update length
936 //
937 AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof (UINT64);
938
939 AcpiTableInstance->NumberOfTableEntries3++;
940 }
941
942 ASSERT (AcpiTableInstance->NumberOfTableEntries3 <= EFI_ACPI_MAX_NUM_TABLES);
943 }
944
945 ChecksumCommonTables (AcpiTableInstance);
946 return EFI_SUCCESS;
947 }
948
949
950 /**
951 This function finds the table specified by the handle and returns a pointer to it.
952 If the handle is not found, EFI_NOT_FOUND is returned and the contents of Table are
953 undefined.
954
955 @param Handle Table to find.
956 @param TableList Table list to search
957 @param Table Pointer to table found.
958
959 @return EFI_SUCCESS The function completed successfully.
960 @return EFI_NOT_FOUND No table found matching the handle specified.
961
962 **/
963 EFI_STATUS
964 FindTableByHandle (
965 IN UINTN Handle,
966 IN LIST_ENTRY *TableList,
967 OUT EFI_ACPI_TABLE_LIST **Table
968 )
969 {
970 LIST_ENTRY *CurrentLink;
971 EFI_ACPI_TABLE_LIST *CurrentTable;
972
973 //
974 // Check for invalid input parameters
975 //
976 ASSERT (Table);
977
978 //
979 // Find the table
980 //
981 CurrentLink = TableList->ForwardLink;
982
983 while (CurrentLink != TableList) {
984 CurrentTable = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);
985 if (CurrentTable->Handle == Handle) {
986 //
987 // Found handle, so return this table.
988 //
989 *Table = CurrentTable;
990 return EFI_SUCCESS;
991 }
992
993 CurrentLink = CurrentLink->ForwardLink;
994 }
995 //
996 // Table not found
997 //
998 return EFI_NOT_FOUND;
999 }
1000
1001
1002 /**
1003 This function removes a basic table from the RSDT and/or XSDT.
1004 For Acpi 1.0 tables, pass in the Rsdt.
1005 For Acpi 2.0 tables, pass in both Rsdt and Xsdt.
1006
1007 @param Table Pointer to table found.
1008 @param NumberOfTableEntries Current number of table entries in the RSDT/XSDT
1009 @param Rsdt Pointer to the RSDT to remove from
1010 @param Xsdt Pointer to the Xsdt to remove from
1011
1012 @return EFI_SUCCESS The function completed successfully.
1013 @return EFI_INVALID_PARAMETER The table was not found in both Rsdt and Xsdt.
1014
1015 **/
1016 EFI_STATUS
1017 RemoveTableFromRsdt (
1018 IN OUT EFI_ACPI_TABLE_LIST * Table,
1019 IN OUT UINTN *NumberOfTableEntries,
1020 IN OUT EFI_ACPI_DESCRIPTION_HEADER * Rsdt,
1021 IN OUT EFI_ACPI_DESCRIPTION_HEADER * Xsdt OPTIONAL
1022 )
1023 {
1024 UINT32 *CurrentRsdtEntry;
1025 VOID *CurrentXsdtEntry;
1026 UINT64 CurrentTablePointer64;
1027 UINTN Index;
1028
1029 //
1030 // Check for invalid input parameters
1031 //
1032 ASSERT (Table);
1033 ASSERT (NumberOfTableEntries);
1034 ASSERT (Rsdt);
1035
1036 //
1037 // Find the table entry in the RSDT and XSDT
1038 //
1039 for (Index = 0; Index < *NumberOfTableEntries; Index++) {
1040 //
1041 // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
1042 // If it becomes necessary to maintain separate table lists, changes will be required.
1043 //
1044 CurrentRsdtEntry = (UINT32 *) ((UINT8 *) Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT32));
1045 if (Xsdt != NULL) {
1046 //
1047 // This pointer must not be directly dereferenced as the XSDT entries may not
1048 // be 64 bit aligned resulting in a possible fault. Use CopyMem to update.
1049 //
1050 CurrentXsdtEntry = (VOID *) ((UINT8 *) Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT64));
1051
1052 //
1053 // Read the entry value out of the XSDT
1054 //
1055 CopyMem (&CurrentTablePointer64, CurrentXsdtEntry, sizeof (UINT64));
1056 } else {
1057 //
1058 // Initialize to NULL
1059 //
1060 CurrentXsdtEntry = 0;
1061 CurrentTablePointer64 = 0;
1062 }
1063 //
1064 // Check if we have found the corresponding entry in both RSDT and XSDT
1065 //
1066 if (*CurrentRsdtEntry == (UINT32) (UINTN) Table->Table &&
1067 ((Xsdt == NULL) || CurrentTablePointer64 == (UINT64) (UINTN) Table->Table)
1068 ) {
1069 //
1070 // Found entry, so copy all following entries and shrink table
1071 // We actually copy all + 1 to copy the initialized value of memory over
1072 // the last entry.
1073 //
1074 CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - Index) * sizeof (UINT32));
1075 Rsdt->Length = Rsdt->Length - sizeof (UINT32);
1076 if (Xsdt != NULL) {
1077 CopyMem (CurrentXsdtEntry, ((UINT64 *) CurrentXsdtEntry) + 1, (*NumberOfTableEntries - Index) * sizeof (UINT64));
1078 Xsdt->Length = Xsdt->Length - sizeof (UINT64);
1079 }
1080 break;
1081 } else if (Index + 1 == *NumberOfTableEntries) {
1082 //
1083 // At the last entry, and table not found
1084 //
1085 return EFI_INVALID_PARAMETER;
1086 }
1087 }
1088 //
1089 // Checksum the tables
1090 //
1091 AcpiPlatformChecksum (
1092 Rsdt,
1093 Rsdt->Length,
1094 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1095 Checksum)
1096 );
1097
1098 if (Xsdt != NULL) {
1099 AcpiPlatformChecksum (
1100 Xsdt,
1101 Xsdt->Length,
1102 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1103 Checksum)
1104 );
1105 }
1106 //
1107 // Decrement the number of tables
1108 //
1109 (*NumberOfTableEntries)--;
1110
1111 return EFI_SUCCESS;
1112 }
1113
1114
1115 /**
1116 This function removes a table and frees any associated memory.
1117
1118 @param AcpiTableInstance Instance of the protocol.
1119 @param Version Version(s) to delete.
1120 @param Table Pointer to table found.
1121
1122 @return EFI_SUCCESS The function completed successfully.
1123
1124 **/
1125 EFI_STATUS
1126 DeleteTable (
1127 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
1128 IN EFI_ACPI_TABLE_VERSION Version,
1129 IN OUT EFI_ACPI_TABLE_LIST *Table
1130 )
1131 {
1132 UINT32 CurrentTableSignature;
1133 BOOLEAN RemoveFromRsdt;
1134
1135 //
1136 // Check for invalid input parameters
1137 //
1138 ASSERT (AcpiTableInstance);
1139 ASSERT (Table);
1140
1141 //
1142 // Init locals
1143 //
1144 RemoveFromRsdt = TRUE;
1145 CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table->Table)->Signature;
1146
1147 //
1148 // Basic tasks to accomplish delete are:
1149 // Determine removal requirements (in RSDT/XSDT or not)
1150 // Remove entry from RSDT/XSDT
1151 // Remove any table references to the table
1152 // If no one is using the table
1153 // Free the table (removing pointers from private data and tables)
1154 // Remove from list
1155 // Free list structure
1156 //
1157 //
1158 // Determine if this table is in the RSDT or XSDT
1159 //
1160 if ((CurrentTableSignature == EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
1161 (CurrentTableSignature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) ||
1162 (CurrentTableSignature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)
1163 ) {
1164 RemoveFromRsdt = FALSE;
1165 }
1166 //
1167 // We don't remove the FADT in the standard way because some
1168 // OS expect the FADT to be early in the table list.
1169 // So we always put it as the first element in the list.
1170 //
1171 if (CurrentTableSignature == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
1172 RemoveFromRsdt = FALSE;
1173 }
1174
1175 //
1176 // Remove the table from RSDT and XSDT
1177 //
1178 if (Table->Table != NULL) {
1179 //
1180 // This is a basic table, remove it from any lists and the Rsdt and/or Xsdt
1181 //
1182 if (Version & EFI_ACPI_TABLE_VERSION_NONE & Table->Version) {
1183 //
1184 // Remove this version from the table
1185 //
1186 Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_NONE;
1187 }
1188
1189 if (Version & EFI_ACPI_TABLE_VERSION_1_0B & Table->Version) {
1190 //
1191 // Remove this version from the table
1192 //
1193 Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_1_0B;
1194
1195 //
1196 // Remove from Rsdt. We don't care about the return value because it is
1197 // acceptable for the table to not exist in Rsdt.
1198 // We didn't add some tables so we don't remove them.
1199 //
1200 if (RemoveFromRsdt) {
1201 RemoveTableFromRsdt (
1202 Table,
1203 &AcpiTableInstance->NumberOfTableEntries1,
1204 AcpiTableInstance->Rsdt1,
1205 NULL
1206 );
1207 }
1208 }
1209
1210 if ((Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) ||
1211 (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version)) {
1212 //
1213 // Remove this version from the table
1214 //
1215 if (Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) {
1216 Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_2_0;
1217 }
1218 if (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version) {
1219 Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_3_0;
1220 }
1221
1222 //
1223 // Remove from Rsdt and Xsdt. We don't care about the return value
1224 // because it is acceptable for the table to not exist in Rsdt/Xsdt.
1225 // We didn't add some tables so we don't remove them.
1226 //
1227 if (RemoveFromRsdt) {
1228 RemoveTableFromRsdt (
1229 Table,
1230 &AcpiTableInstance->NumberOfTableEntries3,
1231 AcpiTableInstance->Rsdt3,
1232 AcpiTableInstance->Xsdt
1233 );
1234 }
1235 }
1236 //
1237 // Free the table, clean up any dependent tables and our private data pointers.
1238 //
1239 switch (Table->Table->Signature) {
1240
1241 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
1242 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1243 AcpiTableInstance->Fadt1 = NULL;
1244 }
1245
1246 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
1247 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
1248 AcpiTableInstance->Fadt3 = NULL;
1249 }
1250 break;
1251
1252 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
1253 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1254 AcpiTableInstance->Facs1 = NULL;
1255
1256 //
1257 // Update FADT table pointers
1258 //
1259 if (AcpiTableInstance->Fadt1 != NULL) {
1260 AcpiTableInstance->Fadt1->FirmwareCtrl = 0;
1261
1262 //
1263 // Checksum table
1264 //
1265 AcpiPlatformChecksum (
1266 AcpiTableInstance->Fadt1,
1267 AcpiTableInstance->Fadt1->Header.Length,
1268 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1269 Checksum)
1270 );
1271 }
1272 }
1273
1274 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
1275 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
1276 AcpiTableInstance->Facs3 = NULL;
1277
1278 //
1279 // Update FADT table pointers
1280 //
1281 if (AcpiTableInstance->Fadt3 != NULL) {
1282 AcpiTableInstance->Fadt3->FirmwareCtrl = 0;
1283 ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));
1284
1285 //
1286 // Checksum table
1287 //
1288 AcpiPlatformChecksum (
1289 AcpiTableInstance->Fadt3,
1290 AcpiTableInstance->Fadt3->Header.Length,
1291 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1292 Checksum)
1293 );
1294 }
1295 }
1296 break;
1297
1298 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
1299 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1300 AcpiTableInstance->Dsdt1 = NULL;
1301
1302 //
1303 // Update FADT table pointers
1304 //
1305 if (AcpiTableInstance->Fadt1 != NULL) {
1306 AcpiTableInstance->Fadt1->Dsdt = 0;
1307
1308 //
1309 // Checksum table
1310 //
1311 AcpiPlatformChecksum (
1312 AcpiTableInstance->Fadt1,
1313 AcpiTableInstance->Fadt1->Header.Length,
1314 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1315 Checksum)
1316 );
1317 }
1318 }
1319
1320
1321 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
1322 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
1323 AcpiTableInstance->Dsdt3 = NULL;
1324
1325 //
1326 // Update FADT table pointers
1327 //
1328 if (AcpiTableInstance->Fadt3 != NULL) {
1329 AcpiTableInstance->Fadt3->Dsdt = 0;
1330 ZeroMem (&AcpiTableInstance->Fadt3->XDsdt, sizeof (UINT64));
1331
1332 //
1333 // Checksum table
1334 //
1335 AcpiPlatformChecksum (
1336 AcpiTableInstance->Fadt3,
1337 AcpiTableInstance->Fadt3->Header.Length,
1338 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1339 Checksum)
1340 );
1341 }
1342 }
1343 break;
1344
1345 default:
1346 //
1347 // Do nothing
1348 //
1349 break;
1350 }
1351 }
1352 //
1353 // If no version is using this table anymore, remove and free list entry.
1354 //
1355 if (Table->Version == 0) {
1356 //
1357 // Free the Table
1358 //
1359 gBS->FreePages (Table->PageAddress, Table->NumberOfPages);
1360 RemoveEntryList (&(Table->Link));
1361 gBS->FreePool (Table);
1362 }
1363 //
1364 // Done
1365 //
1366 return EFI_SUCCESS;
1367 }
1368
1369
1370 /**
1371 This function finds and removes the table specified by the handle.
1372
1373 @param AcpiTableInstance Instance of the protocol.
1374 @param Version Bitmask of which versions to remove.
1375 @param Handle Table to remove.
1376
1377 @return EFI_SUCCESS The function completed successfully.
1378 @return EFI_ABORTED An error occurred.
1379 @return EFI_NOT_FOUND Handle not found in table list.
1380
1381 **/
1382 EFI_STATUS
1383 RemoveTableFromList (
1384 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
1385 IN EFI_ACPI_TABLE_VERSION Version,
1386 IN UINTN Handle
1387 )
1388 {
1389 EFI_ACPI_TABLE_LIST *Table;
1390 EFI_STATUS Status;
1391
1392 //
1393 // Check for invalid input parameters
1394 //
1395 ASSERT (AcpiTableInstance);
1396
1397 //
1398 // Find the table
1399 //
1400 Status = FindTableByHandle (
1401 Handle,
1402 &AcpiTableInstance->TableList,
1403 &Table
1404 );
1405 if (EFI_ERROR (Status)) {
1406 return EFI_NOT_FOUND;
1407 }
1408 //
1409 // Remove the table
1410 //
1411 Status = DeleteTable (AcpiTableInstance, Version, Table);
1412 if (EFI_ERROR (Status)) {
1413 return EFI_ABORTED;
1414 }
1415 //
1416 // Completed successfully
1417 //
1418 return EFI_SUCCESS;
1419 }
1420
1421
1422 /**
1423 This function calculates and updates an UINT8 checksum.
1424
1425 @param Buffer Pointer to buffer to checksum
1426 @param Size Number of bytes to checksum
1427 @param ChecksumOffset Offset to place the checksum result in
1428
1429 @return EFI_SUCCESS The function completed successfully.
1430
1431 **/
1432 EFI_STATUS
1433 AcpiPlatformChecksum (
1434 IN VOID *Buffer,
1435 IN UINTN Size,
1436 IN UINTN ChecksumOffset
1437 )
1438 {
1439 UINT8 Sum;
1440 UINT8 *Ptr;
1441
1442 Sum = 0;
1443 //
1444 // Initialize pointer
1445 //
1446 Ptr = Buffer;
1447
1448 //
1449 // set checksum to 0 first
1450 //
1451 Ptr[ChecksumOffset] = 0;
1452
1453 //
1454 // add all content of buffer
1455 //
1456 while ((Size--) != 0) {
1457 Sum = (UINT8) (Sum + (*Ptr++));
1458 }
1459 //
1460 // set checksum
1461 //
1462 Ptr = Buffer;
1463 Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1);
1464
1465 return EFI_SUCCESS;
1466 }
1467
1468
1469 /**
1470 Checksum all versions of the common tables, RSDP, RSDT, XSDT.
1471
1472 @param AcpiTableInstance Protocol instance private data.
1473
1474 @return EFI_SUCCESS The function completed successfully.
1475
1476 **/
1477 EFI_STATUS
1478 ChecksumCommonTables (
1479 IN OUT EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance
1480 )
1481 {
1482 //
1483 // RSDP ACPI 1.0 checksum for 1.0 table. This is only the first 20 bytes of the structure
1484 //
1485 AcpiPlatformChecksum (
1486 AcpiTableInstance->Rsdp1,
1487 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
1488 OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
1489 Checksum)
1490 );
1491
1492 //
1493 // RSDP ACPI 1.0 checksum for 2.0/3.0 table. This is only the first 20 bytes of the structure
1494 //
1495 AcpiPlatformChecksum (
1496 AcpiTableInstance->Rsdp3,
1497 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
1498 OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
1499 Checksum)
1500 );
1501
1502 //
1503 // RSDP ACPI 2.0/3.0 checksum, this is the entire table
1504 //
1505 AcpiPlatformChecksum (
1506 AcpiTableInstance->Rsdp3,
1507 sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
1508 OFFSET_OF (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
1509 ExtendedChecksum)
1510 );
1511
1512 //
1513 // RSDT checksums
1514 //
1515 AcpiPlatformChecksum (
1516 AcpiTableInstance->Rsdt1,
1517 AcpiTableInstance->Rsdt1->Length,
1518 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1519 Checksum)
1520 );
1521
1522 AcpiPlatformChecksum (
1523 AcpiTableInstance->Rsdt3,
1524 AcpiTableInstance->Rsdt3->Length,
1525 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1526 Checksum)
1527 );
1528
1529 //
1530 // XSDT checksum
1531 //
1532 AcpiPlatformChecksum (
1533 AcpiTableInstance->Xsdt,
1534 AcpiTableInstance->Xsdt->Length,
1535 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1536 Checksum)
1537 );
1538
1539 return EFI_SUCCESS;
1540 }
1541
1542
1543 /**
1544 Constructor for the ACPI table protocol. Initializes instance
1545 data.
1546
1547 @param AcpiTableInstance Instance to construct
1548
1549 @return EFI_SUCCESS Instance initialized.
1550 @return EFI_OUT_OF_RESOURCES Unable to allocate required resources.
1551
1552 **/
1553 EFI_STATUS
1554 AcpiTableAcpiTableConstructor (
1555 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance
1556 )
1557 {
1558 EFI_STATUS Status;
1559 UINT64 CurrentData;
1560 UINTN TotalSize;
1561 UINT8 *Pointer;
1562 EFI_PHYSICAL_ADDRESS PageAddress;
1563
1564 //
1565 // Check for invalid input parameters
1566 //
1567 ASSERT (AcpiTableInstance);
1568
1569 InitializeListHead (&AcpiTableInstance->TableList);
1570 AcpiTableInstance->CurrentHandle = 1;
1571
1572 AcpiTableInstance->AcpiTableProtocol.InstallAcpiTable = InstallAcpiTable;
1573 AcpiTableInstance->AcpiTableProtocol.UninstallAcpiTable = UninstallAcpiTable;
1574 //
1575 // Create RSDP, RSDT, XSDT structures
1576 // Allocate all buffers
1577 //
1578 TotalSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +
1579 sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +
1580 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT
1581 EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32) +
1582 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT
1583 EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32) +
1584 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT
1585 EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT64);
1586
1587 //
1588 // Allocate memory in the lower 32 bit of address range for
1589 // compatibility with ACPI 1.0 OS.
1590 //
1591 // This is done because ACPI 1.0 pointers are 32 bit values.
1592 // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
1593 // There is no architectural reason these should be below 4GB, it is purely
1594 // for convenience of implementation that we force memory below 4GB.
1595 //
1596 PageAddress = 0xFFFFFFFF;
1597 Status = gBS->AllocatePages (
1598 AllocateMaxAddress,
1599 EfiACPIReclaimMemory,
1600 EFI_SIZE_TO_PAGES (TotalSize),
1601 &PageAddress
1602 );
1603
1604 if (EFI_ERROR (Status)) {
1605 return EFI_OUT_OF_RESOURCES;
1606 }
1607
1608 Pointer = (UINT8 *) (UINTN) PageAddress;
1609 ZeroMem (Pointer, TotalSize);
1610
1611 AcpiTableInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
1612 Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1613 AcpiTableInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
1614 Pointer += sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1615
1616 AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
1617 Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));
1618 AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
1619 Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));
1620
1621 AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
1622
1623 //
1624 // Initialize RSDP
1625 //
1626 CurrentData = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;
1627 CopyMem (&AcpiTableInstance->Rsdp1->Signature, &CurrentData, sizeof (UINT64));
1628 CopyMem (AcpiTableInstance->Rsdp1->OemId, EFI_ACPI_OEM_ID, 6);
1629 AcpiTableInstance->Rsdp1->Reserved = EFI_ACPI_RESERVED_BYTE;
1630 AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;
1631
1632 CurrentData = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;
1633 CopyMem (&AcpiTableInstance->Rsdp3->Signature, &CurrentData, sizeof (UINT64));
1634 CopyMem (AcpiTableInstance->Rsdp3->OemId, EFI_ACPI_OEM_ID, 6);
1635 AcpiTableInstance->Rsdp3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION;
1636 AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;
1637 AcpiTableInstance->Rsdp3->Length = sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1638 CurrentData = (UINT64) (UINTN) AcpiTableInstance->Xsdt;
1639 CopyMem (&AcpiTableInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));
1640 SetMem (AcpiTableInstance->Rsdp3->Reserved, 3, EFI_ACPI_RESERVED_BYTE);
1641
1642 //
1643 // Initialize Rsdt
1644 //
1645 // Note that we "reserve" one entry for the FADT so it can always be
1646 // at the beginning of the list of tables. Some OS don't seem
1647 // to find it correctly if it is too far down the list.
1648 //
1649 AcpiTableInstance->Rsdt1->Signature = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
1650 AcpiTableInstance->Rsdt1->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
1651 AcpiTableInstance->Rsdt1->Revision = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;
1652 CopyMem (AcpiTableInstance->Rsdt1->OemId, EFI_ACPI_OEM_ID, 6);
1653 CurrentData = EFI_ACPI_OEM_TABLE_ID;
1654 CopyMem (&AcpiTableInstance->Rsdt1->OemTableId, &CurrentData, sizeof (UINT64));
1655 AcpiTableInstance->Rsdt1->OemRevision = EFI_ACPI_OEM_REVISION;
1656 AcpiTableInstance->Rsdt1->CreatorId = EFI_ACPI_CREATOR_ID;
1657 AcpiTableInstance->Rsdt1->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
1658 //
1659 // We always reserve first one for FADT
1660 //
1661 AcpiTableInstance->NumberOfTableEntries1 = 1;
1662 AcpiTableInstance->Rsdt1->Length = AcpiTableInstance->Rsdt1->Length + sizeof(UINT32);
1663
1664 AcpiTableInstance->Rsdt3->Signature = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
1665 AcpiTableInstance->Rsdt3->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
1666 AcpiTableInstance->Rsdt3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;
1667 CopyMem (AcpiTableInstance->Rsdt3->OemId, EFI_ACPI_OEM_ID, 6);
1668 CurrentData = EFI_ACPI_OEM_TABLE_ID;
1669 CopyMem (&AcpiTableInstance->Rsdt3->OemTableId, &CurrentData, sizeof (UINT64));
1670 AcpiTableInstance->Rsdt3->OemRevision = EFI_ACPI_OEM_REVISION;
1671 AcpiTableInstance->Rsdt3->CreatorId = EFI_ACPI_CREATOR_ID;
1672 AcpiTableInstance->Rsdt3->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
1673 //
1674 // We always reserve first one for FADT
1675 //
1676 AcpiTableInstance->NumberOfTableEntries3 = 1;
1677 AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof(UINT32);
1678
1679 //
1680 // Initialize Xsdt
1681 //
1682 AcpiTableInstance->Xsdt->Signature = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
1683 AcpiTableInstance->Xsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
1684 AcpiTableInstance->Xsdt->Revision = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION;
1685 CopyMem (AcpiTableInstance->Xsdt->OemId, EFI_ACPI_OEM_ID, 6);
1686 CurrentData = EFI_ACPI_OEM_TABLE_ID;
1687 CopyMem (&AcpiTableInstance->Xsdt->OemTableId, &CurrentData, sizeof (UINT64));
1688 AcpiTableInstance->Xsdt->OemRevision = EFI_ACPI_OEM_REVISION;
1689 AcpiTableInstance->Xsdt->CreatorId = EFI_ACPI_CREATOR_ID;
1690 AcpiTableInstance->Xsdt->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
1691 //
1692 // We always reserve first one for FADT
1693 //
1694 AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof(UINT64);
1695
1696 ChecksumCommonTables (AcpiTableInstance);
1697
1698 //
1699 // Completed successfully
1700 //
1701 return EFI_SUCCESS;
1702 }
1703