]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
fixed 2 k8 issues.
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / AcpiTableDxe / AcpiTableProtocol.c
1 /** @file
2 ACPI Table Protocol Implementation
3
4 Copyright (c) 2006 - 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 //
658 // Checksum the table
659 //
660 if (Checksum) {
661 AcpiPlatformChecksum (
662 CurrentTableList->Table,
663 CurrentTableList->Table->Length,
664 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
665 Checksum)
666 );
667 }
668 break;
669
670 case EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
671 //
672 // Check that the table has not been previously added.
673 //
674 if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Facs1 != NULL) ||
675 ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiTableInstance->Facs3 != NULL) ||
676 ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiTableInstance->Facs3 != NULL)
677 ) {
678 gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
679 gBS->FreePool (CurrentTableList);
680 return EFI_ABORTED;
681 }
682 //
683 // FACS is referenced by FADT and is not part of RSDT
684 //
685 AddToRsdt = FALSE;
686
687 //
688 // Add the table to the appropriate table version
689 //
690 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
691 //
692 // Save a pointer to the table
693 //
694 AcpiTableInstance->Facs1 = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;
695
696 //
697 // If FADT already exists, update table pointers.
698 //
699 if (AcpiTableInstance->Fadt1 != NULL) {
700 AcpiTableInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs1;
701
702 //
703 // Checksum FADT table
704 //
705 AcpiPlatformChecksum (
706 AcpiTableInstance->Fadt1,
707 AcpiTableInstance->Fadt1->Header.Length,
708 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
709 Checksum)
710 );
711 }
712 }
713
714 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
715 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
716 //
717 // Save a pointer to the table
718 //
719 AcpiTableInstance->Facs3 = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;
720
721 //
722 // If FADT already exists, update table pointers.
723 //
724 if (AcpiTableInstance->Fadt3 != NULL) {
725 AcpiTableInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiTableInstance->Facs3;
726 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;
727 CopyMem (
728 &AcpiTableInstance->Fadt3->XFirmwareCtrl,
729 &Buffer64,
730 sizeof (UINT64)
731 );
732
733 //
734 // Checksum FADT table
735 //
736 AcpiPlatformChecksum (
737 AcpiTableInstance->Fadt3,
738 AcpiTableInstance->Fadt3->Header.Length,
739 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
740 Checksum)
741 );
742 }
743 }
744
745 break;
746
747 case EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
748 //
749 // Check that the table has not been previously added.
750 //
751 if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Dsdt1 != NULL) ||
752 ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 && AcpiTableInstance->Dsdt3 != NULL) ||
753 ((Version & EFI_ACPI_TABLE_VERSION_3_0) != 0 && AcpiTableInstance->Dsdt3 != NULL)
754 ) {
755 gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
756 gBS->FreePool (CurrentTableList);
757 return EFI_ABORTED;
758 }
759 //
760 // DSDT is referenced by FADT and is not part of RSDT
761 //
762 AddToRsdt = FALSE;
763
764 //
765 // Add the table to the appropriate table version
766 //
767 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
768 //
769 // Save a pointer to the table
770 //
771 AcpiTableInstance->Dsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;
772
773 //
774 // If FADT already exists, update table pointers.
775 //
776 if (AcpiTableInstance->Fadt1 != NULL) {
777 AcpiTableInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt1;
778
779 //
780 // Checksum FADT table
781 //
782 AcpiPlatformChecksum (
783 AcpiTableInstance->Fadt1,
784 AcpiTableInstance->Fadt1->Header.Length,
785 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
786 Checksum)
787 );
788 }
789 }
790
791 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
792 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
793 //
794 // Save a pointer to the table
795 //
796 AcpiTableInstance->Dsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;
797
798 //
799 // If FADT already exists, update table pointers.
800 //
801 if (AcpiTableInstance->Fadt3 != NULL) {
802 AcpiTableInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;
803 Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;
804 CopyMem (
805 &AcpiTableInstance->Fadt3->XDsdt,
806 &Buffer64,
807 sizeof (UINT64)
808 );
809
810 //
811 // Checksum FADT table
812 //
813 AcpiPlatformChecksum (
814 AcpiTableInstance->Fadt3,
815 AcpiTableInstance->Fadt3->Header.Length,
816 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
817 Checksum)
818 );
819 }
820 }
821 //
822 // Checksum the table
823 //
824 if (Checksum) {
825 AcpiPlatformChecksum (
826 CurrentTableList->Table,
827 CurrentTableList->Table->Length,
828 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
829 Checksum)
830 );
831 }
832 break;
833
834 default:
835 //
836 // Checksum the table
837 //
838 if (Checksum) {
839 AcpiPlatformChecksum (
840 CurrentTableList->Table,
841 CurrentTableList->Table->Length,
842 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
843 Checksum)
844 );
845 }
846 break;
847 }
848 //
849 // Add the table to the current list of tables
850 //
851 InsertTailList (&AcpiTableInstance->TableList, &CurrentTableList->Link);
852
853 //
854 // Add the table to RSDT and/or XSDT table entry lists.
855 //
856 //
857 // Add to ACPI 1.0b table tree
858 //
859 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
860 CurrentRsdtEntry = (UINT32 *)
861 (
862 (UINT8 *) AcpiTableInstance->Rsdt1 +
863 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
864 AcpiTableInstance->NumberOfTableEntries1 *
865 sizeof (UINT32)
866 );
867
868 //
869 // Add entry to the RSDT unless its the FACS or DSDT
870 //
871 if (AddToRsdt) {
872 *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;
873
874 //
875 // Update RSDT length
876 //
877 AcpiTableInstance->Rsdt1->Length = AcpiTableInstance->Rsdt1->Length + sizeof (UINT32);
878
879 AcpiTableInstance->NumberOfTableEntries1++;
880 }
881
882 ASSERT (AcpiTableInstance->NumberOfTableEntries1 <= EFI_ACPI_MAX_NUM_TABLES);
883 }
884 //
885 // Add to ACPI 2.0/3.0 table tree
886 //
887 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
888 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
889 if (AddToRsdt) {
890 //
891 // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
892 // If it becomes necessary to maintain separate table lists, changes will be required.
893 //
894 CurrentRsdtEntry = (UINT32 *)
895 (
896 (UINT8 *) AcpiTableInstance->Rsdt3 +
897 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
898 AcpiTableInstance->NumberOfTableEntries3 *
899 sizeof (UINT32)
900 );
901
902 //
903 // This pointer must not be directly dereferenced as the XSDT entries may not
904 // be 64 bit aligned resulting in a possible fault. Use CopyMem to update.
905 //
906 CurrentXsdtEntry = (VOID *)
907 (
908 (UINT8 *) AcpiTableInstance->Xsdt +
909 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
910 AcpiTableInstance->NumberOfTableEntries3 *
911 sizeof (UINT64)
912 );
913
914 //
915 // Add entry to the RSDT
916 //
917 *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;
918
919 //
920 // Update RSDT length
921 //
922 AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof (UINT32);
923
924 //
925 // Add entry to XSDT, XSDT expects 64 bit pointers, but
926 // the table pointers in XSDT are not aligned on 8 byte boundary.
927 //
928 Buffer64 = (UINT64) (UINTN) CurrentTableList->Table;
929 CopyMem (
930 CurrentXsdtEntry,
931 &Buffer64,
932 sizeof (UINT64)
933 );
934
935 //
936 // Update length
937 //
938 AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof (UINT64);
939
940 AcpiTableInstance->NumberOfTableEntries3++;
941 }
942
943 ASSERT (AcpiTableInstance->NumberOfTableEntries3 <= EFI_ACPI_MAX_NUM_TABLES);
944 }
945
946 ChecksumCommonTables (AcpiTableInstance);
947 return EFI_SUCCESS;
948 }
949
950
951 /**
952 This function finds the table specified by the handle and returns a pointer to it.
953 If the handle is not found, EFI_NOT_FOUND is returned and the contents of Table are
954 undefined.
955
956 @param Handle Table to find.
957 @param TableList Table list to search
958 @param Table Pointer to table found.
959
960 @return EFI_SUCCESS The function completed successfully.
961 @return EFI_NOT_FOUND No table found matching the handle specified.
962
963 **/
964 EFI_STATUS
965 FindTableByHandle (
966 IN UINTN Handle,
967 IN LIST_ENTRY *TableList,
968 OUT EFI_ACPI_TABLE_LIST **Table
969 )
970 {
971 LIST_ENTRY *CurrentLink;
972 EFI_ACPI_TABLE_LIST *CurrentTable;
973
974 //
975 // Check for invalid input parameters
976 //
977 ASSERT (Table);
978
979 //
980 // Find the table
981 //
982 CurrentLink = TableList->ForwardLink;
983
984 while (CurrentLink != TableList) {
985 CurrentTable = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);
986 if (CurrentTable->Handle == Handle) {
987 //
988 // Found handle, so return this table.
989 //
990 *Table = CurrentTable;
991 return EFI_SUCCESS;
992 }
993
994 CurrentLink = CurrentLink->ForwardLink;
995 }
996 //
997 // Table not found
998 //
999 return EFI_NOT_FOUND;
1000 }
1001
1002
1003 /**
1004 This function removes a basic table from the RSDT and/or XSDT.
1005 For Acpi 1.0 tables, pass in the Rsdt.
1006 For Acpi 2.0 tables, pass in both Rsdt and Xsdt.
1007
1008 @param Table Pointer to table found.
1009 @param NumberOfTableEntries Current number of table entries in the RSDT/XSDT
1010 @param Rsdt Pointer to the RSDT to remove from
1011 @param Xsdt Pointer to the Xsdt to remove from
1012
1013 @return EFI_SUCCESS The function completed successfully.
1014 @return EFI_INVALID_PARAMETER The table was not found in both Rsdt and Xsdt.
1015
1016 **/
1017 EFI_STATUS
1018 RemoveTableFromRsdt (
1019 IN OUT EFI_ACPI_TABLE_LIST * Table,
1020 IN OUT UINTN *NumberOfTableEntries,
1021 IN OUT EFI_ACPI_DESCRIPTION_HEADER * Rsdt,
1022 IN OUT EFI_ACPI_DESCRIPTION_HEADER * Xsdt OPTIONAL
1023 )
1024 {
1025 UINT32 *CurrentRsdtEntry;
1026 VOID *CurrentXsdtEntry;
1027 UINT64 CurrentTablePointer64;
1028 UINTN Index;
1029
1030 //
1031 // Check for invalid input parameters
1032 //
1033 ASSERT (Table);
1034 ASSERT (NumberOfTableEntries);
1035 ASSERT (Rsdt);
1036
1037 //
1038 // Find the table entry in the RSDT and XSDT
1039 //
1040 for (Index = 0; Index < *NumberOfTableEntries; Index++) {
1041 //
1042 // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
1043 // If it becomes necessary to maintain separate table lists, changes will be required.
1044 //
1045 CurrentRsdtEntry = (UINT32 *) ((UINT8 *) Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT32));
1046 if (Xsdt != NULL) {
1047 //
1048 // This pointer must not be directly dereferenced as the XSDT entries may not
1049 // be 64 bit aligned resulting in a possible fault. Use CopyMem to update.
1050 //
1051 CurrentXsdtEntry = (VOID *) ((UINT8 *) Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT64));
1052
1053 //
1054 // Read the entry value out of the XSDT
1055 //
1056 CopyMem (&CurrentTablePointer64, CurrentXsdtEntry, sizeof (UINT64));
1057 } else {
1058 //
1059 // Initialize to NULL
1060 //
1061 CurrentXsdtEntry = 0;
1062 CurrentTablePointer64 = 0;
1063 }
1064 //
1065 // Check if we have found the corresponding entry in both RSDT and XSDT
1066 //
1067 if (*CurrentRsdtEntry == (UINT32) (UINTN) Table->Table &&
1068 ((Xsdt == NULL) || CurrentTablePointer64 == (UINT64) (UINTN) Table->Table)
1069 ) {
1070 //
1071 // Found entry, so copy all following entries and shrink table
1072 // We actually copy all + 1 to copy the initialized value of memory over
1073 // the last entry.
1074 //
1075 CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - Index) * sizeof (UINT32));
1076 Rsdt->Length = Rsdt->Length - sizeof (UINT32);
1077 if (Xsdt != NULL) {
1078 CopyMem (CurrentXsdtEntry, ((UINT64 *) CurrentXsdtEntry) + 1, (*NumberOfTableEntries - Index) * sizeof (UINT64));
1079 Xsdt->Length = Xsdt->Length - sizeof (UINT64);
1080 }
1081 break;
1082 } else if (Index + 1 == *NumberOfTableEntries) {
1083 //
1084 // At the last entry, and table not found
1085 //
1086 return EFI_INVALID_PARAMETER;
1087 }
1088 }
1089 //
1090 // Checksum the tables
1091 //
1092 AcpiPlatformChecksum (
1093 Rsdt,
1094 Rsdt->Length,
1095 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1096 Checksum)
1097 );
1098
1099 if (Xsdt != NULL) {
1100 AcpiPlatformChecksum (
1101 Xsdt,
1102 Xsdt->Length,
1103 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1104 Checksum)
1105 );
1106 }
1107 //
1108 // Decrement the number of tables
1109 //
1110 (*NumberOfTableEntries)--;
1111
1112 return EFI_SUCCESS;
1113 }
1114
1115
1116 /**
1117 This function removes a table and frees any associated memory.
1118
1119 @param AcpiTableInstance Instance of the protocol.
1120 @param Version Version(s) to delete.
1121 @param Table Pointer to table found.
1122
1123 @return EFI_SUCCESS The function completed successfully.
1124
1125 **/
1126 EFI_STATUS
1127 DeleteTable (
1128 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
1129 IN EFI_ACPI_TABLE_VERSION Version,
1130 IN OUT EFI_ACPI_TABLE_LIST *Table
1131 )
1132 {
1133 UINT32 CurrentTableSignature;
1134 BOOLEAN RemoveFromRsdt;
1135
1136 //
1137 // Check for invalid input parameters
1138 //
1139 ASSERT (AcpiTableInstance);
1140 ASSERT (Table);
1141
1142 //
1143 // Init locals
1144 //
1145 RemoveFromRsdt = TRUE;
1146 //
1147 // Check for Table->Table
1148 //
1149 ASSERT (Table->Table != NULL);
1150 CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table->Table)->Signature;
1151
1152 //
1153 // Basic tasks to accomplish delete are:
1154 // Determine removal requirements (in RSDT/XSDT or not)
1155 // Remove entry from RSDT/XSDT
1156 // Remove any table references to the table
1157 // If no one is using the table
1158 // Free the table (removing pointers from private data and tables)
1159 // Remove from list
1160 // Free list structure
1161 //
1162 //
1163 // Determine if this table is in the RSDT or XSDT
1164 //
1165 if ((CurrentTableSignature == EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
1166 (CurrentTableSignature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) ||
1167 (CurrentTableSignature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)
1168 ) {
1169 RemoveFromRsdt = FALSE;
1170 }
1171 //
1172 // We don't remove the FADT in the standard way because some
1173 // OS expect the FADT to be early in the table list.
1174 // So we always put it as the first element in the list.
1175 //
1176 if (CurrentTableSignature == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
1177 RemoveFromRsdt = FALSE;
1178 }
1179
1180 //
1181 // Remove the table from RSDT and XSDT
1182 //
1183 if (Table->Table != NULL) {
1184 //
1185 // This is a basic table, remove it from any lists and the Rsdt and/or Xsdt
1186 //
1187 if (Version & EFI_ACPI_TABLE_VERSION_NONE & Table->Version) {
1188 //
1189 // Remove this version from the table
1190 //
1191 Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_NONE;
1192 }
1193
1194 if (Version & EFI_ACPI_TABLE_VERSION_1_0B & Table->Version) {
1195 //
1196 // Remove this version from the table
1197 //
1198 Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_1_0B;
1199
1200 //
1201 // Remove from Rsdt. We don't care about the return value because it is
1202 // acceptable for the table to not exist in Rsdt.
1203 // We didn't add some tables so we don't remove them.
1204 //
1205 if (RemoveFromRsdt) {
1206 RemoveTableFromRsdt (
1207 Table,
1208 &AcpiTableInstance->NumberOfTableEntries1,
1209 AcpiTableInstance->Rsdt1,
1210 NULL
1211 );
1212 }
1213 }
1214
1215 if ((Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) ||
1216 (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version)) {
1217 //
1218 // Remove this version from the table
1219 //
1220 if (Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) {
1221 Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_2_0;
1222 }
1223 if (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version) {
1224 Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_3_0;
1225 }
1226
1227 //
1228 // Remove from Rsdt and Xsdt. We don't care about the return value
1229 // because it is acceptable for the table to not exist in Rsdt/Xsdt.
1230 // We didn't add some tables so we don't remove them.
1231 //
1232 if (RemoveFromRsdt) {
1233 RemoveTableFromRsdt (
1234 Table,
1235 &AcpiTableInstance->NumberOfTableEntries3,
1236 AcpiTableInstance->Rsdt3,
1237 AcpiTableInstance->Xsdt
1238 );
1239 }
1240 }
1241 //
1242 // Free the table, clean up any dependent tables and our private data pointers.
1243 //
1244 switch (Table->Table->Signature) {
1245
1246 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
1247 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1248 AcpiTableInstance->Fadt1 = NULL;
1249 }
1250
1251 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
1252 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
1253 AcpiTableInstance->Fadt3 = NULL;
1254 }
1255 break;
1256
1257 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
1258 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1259 AcpiTableInstance->Facs1 = NULL;
1260
1261 //
1262 // Update FADT table pointers
1263 //
1264 if (AcpiTableInstance->Fadt1 != NULL) {
1265 AcpiTableInstance->Fadt1->FirmwareCtrl = 0;
1266
1267 //
1268 // Checksum table
1269 //
1270 AcpiPlatformChecksum (
1271 AcpiTableInstance->Fadt1,
1272 AcpiTableInstance->Fadt1->Header.Length,
1273 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1274 Checksum)
1275 );
1276 }
1277 }
1278
1279 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
1280 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
1281 AcpiTableInstance->Facs3 = NULL;
1282
1283 //
1284 // Update FADT table pointers
1285 //
1286 if (AcpiTableInstance->Fadt3 != NULL) {
1287 AcpiTableInstance->Fadt3->FirmwareCtrl = 0;
1288 ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));
1289
1290 //
1291 // Checksum table
1292 //
1293 AcpiPlatformChecksum (
1294 AcpiTableInstance->Fadt3,
1295 AcpiTableInstance->Fadt3->Header.Length,
1296 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1297 Checksum)
1298 );
1299 }
1300 }
1301 break;
1302
1303 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
1304 if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1305 AcpiTableInstance->Dsdt1 = NULL;
1306
1307 //
1308 // Update FADT table pointers
1309 //
1310 if (AcpiTableInstance->Fadt1 != NULL) {
1311 AcpiTableInstance->Fadt1->Dsdt = 0;
1312
1313 //
1314 // Checksum table
1315 //
1316 AcpiPlatformChecksum (
1317 AcpiTableInstance->Fadt1,
1318 AcpiTableInstance->Fadt1->Header.Length,
1319 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1320 Checksum)
1321 );
1322 }
1323 }
1324
1325
1326 if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
1327 (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
1328 AcpiTableInstance->Dsdt3 = NULL;
1329
1330 //
1331 // Update FADT table pointers
1332 //
1333 if (AcpiTableInstance->Fadt3 != NULL) {
1334 AcpiTableInstance->Fadt3->Dsdt = 0;
1335 ZeroMem (&AcpiTableInstance->Fadt3->XDsdt, sizeof (UINT64));
1336
1337 //
1338 // Checksum table
1339 //
1340 AcpiPlatformChecksum (
1341 AcpiTableInstance->Fadt3,
1342 AcpiTableInstance->Fadt3->Header.Length,
1343 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1344 Checksum)
1345 );
1346 }
1347 }
1348 break;
1349
1350 default:
1351 //
1352 // Do nothing
1353 //
1354 break;
1355 }
1356 }
1357 //
1358 // If no version is using this table anymore, remove and free list entry.
1359 //
1360 if (Table->Version == 0) {
1361 //
1362 // Free the Table
1363 //
1364 gBS->FreePages (Table->PageAddress, Table->NumberOfPages);
1365 RemoveEntryList (&(Table->Link));
1366 gBS->FreePool (Table);
1367 }
1368 //
1369 // Done
1370 //
1371 return EFI_SUCCESS;
1372 }
1373
1374
1375 /**
1376 This function finds and removes the table specified by the handle.
1377
1378 @param AcpiTableInstance Instance of the protocol.
1379 @param Version Bitmask of which versions to remove.
1380 @param Handle Table to remove.
1381
1382 @return EFI_SUCCESS The function completed successfully.
1383 @return EFI_ABORTED An error occurred.
1384 @return EFI_NOT_FOUND Handle not found in table list.
1385
1386 **/
1387 EFI_STATUS
1388 RemoveTableFromList (
1389 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
1390 IN EFI_ACPI_TABLE_VERSION Version,
1391 IN UINTN Handle
1392 )
1393 {
1394 EFI_ACPI_TABLE_LIST *Table;
1395 EFI_STATUS Status;
1396
1397 //
1398 // Check for invalid input parameters
1399 //
1400 ASSERT (AcpiTableInstance);
1401
1402 //
1403 // Find the table
1404 //
1405 Status = FindTableByHandle (
1406 Handle,
1407 &AcpiTableInstance->TableList,
1408 &Table
1409 );
1410 if (EFI_ERROR (Status)) {
1411 return EFI_NOT_FOUND;
1412 }
1413 //
1414 // Remove the table
1415 //
1416 Status = DeleteTable (AcpiTableInstance, Version, Table);
1417 if (EFI_ERROR (Status)) {
1418 return EFI_ABORTED;
1419 }
1420 //
1421 // Completed successfully
1422 //
1423 return EFI_SUCCESS;
1424 }
1425
1426
1427 /**
1428 This function calculates and updates an UINT8 checksum.
1429
1430 @param Buffer Pointer to buffer to checksum
1431 @param Size Number of bytes to checksum
1432 @param ChecksumOffset Offset to place the checksum result in
1433
1434 @return EFI_SUCCESS The function completed successfully.
1435
1436 **/
1437 EFI_STATUS
1438 AcpiPlatformChecksum (
1439 IN VOID *Buffer,
1440 IN UINTN Size,
1441 IN UINTN ChecksumOffset
1442 )
1443 {
1444 UINT8 Sum;
1445 UINT8 *Ptr;
1446
1447 Sum = 0;
1448 //
1449 // Initialize pointer
1450 //
1451 Ptr = Buffer;
1452
1453 //
1454 // set checksum to 0 first
1455 //
1456 Ptr[ChecksumOffset] = 0;
1457
1458 //
1459 // add all content of buffer
1460 //
1461 while ((Size--) != 0) {
1462 Sum = (UINT8) (Sum + (*Ptr++));
1463 }
1464 //
1465 // set checksum
1466 //
1467 Ptr = Buffer;
1468 Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1);
1469
1470 return EFI_SUCCESS;
1471 }
1472
1473
1474 /**
1475 Checksum all versions of the common tables, RSDP, RSDT, XSDT.
1476
1477 @param AcpiTableInstance Protocol instance private data.
1478
1479 @return EFI_SUCCESS The function completed successfully.
1480
1481 **/
1482 EFI_STATUS
1483 ChecksumCommonTables (
1484 IN OUT EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance
1485 )
1486 {
1487 //
1488 // RSDP ACPI 1.0 checksum for 1.0 table. This is only the first 20 bytes of the structure
1489 //
1490 AcpiPlatformChecksum (
1491 AcpiTableInstance->Rsdp1,
1492 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
1493 OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
1494 Checksum)
1495 );
1496
1497 //
1498 // RSDP ACPI 1.0 checksum for 2.0/3.0 table. This is only the first 20 bytes of the structure
1499 //
1500 AcpiPlatformChecksum (
1501 AcpiTableInstance->Rsdp3,
1502 sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
1503 OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
1504 Checksum)
1505 );
1506
1507 //
1508 // RSDP ACPI 2.0/3.0 checksum, this is the entire table
1509 //
1510 AcpiPlatformChecksum (
1511 AcpiTableInstance->Rsdp3,
1512 sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
1513 OFFSET_OF (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
1514 ExtendedChecksum)
1515 );
1516
1517 //
1518 // RSDT checksums
1519 //
1520 AcpiPlatformChecksum (
1521 AcpiTableInstance->Rsdt1,
1522 AcpiTableInstance->Rsdt1->Length,
1523 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1524 Checksum)
1525 );
1526
1527 AcpiPlatformChecksum (
1528 AcpiTableInstance->Rsdt3,
1529 AcpiTableInstance->Rsdt3->Length,
1530 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1531 Checksum)
1532 );
1533
1534 //
1535 // XSDT checksum
1536 //
1537 AcpiPlatformChecksum (
1538 AcpiTableInstance->Xsdt,
1539 AcpiTableInstance->Xsdt->Length,
1540 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1541 Checksum)
1542 );
1543
1544 return EFI_SUCCESS;
1545 }
1546
1547
1548 /**
1549 Constructor for the ACPI table protocol. Initializes instance
1550 data.
1551
1552 @param AcpiTableInstance Instance to construct
1553
1554 @return EFI_SUCCESS Instance initialized.
1555 @return EFI_OUT_OF_RESOURCES Unable to allocate required resources.
1556
1557 **/
1558 EFI_STATUS
1559 AcpiTableAcpiTableConstructor (
1560 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance
1561 )
1562 {
1563 EFI_STATUS Status;
1564 UINT64 CurrentData;
1565 UINTN TotalSize;
1566 UINT8 *Pointer;
1567 EFI_PHYSICAL_ADDRESS PageAddress;
1568
1569 //
1570 // Check for invalid input parameters
1571 //
1572 ASSERT (AcpiTableInstance);
1573
1574 InitializeListHead (&AcpiTableInstance->TableList);
1575 AcpiTableInstance->CurrentHandle = 1;
1576
1577 AcpiTableInstance->AcpiTableProtocol.InstallAcpiTable = InstallAcpiTable;
1578 AcpiTableInstance->AcpiTableProtocol.UninstallAcpiTable = UninstallAcpiTable;
1579 //
1580 // Create RSDP, RSDT, XSDT structures
1581 // Allocate all buffers
1582 //
1583 TotalSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +
1584 sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +
1585 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT
1586 EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32) +
1587 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT
1588 EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32) +
1589 sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT
1590 EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT64);
1591
1592 //
1593 // Allocate memory in the lower 32 bit of address range for
1594 // compatibility with ACPI 1.0 OS.
1595 //
1596 // This is done because ACPI 1.0 pointers are 32 bit values.
1597 // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
1598 // There is no architectural reason these should be below 4GB, it is purely
1599 // for convenience of implementation that we force memory below 4GB.
1600 //
1601 PageAddress = 0xFFFFFFFF;
1602 Status = gBS->AllocatePages (
1603 AllocateMaxAddress,
1604 EfiACPIReclaimMemory,
1605 EFI_SIZE_TO_PAGES (TotalSize),
1606 &PageAddress
1607 );
1608
1609 if (EFI_ERROR (Status)) {
1610 return EFI_OUT_OF_RESOURCES;
1611 }
1612
1613 Pointer = (UINT8 *) (UINTN) PageAddress;
1614 ZeroMem (Pointer, TotalSize);
1615
1616 AcpiTableInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
1617 Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1618 AcpiTableInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
1619 Pointer += sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1620
1621 AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
1622 Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));
1623 AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
1624 Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));
1625
1626 AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
1627
1628 //
1629 // Initialize RSDP
1630 //
1631 CurrentData = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;
1632 CopyMem (&AcpiTableInstance->Rsdp1->Signature, &CurrentData, sizeof (UINT64));
1633 CopyMem (AcpiTableInstance->Rsdp1->OemId, EFI_ACPI_OEM_ID, 6);
1634 AcpiTableInstance->Rsdp1->Reserved = EFI_ACPI_RESERVED_BYTE;
1635 AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;
1636
1637 CurrentData = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;
1638 CopyMem (&AcpiTableInstance->Rsdp3->Signature, &CurrentData, sizeof (UINT64));
1639 CopyMem (AcpiTableInstance->Rsdp3->OemId, EFI_ACPI_OEM_ID, 6);
1640 AcpiTableInstance->Rsdp3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION;
1641 AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;
1642 AcpiTableInstance->Rsdp3->Length = sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1643 CurrentData = (UINT64) (UINTN) AcpiTableInstance->Xsdt;
1644 CopyMem (&AcpiTableInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));
1645 SetMem (AcpiTableInstance->Rsdp3->Reserved, 3, EFI_ACPI_RESERVED_BYTE);
1646
1647 //
1648 // Initialize Rsdt
1649 //
1650 // Note that we "reserve" one entry for the FADT so it can always be
1651 // at the beginning of the list of tables. Some OS don't seem
1652 // to find it correctly if it is too far down the list.
1653 //
1654 AcpiTableInstance->Rsdt1->Signature = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
1655 AcpiTableInstance->Rsdt1->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
1656 AcpiTableInstance->Rsdt1->Revision = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;
1657 CopyMem (AcpiTableInstance->Rsdt1->OemId, EFI_ACPI_OEM_ID, 6);
1658 CurrentData = EFI_ACPI_OEM_TABLE_ID;
1659 CopyMem (&AcpiTableInstance->Rsdt1->OemTableId, &CurrentData, sizeof (UINT64));
1660 AcpiTableInstance->Rsdt1->OemRevision = EFI_ACPI_OEM_REVISION;
1661 AcpiTableInstance->Rsdt1->CreatorId = EFI_ACPI_CREATOR_ID;
1662 AcpiTableInstance->Rsdt1->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
1663 //
1664 // We always reserve first one for FADT
1665 //
1666 AcpiTableInstance->NumberOfTableEntries1 = 1;
1667 AcpiTableInstance->Rsdt1->Length = AcpiTableInstance->Rsdt1->Length + sizeof(UINT32);
1668
1669 AcpiTableInstance->Rsdt3->Signature = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
1670 AcpiTableInstance->Rsdt3->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
1671 AcpiTableInstance->Rsdt3->Revision = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;
1672 CopyMem (AcpiTableInstance->Rsdt3->OemId, EFI_ACPI_OEM_ID, 6);
1673 CurrentData = EFI_ACPI_OEM_TABLE_ID;
1674 CopyMem (&AcpiTableInstance->Rsdt3->OemTableId, &CurrentData, sizeof (UINT64));
1675 AcpiTableInstance->Rsdt3->OemRevision = EFI_ACPI_OEM_REVISION;
1676 AcpiTableInstance->Rsdt3->CreatorId = EFI_ACPI_CREATOR_ID;
1677 AcpiTableInstance->Rsdt3->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
1678 //
1679 // We always reserve first one for FADT
1680 //
1681 AcpiTableInstance->NumberOfTableEntries3 = 1;
1682 AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof(UINT32);
1683
1684 //
1685 // Initialize Xsdt
1686 //
1687 AcpiTableInstance->Xsdt->Signature = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
1688 AcpiTableInstance->Xsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
1689 AcpiTableInstance->Xsdt->Revision = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION;
1690 CopyMem (AcpiTableInstance->Xsdt->OemId, EFI_ACPI_OEM_ID, 6);
1691 CurrentData = EFI_ACPI_OEM_TABLE_ID;
1692 CopyMem (&AcpiTableInstance->Xsdt->OemTableId, &CurrentData, sizeof (UINT64));
1693 AcpiTableInstance->Xsdt->OemRevision = EFI_ACPI_OEM_REVISION;
1694 AcpiTableInstance->Xsdt->CreatorId = EFI_ACPI_CREATOR_ID;
1695 AcpiTableInstance->Xsdt->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
1696 //
1697 // We always reserve first one for FADT
1698 //
1699 AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof(UINT64);
1700
1701 ChecksumCommonTables (AcpiTableInstance);
1702
1703 //
1704 // Completed successfully
1705 //
1706 return EFI_SUCCESS;
1707 }
1708