]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/AcpiPlatformDxe/CloudHvAcpi.c
OvmfPkg/AcpiPlatformDxe: Return error if installing NotifyProtocol failed
[mirror_edk2.git] / OvmfPkg / AcpiPlatformDxe / CloudHvAcpi.c
1 /** @file
2 OVMF ACPI Cloud Hypervisor support
3
4 Copyright (c) 2021, Intel Corporation. All rights reserved.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <IndustryStandard/Acpi.h> // EFI_ACPI_DESCRIPTION_HEADER
11 #include <IndustryStandard/CloudHv.h> // CLOUDHV_RSDP_ADDRESS
12 #include <IndustryStandard/Xen/arch-x86/hvm/start_info.h> // hvm_start_info
13 #include <Library/BaseLib.h> // CpuDeadLoop()
14 #include <Library/DebugLib.h> // DEBUG()
15 #include <Library/PcdLib.h> // PcdGet32()
16 #include <Library/HobLib.h> // GetFirstGuidHob(), GetNextGuidHob()
17 #include <Library/UefiBootServicesTableLib.h> // gBS
18 #include <Protocol/AcpiSystemDescriptionTable.h>
19 #include <Protocol/AcpiTable.h>
20
21 #include "AcpiPlatform.h"
22
23 EFI_STATUS
24 EFIAPI
25 InstallCloudHvTablesTdx (
26 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
27 )
28 {
29 EFI_STATUS Status;
30 UINTN TableHandle;
31 EFI_HANDLE ChAcpiHandle;
32
33 EFI_PEI_HOB_POINTERS Hob;
34 EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
35 EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
36
37 DsdtTable = NULL;
38 TableHandle = 0;
39
40 Hob.Guid = (EFI_HOB_GUID_TYPE *)GetFirstGuidHob (&gUefiOvmfPkgTdxAcpiHobGuid);
41
42 while (Hob.Guid != NULL) {
43 CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)(&Hob.Guid->Name + 1);
44 if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "DSDT", 4)) {
45 DsdtTable = CurrentTable;
46 } else {
47 //
48 // Install the tables
49 //
50 Status = AcpiProtocol->InstallAcpiTable (
51 AcpiProtocol,
52 CurrentTable,
53 CurrentTable->Length,
54 &TableHandle
55 );
56 for (UINTN i = 0; i < CurrentTable->Length; i++) {
57 DEBUG ((DEBUG_INFO, " %x", *((UINT8 *)CurrentTable + i)));
58 }
59
60 DEBUG ((DEBUG_INFO, "\n"));
61 }
62
63 Hob.Raw = GET_NEXT_HOB (Hob.Raw);
64 Hob.Guid = (EFI_HOB_GUID_TYPE *)GetNextGuidHob (&gUefiOvmfPkgTdxAcpiHobGuid, Hob.Raw);
65 }
66
67 //
68 // Install DSDT table. If we reached this point without finding the DSDT,
69 // then we're out of sync with the hypervisor, and cannot continue.
70 //
71 if (DsdtTable == NULL) {
72 DEBUG ((DEBUG_INFO, "%a: no DSDT found\n", __FUNCTION__));
73 ASSERT (FALSE);
74 }
75
76 Status = AcpiProtocol->InstallAcpiTable (
77 AcpiProtocol,
78 DsdtTable,
79 DsdtTable->Length,
80 &TableHandle
81 );
82 if (EFI_ERROR (Status)) {
83 ASSERT_EFI_ERROR (Status);
84 return Status;
85 }
86
87 //
88 // Install a protocol to notify that the ACPI table provided by CH is
89 // ready.
90 //
91 ChAcpiHandle = NULL;
92 Status = gBS->InstallProtocolInterface (
93 &ChAcpiHandle,
94 &gQemuAcpiTableNotifyProtocolGuid,
95 EFI_NATIVE_INTERFACE,
96 NULL
97 );
98 if (EFI_ERROR (Status)) {
99 ASSERT_EFI_ERROR (Status);
100 return Status;
101 }
102
103 return EFI_SUCCESS;
104 }
105
106 // Get the ACPI tables from EBDA start
107 EFI_STATUS
108 EFIAPI
109 InstallCloudHvTables (
110 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
111 )
112 {
113 EFI_STATUS Status;
114 UINTN TableHandle;
115
116 EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
117 VOID *CurrentTableEntry;
118 UINTN CurrentTablePointer;
119 EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
120 UINTN Index;
121 UINTN NumberOfTableEntries;
122 EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt2Table;
123 EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
124 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *AcpiRsdpStructurePtr;
125 UINT32 *PVHResetVectorData;
126 struct hvm_start_info *pvh_start_info;
127
128 Fadt2Table = NULL;
129 DsdtTable = NULL;
130 TableHandle = 0;
131 NumberOfTableEntries = 0;
132 AcpiRsdpStructurePtr = NULL;
133 PVHResetVectorData = NULL;
134 pvh_start_info = NULL;
135
136 PVHResetVectorData = (VOID *)(UINTN)PcdGet32 (PcdXenPvhStartOfDayStructPtr);
137 if (PVHResetVectorData == 0) {
138 return EFI_NOT_FOUND;
139 }
140
141 pvh_start_info = (struct hvm_start_info *)(UINTN)PVHResetVectorData[0];
142 AcpiRsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)pvh_start_info->rsdp_paddr;
143
144 // If XSDT table is found, just install its tables.
145 // Otherwise, try to find and install the RSDT tables.
146 //
147 if (AcpiRsdpStructurePtr->XsdtAddress) {
148 //
149 // Retrieve the addresses of XSDT and
150 // calculate the number of its table entries.
151 //
152 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)
153 AcpiRsdpStructurePtr->XsdtAddress;
154 NumberOfTableEntries = (Xsdt->Length -
155 sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
156 sizeof (UINT64);
157
158 //
159 // Install ACPI tables found in XSDT.
160 //
161 for (Index = 0; Index < NumberOfTableEntries; Index++) {
162 //
163 // Get the table entry from XSDT
164 //
165 CurrentTableEntry = (VOID *)((UINT8 *)Xsdt +
166 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
167 Index * sizeof (UINT64));
168 CurrentTablePointer = (UINTN)*(UINT64 *)CurrentTableEntry;
169 CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;
170
171 //
172 // Install the XSDT tables
173 //
174 Status = AcpiProtocol->InstallAcpiTable (
175 AcpiProtocol,
176 CurrentTable,
177 CurrentTable->Length,
178 &TableHandle
179 );
180
181 if (EFI_ERROR (Status)) {
182 ASSERT_EFI_ERROR (Status);
183 return Status;
184 }
185
186 //
187 // Get the X-DSDT table address from the table FADT
188 //
189 if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {
190 Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)
191 (UINTN)CurrentTablePointer;
192 DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt2Table->XDsdt;
193 }
194 }
195 } else {
196 return EFI_NOT_FOUND;
197 }
198
199 //
200 // Install DSDT table. If we reached this point without finding the DSDT,
201 // then we're out of sync with the hypervisor, and cannot continue.
202 //
203 if (DsdtTable == NULL) {
204 DEBUG ((DEBUG_ERROR, "%a: no DSDT found\n", __FUNCTION__));
205 ASSERT (FALSE);
206 CpuDeadLoop ();
207 }
208
209 Status = AcpiProtocol->InstallAcpiTable (
210 AcpiProtocol,
211 DsdtTable,
212 DsdtTable->Length,
213 &TableHandle
214 );
215 if (EFI_ERROR (Status)) {
216 ASSERT_EFI_ERROR (Status);
217 return Status;
218 }
219
220 return EFI_SUCCESS;
221 }