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