]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/AcpiPlatformDxe/Qemu.c
OvmfPkg: AcpiPlatformDxe: don't rely on unstable QEMU interface
[mirror_edk2.git] / OvmfPkg / AcpiPlatformDxe / Qemu.c
1 /** @file
2 OVMF ACPI QEMU support
3
4 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
5
6 Copyright (C) 2012-2014, Red Hat, Inc.
7
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include "AcpiPlatform.h"
19 #include "QemuLoader.h"
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/QemuFwCfgLib.h>
23 #include <Library/DxeServicesTableLib.h>
24 #include <Library/PcdLib.h>
25 #include <IndustryStandard/Acpi.h>
26
27 BOOLEAN
28 QemuDetected (
29 VOID
30 )
31 {
32 if (!QemuFwCfgIsAvailable ()) {
33 return FALSE;
34 }
35
36 return TRUE;
37 }
38
39
40 STATIC
41 UINTN
42 CountBits16 (
43 UINT16 Mask
44 )
45 {
46 //
47 // For all N >= 1, N bits are enough to represent the number of bits set
48 // among N bits. It's true for N == 1. When adding a new bit (N := N+1),
49 // the maximum number of possibly set bits increases by one, while the
50 // representable maximum doubles.
51 //
52 Mask = ((Mask & 0xAAAA) >> 1) + (Mask & 0x5555);
53 Mask = ((Mask & 0xCCCC) >> 2) + (Mask & 0x3333);
54 Mask = ((Mask & 0xF0F0) >> 4) + (Mask & 0x0F0F);
55 Mask = ((Mask & 0xFF00) >> 8) + (Mask & 0x00FF);
56
57 return Mask;
58 }
59
60
61 STATIC
62 EFI_STATUS
63 EFIAPI
64 QemuInstallAcpiMadtTable (
65 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
66 IN VOID *AcpiTableBuffer,
67 IN UINTN AcpiTableBufferSize,
68 OUT UINTN *TableKey
69 )
70 {
71 UINTN CpuCount;
72 UINTN PciLinkIsoCount;
73 UINTN NewBufferSize;
74 EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt;
75 EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic;
76 EFI_ACPI_1_0_IO_APIC_STRUCTURE *IoApic;
77 EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *Iso;
78 EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE *LocalApicNmi;
79 VOID *Ptr;
80 UINTN Loop;
81 EFI_STATUS Status;
82
83 ASSERT (AcpiTableBufferSize >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
84
85 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount);
86 CpuCount = QemuFwCfgRead16 ();
87 ASSERT (CpuCount >= 1);
88
89 //
90 // Set Level-tiggered, Active High for these identity mapped IRQs. The bitset
91 // corresponds to the union of all possible interrupt assignments for the LNKA,
92 // LNKB, LNKC, LNKD PCI interrupt lines. See the DSDT.
93 //
94 PciLinkIsoCount = CountBits16 (PcdGet16 (Pcd8259LegacyModeEdgeLevel));
95
96 NewBufferSize = 1 * sizeof (*Madt) +
97 CpuCount * sizeof (*LocalApic) +
98 1 * sizeof (*IoApic) +
99 (1 + PciLinkIsoCount) * sizeof (*Iso) +
100 1 * sizeof (*LocalApicNmi);
101
102 Madt = AllocatePool (NewBufferSize);
103 if (Madt == NULL) {
104 return EFI_OUT_OF_RESOURCES;
105 }
106
107 CopyMem (&(Madt->Header), AcpiTableBuffer, sizeof (EFI_ACPI_DESCRIPTION_HEADER));
108 Madt->Header.Length = (UINT32) NewBufferSize;
109 Madt->LocalApicAddress = PcdGet32 (PcdCpuLocalApicBaseAddress);
110 Madt->Flags = EFI_ACPI_1_0_PCAT_COMPAT;
111 Ptr = Madt + 1;
112
113 LocalApic = Ptr;
114 for (Loop = 0; Loop < CpuCount; ++Loop) {
115 LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;
116 LocalApic->Length = sizeof (*LocalApic);
117 LocalApic->AcpiProcessorId = (UINT8) Loop;
118 LocalApic->ApicId = (UINT8) Loop;
119 LocalApic->Flags = 1; // enabled
120 ++LocalApic;
121 }
122 Ptr = LocalApic;
123
124 IoApic = Ptr;
125 IoApic->Type = EFI_ACPI_1_0_IO_APIC;
126 IoApic->Length = sizeof (*IoApic);
127 IoApic->IoApicId = (UINT8) CpuCount;
128 IoApic->Reserved = EFI_ACPI_RESERVED_BYTE;
129 IoApic->IoApicAddress = 0xFEC00000;
130 IoApic->SystemVectorBase = 0x00000000;
131 Ptr = IoApic + 1;
132
133 //
134 // IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure
135 //
136 Iso = Ptr;
137 Iso->Type = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE;
138 Iso->Length = sizeof (*Iso);
139 Iso->Bus = 0x00; // ISA
140 Iso->Source = 0x00; // IRQ0
141 Iso->GlobalSystemInterruptVector = 0x00000002;
142 Iso->Flags = 0x0000; // Conforms to specs of the bus
143 ++Iso;
144
145 //
146 // Set Level-tiggered, Active High for all possible PCI link targets.
147 //
148 for (Loop = 0; Loop < 16; ++Loop) {
149 if ((PcdGet16 (Pcd8259LegacyModeEdgeLevel) & (1 << Loop)) == 0) {
150 continue;
151 }
152 Iso->Type = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE;
153 Iso->Length = sizeof (*Iso);
154 Iso->Bus = 0x00; // ISA
155 Iso->Source = (UINT8) Loop;
156 Iso->GlobalSystemInterruptVector = (UINT32) Loop;
157 Iso->Flags = 0x000D; // Level-tiggered, Active High
158 ++Iso;
159 }
160 ASSERT (
161 (UINTN) (Iso - (EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *)Ptr) ==
162 1 + PciLinkIsoCount
163 );
164 Ptr = Iso;
165
166 LocalApicNmi = Ptr;
167 LocalApicNmi->Type = EFI_ACPI_1_0_LOCAL_APIC_NMI;
168 LocalApicNmi->Length = sizeof (*LocalApicNmi);
169 LocalApicNmi->AcpiProcessorId = 0xFF; // applies to all processors
170 //
171 // polarity and trigger mode of the APIC I/O input signals conform to the
172 // specifications of the bus
173 //
174 LocalApicNmi->Flags = 0x0000;
175 //
176 // Local APIC interrupt input LINTn to which NMI is connected.
177 //
178 LocalApicNmi->LocalApicInti = 0x01;
179 Ptr = LocalApicNmi + 1;
180
181 ASSERT ((UINTN) ((UINT8 *)Ptr - (UINT8 *)Madt) == NewBufferSize);
182 Status = InstallAcpiTable (AcpiProtocol, Madt, NewBufferSize, TableKey);
183
184 FreePool (Madt);
185
186 return Status;
187 }
188
189
190 #pragma pack(1)
191
192 typedef struct {
193 UINT64 Base;
194 UINT64 End;
195 UINT64 Length;
196 } PCI_WINDOW;
197
198 typedef struct {
199 PCI_WINDOW PciWindow32;
200 PCI_WINDOW PciWindow64;
201 } FIRMWARE_DATA;
202
203 typedef struct {
204 UINT8 BytePrefix;
205 UINT8 ByteValue;
206 } AML_BYTE;
207
208 typedef struct {
209 UINT8 NameOp;
210 UINT8 RootChar;
211 UINT8 NameChar[4];
212 UINT8 PackageOp;
213 UINT8 PkgLength;
214 UINT8 NumElements;
215 AML_BYTE Pm1aCntSlpTyp;
216 AML_BYTE Pm1bCntSlpTyp;
217 AML_BYTE Reserved[2];
218 } SYSTEM_STATE_PACKAGE;
219
220 #pragma pack()
221
222
223 STATIC
224 EFI_STATUS
225 EFIAPI
226 PopulateFwData(
227 OUT FIRMWARE_DATA *FwData
228 )
229 {
230 EFI_STATUS Status;
231 UINTN NumDesc;
232 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *AllDesc;
233
234 Status = gDS->GetMemorySpaceMap (&NumDesc, &AllDesc);
235 if (Status == EFI_SUCCESS) {
236 UINT64 NonMmio32MaxExclTop;
237 UINT64 Mmio32MinBase;
238 UINT64 Mmio32MaxExclTop;
239 UINTN CurDesc;
240
241 Status = EFI_UNSUPPORTED;
242
243 NonMmio32MaxExclTop = 0;
244 Mmio32MinBase = BASE_4GB;
245 Mmio32MaxExclTop = 0;
246
247 for (CurDesc = 0; CurDesc < NumDesc; ++CurDesc) {
248 CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Desc;
249 UINT64 ExclTop;
250
251 Desc = &AllDesc[CurDesc];
252 ExclTop = Desc->BaseAddress + Desc->Length;
253
254 if (ExclTop <= (UINT64) PcdGet32 (PcdOvmfFdBaseAddress)) {
255 switch (Desc->GcdMemoryType) {
256 case EfiGcdMemoryTypeNonExistent:
257 break;
258
259 case EfiGcdMemoryTypeReserved:
260 case EfiGcdMemoryTypeSystemMemory:
261 if (NonMmio32MaxExclTop < ExclTop) {
262 NonMmio32MaxExclTop = ExclTop;
263 }
264 break;
265
266 case EfiGcdMemoryTypeMemoryMappedIo:
267 if (Mmio32MinBase > Desc->BaseAddress) {
268 Mmio32MinBase = Desc->BaseAddress;
269 }
270 if (Mmio32MaxExclTop < ExclTop) {
271 Mmio32MaxExclTop = ExclTop;
272 }
273 break;
274
275 default:
276 ASSERT(0);
277 }
278 }
279 }
280
281 if (Mmio32MinBase < NonMmio32MaxExclTop) {
282 Mmio32MinBase = NonMmio32MaxExclTop;
283 }
284
285 if (Mmio32MinBase < Mmio32MaxExclTop) {
286 FwData->PciWindow32.Base = Mmio32MinBase;
287 FwData->PciWindow32.End = Mmio32MaxExclTop - 1;
288 FwData->PciWindow32.Length = Mmio32MaxExclTop - Mmio32MinBase;
289
290 FwData->PciWindow64.Base = 0;
291 FwData->PciWindow64.End = 0;
292 FwData->PciWindow64.Length = 0;
293
294 Status = EFI_SUCCESS;
295 }
296
297 FreePool (AllDesc);
298 }
299
300 DEBUG ((
301 DEBUG_INFO,
302 "ACPI PciWindow32: Base=0x%08lx End=0x%08lx Length=0x%08lx\n",
303 FwData->PciWindow32.Base,
304 FwData->PciWindow32.End,
305 FwData->PciWindow32.Length
306 ));
307 DEBUG ((
308 DEBUG_INFO,
309 "ACPI PciWindow64: Base=0x%08lx End=0x%08lx Length=0x%08lx\n",
310 FwData->PciWindow64.Base,
311 FwData->PciWindow64.End,
312 FwData->PciWindow64.Length
313 ));
314
315 return Status;
316 }
317
318
319 STATIC
320 VOID
321 EFIAPI
322 GetSuspendStates (
323 UINTN *SuspendToRamSize,
324 SYSTEM_STATE_PACKAGE *SuspendToRam,
325 UINTN *SuspendToDiskSize,
326 SYSTEM_STATE_PACKAGE *SuspendToDisk
327 )
328 {
329 STATIC CONST SYSTEM_STATE_PACKAGE Template = {
330 0x08, // NameOp
331 '\\', // RootChar
332 { '_', 'S', 'x', '_' }, // NameChar[4]
333 0x12, // PackageOp
334 0x0A, // PkgLength
335 0x04, // NumElements
336 { 0x0A, 0x00 }, // Pm1aCntSlpTyp
337 { 0x0A, 0x00 }, // Pm1bCntSlpTyp -- we don't support it
338 { // Reserved[2]
339 { 0x0A, 0x00 },
340 { 0x0A, 0x00 }
341 }
342 };
343 RETURN_STATUS Status;
344 FIRMWARE_CONFIG_ITEM FwCfgItem;
345 UINTN FwCfgSize;
346 UINT8 SystemStates[6];
347
348 //
349 // configure defaults
350 //
351 *SuspendToRamSize = sizeof Template;
352 CopyMem (SuspendToRam, &Template, sizeof Template);
353 SuspendToRam->NameChar[2] = '3'; // S3
354 SuspendToRam->Pm1aCntSlpTyp.ByteValue = 1; // PIIX4: STR
355
356 *SuspendToDiskSize = sizeof Template;
357 CopyMem (SuspendToDisk, &Template, sizeof Template);
358 SuspendToDisk->NameChar[2] = '4'; // S4
359 SuspendToDisk->Pm1aCntSlpTyp.ByteValue = 2; // PIIX4: POSCL
360
361 //
362 // check for overrides
363 //
364 Status = QemuFwCfgFindFile ("etc/system-states", &FwCfgItem, &FwCfgSize);
365 if (Status != RETURN_SUCCESS || FwCfgSize != sizeof SystemStates) {
366 DEBUG ((DEBUG_INFO, "ACPI using S3/S4 defaults\n"));
367 return;
368 }
369 QemuFwCfgSelectItem (FwCfgItem);
370 QemuFwCfgReadBytes (sizeof SystemStates, SystemStates);
371
372 //
373 // Each byte corresponds to a system state. In each byte, the MSB tells us
374 // whether the given state is enabled. If so, the three LSBs specify the
375 // value to be written to the PM control register's SUS_TYP bits.
376 //
377 if (SystemStates[3] & BIT7) {
378 SuspendToRam->Pm1aCntSlpTyp.ByteValue =
379 SystemStates[3] & (BIT2 | BIT1 | BIT0);
380 DEBUG ((DEBUG_INFO, "ACPI S3 value: %d\n",
381 SuspendToRam->Pm1aCntSlpTyp.ByteValue));
382 } else {
383 *SuspendToRamSize = 0;
384 DEBUG ((DEBUG_INFO, "ACPI S3 disabled\n"));
385 }
386
387 if (SystemStates[4] & BIT7) {
388 SuspendToDisk->Pm1aCntSlpTyp.ByteValue =
389 SystemStates[4] & (BIT2 | BIT1 | BIT0);
390 DEBUG ((DEBUG_INFO, "ACPI S4 value: %d\n",
391 SuspendToDisk->Pm1aCntSlpTyp.ByteValue));
392 } else {
393 *SuspendToDiskSize = 0;
394 DEBUG ((DEBUG_INFO, "ACPI S4 disabled\n"));
395 }
396 }
397
398
399 STATIC
400 EFI_STATUS
401 EFIAPI
402 QemuInstallAcpiSsdtTable (
403 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
404 IN VOID *AcpiTableBuffer,
405 IN UINTN AcpiTableBufferSize,
406 OUT UINTN *TableKey
407 )
408 {
409 EFI_STATUS Status;
410 FIRMWARE_DATA *FwData;
411
412 Status = EFI_OUT_OF_RESOURCES;
413
414 FwData = AllocateReservedPool (sizeof (*FwData));
415 if (FwData != NULL) {
416 UINTN SuspendToRamSize;
417 SYSTEM_STATE_PACKAGE SuspendToRam;
418 UINTN SuspendToDiskSize;
419 SYSTEM_STATE_PACKAGE SuspendToDisk;
420 UINTN SsdtSize;
421 UINT8 *Ssdt;
422
423 GetSuspendStates (&SuspendToRamSize, &SuspendToRam,
424 &SuspendToDiskSize, &SuspendToDisk);
425 SsdtSize = AcpiTableBufferSize + 17 + SuspendToRamSize + SuspendToDiskSize;
426 Ssdt = AllocatePool (SsdtSize);
427
428 if (Ssdt != NULL) {
429 Status = PopulateFwData (FwData);
430
431 if (Status == EFI_SUCCESS) {
432 UINT8 *SsdtPtr;
433
434 SsdtPtr = Ssdt;
435
436 CopyMem (SsdtPtr, AcpiTableBuffer, AcpiTableBufferSize);
437 SsdtPtr += AcpiTableBufferSize;
438
439 //
440 // build "OperationRegion(FWDT, SystemMemory, 0x12345678, 0x87654321)"
441 //
442 *(SsdtPtr++) = 0x5B; // ExtOpPrefix
443 *(SsdtPtr++) = 0x80; // OpRegionOp
444 *(SsdtPtr++) = 'F';
445 *(SsdtPtr++) = 'W';
446 *(SsdtPtr++) = 'D';
447 *(SsdtPtr++) = 'T';
448 *(SsdtPtr++) = 0x00; // SystemMemory
449 *(SsdtPtr++) = 0x0C; // DWordPrefix
450
451 //
452 // no virtual addressing yet, take the four least significant bytes
453 //
454 CopyMem(SsdtPtr, &FwData, 4);
455 SsdtPtr += 4;
456
457 *(SsdtPtr++) = 0x0C; // DWordPrefix
458
459 *(UINT32*) SsdtPtr = sizeof (*FwData);
460 SsdtPtr += 4;
461
462 //
463 // add suspend system states
464 //
465 CopyMem (SsdtPtr, &SuspendToRam, SuspendToRamSize);
466 SsdtPtr += SuspendToRamSize;
467 CopyMem (SsdtPtr, &SuspendToDisk, SuspendToDiskSize);
468 SsdtPtr += SuspendToDiskSize;
469
470 ASSERT((UINTN) (SsdtPtr - Ssdt) == SsdtSize);
471 ((EFI_ACPI_DESCRIPTION_HEADER *) Ssdt)->Length = (UINT32) SsdtSize;
472 Status = InstallAcpiTable (AcpiProtocol, Ssdt, SsdtSize, TableKey);
473 }
474
475 FreePool(Ssdt);
476 }
477
478 if (Status != EFI_SUCCESS) {
479 FreePool(FwData);
480 }
481 }
482
483 return Status;
484 }
485
486
487 EFI_STATUS
488 EFIAPI
489 QemuInstallAcpiTable (
490 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
491 IN VOID *AcpiTableBuffer,
492 IN UINTN AcpiTableBufferSize,
493 OUT UINTN *TableKey
494 )
495 {
496 EFI_ACPI_DESCRIPTION_HEADER *Hdr;
497 EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;
498
499 Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AcpiTableBuffer;
500 switch (Hdr->Signature) {
501 case EFI_ACPI_1_0_APIC_SIGNATURE:
502 TableInstallFunction = QemuInstallAcpiMadtTable;
503 break;
504 case EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
505 TableInstallFunction = QemuInstallAcpiSsdtTable;
506 break;
507 default:
508 TableInstallFunction = InstallAcpiTable;
509 }
510
511 return TableInstallFunction (
512 AcpiProtocol,
513 AcpiTableBuffer,
514 AcpiTableBufferSize,
515 TableKey
516 );
517 }
518
519
520 /**
521 Check if an array of bytes starts with an RSD PTR structure.
522
523 Checksum is ignored.
524
525 @param[in] Buffer The array to check.
526
527 @param[in] Size Number of bytes in Buffer.
528
529 @param[out] RsdpSize If the function returns EFI_SUCCESS, this parameter
530 contains the size of the detected RSD PTR structure.
531
532 @retval EFI_SUCCESS RSD PTR structure detected at the beginning of
533 Buffer, and its advertised size does not exceed
534 Size.
535
536 @retval EFI_PROTOCOL_ERROR RSD PTR structure detected at the beginning of
537 Buffer, but it has inconsistent size.
538
539 @retval EFI_NOT_FOUND RSD PTR structure not found.
540
541 **/
542
543 STATIC
544 EFI_STATUS
545 CheckRsdp (
546 IN CONST VOID *Buffer,
547 IN UINTN Size,
548 OUT UINTN *RsdpSize
549 )
550 {
551 CONST UINT64 *Signature;
552 CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp1;
553 CONST EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp2;
554
555 if (Size < sizeof *Signature) {
556 return EFI_NOT_FOUND;
557 }
558 Signature = Buffer;
559
560 if (*Signature != EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) {
561 return EFI_NOT_FOUND;
562 }
563
564 //
565 // Signature found -- from this point on we can only report
566 // EFI_PROTOCOL_ERROR or EFI_SUCCESS.
567 //
568 if (Size < sizeof *Rsdp1) {
569 return EFI_PROTOCOL_ERROR;
570 }
571 Rsdp1 = Buffer;
572
573 if (Rsdp1->Reserved == 0) {
574 //
575 // ACPI 1.0 doesn't include the Length field
576 //
577 *RsdpSize = sizeof *Rsdp1;
578 return EFI_SUCCESS;
579 }
580
581 if (Size < sizeof *Rsdp2) {
582 return EFI_PROTOCOL_ERROR;
583 }
584 Rsdp2 = Buffer;
585
586 if (Size < Rsdp2->Length || Rsdp2->Length < sizeof *Rsdp2) {
587 return EFI_PROTOCOL_ERROR;
588 }
589
590 *RsdpSize = Rsdp2->Length;
591 return EFI_SUCCESS;
592 }
593
594 //
595 // We'll be saving the keys of installed tables so that we can roll them back
596 // in case of failure. 128 tables should be enough for anyone (TM).
597 //
598 #define INSTALLED_TABLES_MAX 128
599
600 /**
601 Download one ACPI table data file from QEMU and interpret it.
602
603 @param[in] FwCfgFile The NUL-terminated name of the fw_cfg file to
604 download and interpret.
605
606 @param[in] AcpiProtocol The ACPI table protocol used to install tables.
607
608 @param[in,out] InstalledKey On input, an array of INSTALLED_TABLES_MAX UINTN
609 elements, allocated by the caller. On output,
610 the function will have stored (appended) the
611 AcpiProtocol-internal keys of the ACPI tables
612 that the function has installed from the fw_cfg
613 file. The array reflects installed tables even
614 if the function returns with an error.
615
616 @param[in,out] NumInstalled On input, the number of entries already used in
617 InstalledKey; it must be in [0,
618 INSTALLED_TABLES_MAX] inclusive. On output, the
619 parameter is updated to the new cumulative count
620 of the keys stored in InstalledKey; the value
621 reflects installed tables even if the function
622 returns with an error.
623
624 @retval EFI_INVALID_PARAMETER NumInstalled is outside the allowed range on
625 input.
626
627 @retval EFI_UNSUPPORTED Firmware configuration is unavailable.
628
629 @retval EFI_NOT_FOUND The host doesn't export the requested fw_cfg
630 file.
631
632 @retval EFI_OUT_OF_RESOURCES Memory allocation failed, or no more room in
633 InstalledKey.
634
635 @retval EFI_PROTOCOL_ERROR Found truncated or invalid ACPI table header
636 in the fw_cfg contents.
637
638 @return Status codes returned by
639 AcpiProtocol->InstallAcpiTable().
640
641 **/
642
643 STATIC
644 EFI_STATUS
645 InstallQemuLinkedTables (
646 IN CONST CHAR8 *FwCfgFile,
647 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
648 IN OUT UINTN InstalledKey[INSTALLED_TABLES_MAX],
649 IN OUT INT32 *NumInstalled
650 )
651 {
652 EFI_STATUS Status;
653 FIRMWARE_CONFIG_ITEM TablesFile;
654 UINTN TablesFileSize;
655 UINT8 *Tables;
656 UINTN Processed;
657
658 if (*NumInstalled < 0 || *NumInstalled > INSTALLED_TABLES_MAX) {
659 return EFI_INVALID_PARAMETER;
660 }
661
662 Status = QemuFwCfgFindFile (FwCfgFile, &TablesFile, &TablesFileSize);
663 if (EFI_ERROR (Status)) {
664 DEBUG ((EFI_D_ERROR, "%a: \"%a\" unavailable: %r\n", __FUNCTION__,
665 FwCfgFile, Status));
666 return Status;
667 }
668
669 Tables = AllocatePool (TablesFileSize);
670 if (Tables == NULL) {
671 return EFI_OUT_OF_RESOURCES;
672 }
673
674 QemuFwCfgSelectItem (TablesFile);
675 QemuFwCfgReadBytes (TablesFileSize, Tables);
676
677 Processed = 0;
678 while (Processed < TablesFileSize) {
679 UINTN Remaining;
680 UINTN RsdpSize;
681 EFI_ACPI_DESCRIPTION_HEADER *Probe;
682
683 Remaining = TablesFileSize - Processed;
684
685 //
686 // See if we're looking at an RSD PTR structure.
687 //
688 RsdpSize = 0;
689 Status = CheckRsdp (Tables + Processed, Remaining, &RsdpSize);
690 if (Status == EFI_PROTOCOL_ERROR) {
691 //
692 // RSD PTR found but its size is inconsistent; abort processing. (Note
693 // that "RSD PTR found" excludes the NUL-padding case by definition.)
694 //
695 break;
696 }
697 if (!EFI_ERROR (Status)) {
698 //
699 // Consistent RSD PTR found, skip it.
700 //
701 DEBUG ((EFI_D_VERBOSE, "%a: \"%a\" offset 0x%016Lx: RSD PTR "
702 "Length=0x%08x\n", __FUNCTION__, FwCfgFile, (UINT64)Processed,
703 (UINT32)RsdpSize));
704 Processed += RsdpSize;
705 continue;
706 }
707 ASSERT (Status == EFI_NOT_FOUND);
708
709 //
710 // What we're looking at is not an RSD PTR structure; attempt to parse it
711 // as an ACPI table.
712 //
713 if (Remaining < sizeof *Probe) {
714 Status = EFI_PROTOCOL_ERROR;
715 break;
716 }
717
718 Probe = (EFI_ACPI_DESCRIPTION_HEADER *) (Tables + Processed);
719 if (Remaining < Probe->Length || Probe->Length < sizeof *Probe) {
720 Status = EFI_PROTOCOL_ERROR;
721 break;
722 }
723
724 DEBUG ((EFI_D_VERBOSE, "%a: \"%a\" offset 0x%016Lx:"
725 " Signature=\"%-4.4a\" Length=0x%08x\n",
726 __FUNCTION__, FwCfgFile, (UINT64) Processed,
727 (CONST CHAR8 *) &Probe->Signature, Probe->Length));
728
729 //
730 // skip automatically handled "root" tables: RSDT, XSDT
731 //
732 if (Probe->Signature !=
733 EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE &&
734 Probe->Signature !=
735 EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
736 if (*NumInstalled == INSTALLED_TABLES_MAX) {
737 DEBUG ((EFI_D_ERROR, "%a: can't install more than %d tables\n",
738 __FUNCTION__, INSTALLED_TABLES_MAX));
739 Status = EFI_OUT_OF_RESOURCES;
740 break;
741 }
742
743 Status = AcpiProtocol->InstallAcpiTable (AcpiProtocol, Probe,
744 Probe->Length, &InstalledKey[*NumInstalled]);
745 if (EFI_ERROR (Status)) {
746 DEBUG ((EFI_D_ERROR,
747 "%a: failed to install table \"%-4.4a\" at \"%a\" offset 0x%Lx: "
748 "%r\n", __FUNCTION__, (CONST CHAR8 *)&Probe->Signature, FwCfgFile,
749 (UINT64) Processed, Status));
750 break;
751 }
752
753 ++*NumInstalled;
754 }
755
756 Processed += Probe->Length;
757 }
758
759 //
760 // NUL-padding at the end is accepted
761 //
762 if (Status == EFI_PROTOCOL_ERROR) {
763 UINTN ErrorLocation;
764
765 ErrorLocation = Processed;
766 while (Processed < TablesFileSize && Tables[Processed] == '\0') {
767 ++Processed;
768 }
769 if (Processed < TablesFileSize) {
770 DEBUG ((EFI_D_ERROR, "%a: truncated or invalid ACPI table header at "
771 "\"%a\" offset 0x%Lx\n", __FUNCTION__, FwCfgFile,
772 (UINT64)ErrorLocation));
773 }
774 }
775
776 if (Processed == TablesFileSize) {
777 Status = EFI_SUCCESS;
778 } else {
779 ASSERT (EFI_ERROR (Status));
780 }
781
782 FreePool (Tables);
783 return Status;
784 }
785
786 /**
787 Download all ACPI table data files from QEMU and interpret them.
788
789 @param[in] AcpiProtocol The ACPI table protocol used to install tables.
790
791 @retval EFI_UNSUPPORTED Firmware configuration is unavailable.
792
793 @retval EFI_NOT_FOUND The host doesn't export the required fw_cfg
794 files.
795
796 @retval EFI_OUT_OF_RESOURCES Memory allocation failed, or more than
797 INSTALLED_TABLES_MAX tables found.
798
799 @retval EFI_PROTOCOL_ERROR Found invalid fw_cfg contents.
800
801 @return Status codes returned by
802 AcpiProtocol->InstallAcpiTable().
803
804 **/
805
806 EFI_STATUS
807 EFIAPI
808 InstallAllQemuLinkedTables (
809 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
810 )
811 {
812 UINTN *InstalledKey;
813 INT32 Installed;
814 EFI_STATUS Status;
815 FIRMWARE_CONFIG_ITEM LoaderItem;
816 UINTN LoaderSize;
817 UINT8 *Loader;
818 QEMU_LOADER_ENTRY *Entry, *End;
819
820 InstalledKey = AllocatePool (INSTALLED_TABLES_MAX * sizeof *InstalledKey);
821 if (InstalledKey == NULL) {
822 return EFI_OUT_OF_RESOURCES;
823 }
824 Installed = 0;
825
826 Status = QemuFwCfgFindFile ("etc/table-loader", &LoaderItem, &LoaderSize);
827 if (EFI_ERROR (Status)) {
828 goto FreeInstalledKey;
829 }
830 if (LoaderSize % sizeof *Entry != 0) {
831 Status = EFI_PROTOCOL_ERROR;
832 goto FreeInstalledKey;
833 }
834
835 Loader = AllocatePool (LoaderSize);
836 if (Loader == NULL) {
837 Status = EFI_OUT_OF_RESOURCES;
838 goto FreeInstalledKey;
839 }
840
841 QemuFwCfgSelectItem (LoaderItem);
842 QemuFwCfgReadBytes (LoaderSize, Loader);
843
844 Entry = (QEMU_LOADER_ENTRY *)Loader;
845 End = (QEMU_LOADER_ENTRY *)(Loader + LoaderSize);
846 while (Entry < End) {
847 if (Entry->Type == QemuLoaderCmdAllocate) {
848 QEMU_LOADER_ALLOCATE *Allocate;
849
850 Allocate = &Entry->Command.Allocate;
851 if (Allocate->File[sizeof Allocate->File - 1] != '\0') {
852 Status = EFI_PROTOCOL_ERROR;
853 break;
854 }
855
856 Status = InstallQemuLinkedTables ((CHAR8 *)Allocate->File, AcpiProtocol,
857 InstalledKey, &Installed);
858 if (EFI_ERROR (Status)) {
859 ASSERT (Status != EFI_INVALID_PARAMETER);
860 break;
861 }
862 }
863 ++Entry;
864 }
865
866 FreePool (Loader);
867
868 if (EFI_ERROR (Status)) {
869 //
870 // Roll back partial installation.
871 //
872 while (Installed > 0) {
873 --Installed;
874 AcpiProtocol->UninstallAcpiTable (AcpiProtocol, InstalledKey[Installed]);
875 }
876 } else {
877 DEBUG ((EFI_D_INFO, "%a: installed %d tables\n", __FUNCTION__, Installed));
878 }
879
880 FreeInstalledKey:
881 FreePool (InstalledKey);
882 return Status;
883 }