jljusten | 522203d | 2012-05-30 23:15:27 +0000 | [diff] [blame] | 1 | /** @file
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 2 | OVMF ACPI Xen support
|
jljusten | 522203d | 2012-05-30 23:15:27 +0000 | [diff] [blame] | 3 |
|
| 4 | Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 5 | Copyright (c) 2012, Bei Guan <gbtju85@gmail.com>
|
| 6 |
|
jljusten | 522203d | 2012-05-30 23:15:27 +0000 | [diff] [blame] | 7 | This program and the accompanying materials
|
| 8 | are licensed and made available under the terms and conditions of the BSD License
|
| 9 | which accompanies this distribution. The full text of the license may be found at
|
| 10 | http://opensource.org/licenses/bsd-license.php
|
| 11 |
|
| 12 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
| 13 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
| 14 |
|
| 15 | **/
|
| 16 |
|
| 17 | #include "AcpiPlatform.h"
|
| 18 | #include <Library/HobLib.h>
|
| 19 | #include <Guid/XenInfo.h>
|
jljusten | 4804ef4 | 2012-07-18 22:33:48 +0000 | [diff] [blame] | 20 | #include <Library/BaseLib.h>
|
jljusten | 522203d | 2012-05-30 23:15:27 +0000 | [diff] [blame] | 21 |
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 22 | #define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
|
| 23 | #define XEN_BIOS_PHYSICAL_END 0x000FFFFF
|
jljusten | 522203d | 2012-05-30 23:15:27 +0000 | [diff] [blame] | 24 |
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 25 | EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr = NULL;
|
| 26 |
|
| 27 | /**
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 28 | This function detects if OVMF is running on Xen.
|
| 29 |
|
| 30 | **/
|
jljusten | 522203d | 2012-05-30 23:15:27 +0000 | [diff] [blame] | 31 | BOOLEAN
|
| 32 | XenDetected (
|
| 33 | VOID
|
| 34 | )
|
| 35 | {
|
| 36 | EFI_HOB_GUID_TYPE *GuidHob;
|
| 37 |
|
| 38 | //
|
| 39 | // See if a XenInfo HOB is available
|
| 40 | //
|
| 41 | GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);
|
| 42 | if (GuidHob == NULL) {
|
| 43 | return FALSE;
|
| 44 | }
|
| 45 |
|
| 46 | return TRUE;
|
| 47 | }
|
| 48 |
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 49 | /**
|
| 50 | Get the address of Xen ACPI Root System Description Pointer (RSDP)
|
| 51 | structure.
|
jljusten | 522203d | 2012-05-30 23:15:27 +0000 | [diff] [blame] | 52 |
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 53 | @param RsdpStructurePtr Return pointer to RSDP structure
|
| 54 |
|
| 55 | @return EFI_SUCCESS Find Xen RSDP structure successfully.
|
| 56 | @return EFI_NOT_FOUND Don't find Xen RSDP structure.
|
| 57 | @return EFI_ABORTED Find Xen RSDP structure, but it's not integrated.
|
| 58 |
|
| 59 | **/
|
jljusten | 522203d | 2012-05-30 23:15:27 +0000 | [diff] [blame] | 60 | EFI_STATUS
|
| 61 | EFIAPI
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 62 | GetXenAcpiRsdp (
|
| 63 | OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr
|
jljusten | 522203d | 2012-05-30 23:15:27 +0000 | [diff] [blame] | 64 | )
|
| 65 | {
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 66 | EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr;
|
| 67 | UINT8 *XenAcpiPtr;
|
| 68 | UINT8 Sum;
|
| 69 |
|
| 70 | //
|
| 71 | // Detect the RSDP structure
|
| 72 | //
|
| 73 | for (XenAcpiPtr = (UINT8*)(UINTN) XEN_ACPI_PHYSICAL_ADDRESS;
|
| 74 | XenAcpiPtr < (UINT8*)(UINTN) XEN_BIOS_PHYSICAL_END;
|
| 75 | XenAcpiPtr += 0x10) {
|
| 76 |
|
| 77 | RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)
|
| 78 | (UINTN) XenAcpiPtr;
|
| 79 |
|
| 80 | if (!AsciiStrnCmp ((CHAR8 *) &RsdpStructurePtr->Signature, "RSD PTR ", 8)) {
|
| 81 | //
|
| 82 | // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.
|
| 83 | // This is only the first 20 bytes of the structure
|
| 84 | //
|
jljusten | 4804ef4 | 2012-07-18 22:33:48 +0000 | [diff] [blame] | 85 | Sum = CalculateSum8 (
|
| 86 | (CONST UINT8 *)RsdpStructurePtr,
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 87 | sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
|
| 88 | );
|
| 89 | if (Sum != 0) {
|
| 90 | return EFI_ABORTED;
|
| 91 | }
|
| 92 |
|
| 93 | if (RsdpStructurePtr->Revision >= 2) {
|
| 94 | //
|
| 95 | // RSDP ACPI 2.0/3.0 checksum, this is the entire table
|
| 96 | //
|
jljusten | 4804ef4 | 2012-07-18 22:33:48 +0000 | [diff] [blame] | 97 | Sum = CalculateSum8 (
|
| 98 | (CONST UINT8 *)RsdpStructurePtr,
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 99 | sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
|
| 100 | );
|
| 101 | if (Sum != 0) {
|
| 102 | return EFI_ABORTED;
|
| 103 | }
|
| 104 | }
|
| 105 | *RsdpPtr = RsdpStructurePtr;
|
| 106 | return EFI_SUCCESS;
|
| 107 | }
|
| 108 | }
|
| 109 |
|
| 110 | return EFI_NOT_FOUND;
|
| 111 | }
|
| 112 |
|
| 113 | /**
|
| 114 | Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
|
| 115 | into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
|
| 116 | ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.
|
| 117 |
|
| 118 | @param AcpiProtocol Protocol instance pointer.
|
| 119 |
|
| 120 | @return EFI_SUCCESS The table was successfully inserted.
|
| 121 | @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
|
| 122 | NULL, or AcpiTableBufferSize and the size
|
| 123 | field embedded in the ACPI table pointed to
|
| 124 | by AcpiTableBuffer are not in sync.
|
| 125 | @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
|
| 126 |
|
| 127 | **/
|
| 128 | EFI_STATUS
|
| 129 | EFIAPI
|
| 130 | InstallXenTables (
|
| 131 | IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
|
| 132 | )
|
| 133 | {
|
| 134 | EFI_STATUS Status;
|
| 135 | UINTN TableHandle;
|
| 136 |
|
| 137 | EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
|
| 138 | EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
|
| 139 | VOID *CurrentTableEntry;
|
| 140 | UINTN CurrentTablePointer;
|
| 141 | EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
|
| 142 | UINTN Index;
|
| 143 | UINTN NumberOfTableEntries;
|
| 144 | EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt2Table;
|
| 145 | EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt1Table;
|
| 146 | EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs2Table;
|
| 147 | EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs1Table;
|
| 148 | EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
|
| 149 |
|
| 150 | Fadt2Table = NULL;
|
| 151 | Fadt1Table = NULL;
|
| 152 | Facs2Table = NULL;
|
| 153 | Facs1Table = NULL;
|
| 154 | DsdtTable = NULL;
|
| 155 | TableHandle = 0;
|
| 156 | NumberOfTableEntries = 0;
|
| 157 |
|
| 158 | //
|
| 159 | // Try to find Xen ACPI tables
|
| 160 | //
|
| 161 | Status = GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr);
|
| 162 | if (EFI_ERROR (Status)) {
|
| 163 | return Status;
|
| 164 | }
|
| 165 |
|
| 166 | //
|
| 167 | // If XSDT table is find, just install its tables.
|
| 168 | // Otherwise, try to find and install the RSDT tables.
|
| 169 | //
|
| 170 | if (XenAcpiRsdpStructurePtr->XsdtAddress) {
|
| 171 | //
|
| 172 | // Retrieve the addresses of XSDT and
|
| 173 | // calculate the number of its table entries.
|
| 174 | //
|
| 175 | Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)
|
| 176 | XenAcpiRsdpStructurePtr->XsdtAddress;
|
| 177 | NumberOfTableEntries = (Xsdt->Length -
|
| 178 | sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
|
| 179 | sizeof (UINT64);
|
| 180 |
|
| 181 | //
|
| 182 | // Install ACPI tables found in XSDT.
|
| 183 | //
|
| 184 | for (Index = 0; Index < NumberOfTableEntries; Index++) {
|
| 185 | //
|
| 186 | // Get the table entry from XSDT
|
| 187 | //
|
| 188 | CurrentTableEntry = (VOID *) ((UINT8 *) Xsdt +
|
| 189 | sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
|
| 190 | Index * sizeof (UINT64));
|
jljusten | 26af9ac | 2012-08-09 23:27:05 +0000 | [diff] [blame] | 191 | CurrentTablePointer = (UINTN) *(UINT64 *)CurrentTableEntry;
|
jljusten | 377e758 | 2012-07-18 22:33:33 +0000 | [diff] [blame] | 192 | CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;
|
| 193 |
|
| 194 | //
|
| 195 | // Install the XSDT tables
|
| 196 | //
|
| 197 | Status = InstallAcpiTable (
|
| 198 | AcpiProtocol,
|
| 199 | CurrentTable,
|
| 200 | CurrentTable->Length,
|
| 201 | &TableHandle
|
| 202 | );
|
| 203 |
|
| 204 | if (EFI_ERROR (Status)) {
|
| 205 | return Status;
|
| 206 | }
|
| 207 |
|
| 208 | //
|
| 209 | // Get the FACS and DSDT table address from the table FADT
|
| 210 | //
|
| 211 | if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {
|
| 212 | Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)
|
| 213 | (UINTN) CurrentTablePointer;
|
| 214 | Facs2Table = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)
|
| 215 | (UINTN) Fadt2Table->FirmwareCtrl;
|
| 216 | DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt2Table->Dsdt;
|
| 217 | }
|
| 218 | }
|
| 219 | }
|
| 220 | else if (XenAcpiRsdpStructurePtr->RsdtAddress) {
|
| 221 | //
|
| 222 | // Retrieve the addresses of RSDT and
|
| 223 | // calculate the number of its table entries.
|
| 224 | //
|
| 225 | Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)
|
| 226 | XenAcpiRsdpStructurePtr->RsdtAddress;
|
| 227 | NumberOfTableEntries = (Rsdt->Length -
|
| 228 | sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
|
| 229 | sizeof (UINT32);
|
| 230 |
|
| 231 | //
|
| 232 | // Install ACPI tables found in XSDT.
|
| 233 | //
|
| 234 | for (Index = 0; Index < NumberOfTableEntries; Index++) {
|
| 235 | //
|
| 236 | // Get the table entry from RSDT
|
| 237 | //
|
| 238 | CurrentTableEntry = (UINT32 *) ((UINT8 *) Rsdt +
|
| 239 | sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
|
| 240 | Index * sizeof (UINT32));
|
| 241 | CurrentTablePointer = *(UINT32 *)CurrentTableEntry;
|
| 242 | CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;
|
| 243 |
|
| 244 | //
|
| 245 | // Install the RSDT tables
|
| 246 | //
|
| 247 | Status = InstallAcpiTable (
|
| 248 | AcpiProtocol,
|
| 249 | CurrentTable,
|
| 250 | CurrentTable->Length,
|
| 251 | &TableHandle
|
| 252 | );
|
| 253 |
|
| 254 | if (EFI_ERROR (Status)) {
|
| 255 | return Status;
|
| 256 | }
|
| 257 |
|
| 258 | //
|
| 259 | // Get the FACS and DSDT table address from the table FADT
|
| 260 | //
|
| 261 | if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {
|
| 262 | Fadt1Table = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *)
|
| 263 | (UINTN) CurrentTablePointer;
|
| 264 | Facs1Table = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)
|
| 265 | (UINTN) Fadt1Table->FirmwareCtrl;
|
| 266 | DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt1Table->Dsdt;
|
| 267 | }
|
| 268 | }
|
| 269 | }
|
| 270 |
|
| 271 | //
|
| 272 | // Install the FACS table.
|
| 273 | //
|
| 274 | if (Fadt2Table) {
|
| 275 | //
|
| 276 | // FACS 2.0
|
| 277 | //
|
| 278 | Status = InstallAcpiTable (
|
| 279 | AcpiProtocol,
|
| 280 | Facs2Table,
|
| 281 | Facs2Table->Length,
|
| 282 | &TableHandle
|
| 283 | );
|
| 284 | if (EFI_ERROR (Status)) {
|
| 285 | return Status;
|
| 286 | }
|
| 287 | }
|
| 288 | else if (Fadt1Table) {
|
| 289 | //
|
| 290 | // FACS 1.0
|
| 291 | //
|
| 292 | Status = InstallAcpiTable (
|
| 293 | AcpiProtocol,
|
| 294 | Facs1Table,
|
| 295 | Facs1Table->Length,
|
| 296 | &TableHandle
|
| 297 | );
|
| 298 | if (EFI_ERROR (Status)) {
|
| 299 | return Status;
|
| 300 | }
|
| 301 | }
|
| 302 |
|
| 303 | //
|
| 304 | // Install DSDT table.
|
| 305 | //
|
| 306 | Status = InstallAcpiTable (
|
| 307 | AcpiProtocol,
|
| 308 | DsdtTable,
|
| 309 | DsdtTable->Length,
|
| 310 | &TableHandle
|
| 311 | );
|
| 312 | if (EFI_ERROR (Status)) {
|
| 313 | return Status;
|
| 314 | }
|
| 315 |
|
| 316 | return EFI_SUCCESS;
|
jljusten | 522203d | 2012-05-30 23:15:27 +0000 | [diff] [blame] | 317 | }
|
| 318 |
|