github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/acpi/vmm_acpi.c (about) 1 /* 2 * Copyright (c) 2013 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15 #include "vmm_defs.h" 16 #include "vmm_dbg.h" 17 #include "libc.h" 18 #include "host_memory_manager_api.h" 19 #include "file_codes.h" 20 #include "vmm_acpi.h" 21 #define VMM_DEADLOOP() VMM_DEADLOOP_LOG(VMM_ACPI_C) 22 #define VMM_ASSERT(__condition) VMM_ASSERT_LOG(VMM_ACPI_C, __condition) 23 #ifdef JLMDEBUG 24 #include "jlmdebug.h" 25 #endif 26 27 28 #ifdef USE_ACPI 29 30 static ACPI_TABLE_FADT fadt; // locally stored FADT 31 static char sleep_conversion_table[ACPI_PM1_CNTRL_REG_COUNT][ACPI_S_STATE_COUNT] = { 0 }; 32 33 #pragma warning (push) 34 #pragma warning (disable : 4100) 35 void vmm_acpi_print_header(ACPI_TABLE_HEADER *pTableHeader) 36 { 37 VMM_LOG(mask_anonymous, level_trace,"==============Header===============\n"); 38 VMM_LOG(mask_anonymous, level_trace,"Signature = %c%c%c%c\n", 39 pTableHeader->Signature[0], pTableHeader->Signature[1], 40 pTableHeader->Signature[2], pTableHeader->Signature[3]); 41 VMM_LOG(mask_anonymous, level_trace,"Length = 0x%x\n", pTableHeader->Length); 42 VMM_LOG(mask_anonymous, level_trace,"Revision = %d\n", pTableHeader->Revision); 43 VMM_LOG(mask_anonymous, level_trace,"Checksum = 0x%x\n", pTableHeader->Checksum); 44 VMM_LOG(mask_anonymous, level_trace,"OemId = %c%c%c%c%c%c\n", 45 pTableHeader->OemId[0], pTableHeader->OemId[1], 46 pTableHeader->OemId[2], pTableHeader->OemId[3], 47 pTableHeader->OemId[4], pTableHeader->OemId[5]); 48 VMM_LOG(mask_anonymous, level_trace,"OemTableId = %c%c%c%c%c%c%c%c\n", 49 pTableHeader->OemTableId[0], pTableHeader->OemTableId[1], 50 pTableHeader->OemTableId[2], pTableHeader->OemTableId[3], 51 pTableHeader->OemTableId[4], pTableHeader->OemTableId[5], 52 pTableHeader->OemTableId[6], pTableHeader->OemTableId[7]); 53 VMM_LOG(mask_anonymous, level_trace,"OemRevision = %d\n", pTableHeader->OemRevision); 54 VMM_LOG(mask_anonymous, level_trace,"AslCompilerId = %c%c%c%c\n", 55 pTableHeader->AslCompilerId[0], pTableHeader->AslCompilerId[1], 56 pTableHeader->AslCompilerId[2], pTableHeader->AslCompilerId[3]); 57 VMM_LOG(mask_anonymous, level_trace,"AslCompilerRevision= %d\n", pTableHeader->AslCompilerRevision); 58 VMM_LOG(mask_anonymous, level_trace,"-----------------------------------\n"); 59 } 60 61 void vmm_acpi_print_fadt(ACPI_TABLE_FADT *fadt) 62 { 63 VMM_LOG(mask_anonymous, level_trace,"===============FADT================\n"); 64 vmm_acpi_print_header(&fadt->Header); 65 VMM_LOG(mask_anonymous, level_trace,"Facs : %p\n", fadt->Facs); 66 VMM_LOG(mask_anonymous, level_trace,"Dsdt : %p\n", fadt->Dsdt); 67 VMM_LOG(mask_anonymous, level_trace,"Model : %d\n", fadt->Model); 68 VMM_LOG(mask_anonymous, level_trace,"PreferredProfile : %d\n", fadt->PreferredProfile); 69 VMM_LOG(mask_anonymous, level_trace,"SciInterrupt : 0x%x\n", fadt->SciInterrupt); 70 VMM_LOG(mask_anonymous, level_trace,"SmiCommand : 0x%x\n", fadt->SmiCommand); 71 VMM_LOG(mask_anonymous, level_trace,"AcpiEnable : 0x%x\n", fadt->AcpiEnable); 72 VMM_LOG(mask_anonymous, level_trace,"AcpiDisable : 0x%x\n", fadt->AcpiDisable); 73 VMM_LOG(mask_anonymous, level_trace,"S4BiosRequest : 0x%x\n", fadt->S4BiosRequest); 74 VMM_LOG(mask_anonymous, level_trace,"PstateControl : 0x%x\n", fadt->PstateControl); 75 VMM_LOG(mask_anonymous, level_trace,"Pm1aEventBlock : 0x%x\n", fadt->Pm1aEventBlock); 76 VMM_LOG(mask_anonymous, level_trace,"Pm1aEventBlock : 0x%x\n", fadt->Pm1aEventBlock); 77 VMM_LOG(mask_anonymous, level_trace,"Pm1bEventBlock : 0x%x\n", fadt->Pm1bEventBlock); 78 VMM_LOG(mask_anonymous, level_trace,"Pm1aControlBlock : 0x%x\n", fadt->Pm1aControlBlock); 79 VMM_LOG(mask_anonymous, level_trace,"Pm1bControlBlock : 0x%x\n", fadt->Pm1bControlBlock); 80 VMM_LOG(mask_anonymous, level_trace,"Pm2ControlBlock : 0x%x\n", fadt->Pm2ControlBlock); 81 VMM_LOG(mask_anonymous, level_trace,"PmTimerBlock : 0x%x\n", fadt->PmTimerBlock); 82 VMM_LOG(mask_anonymous, level_trace,"Gpe0Block : 0x%x\n", fadt->Gpe0Block); 83 VMM_LOG(mask_anonymous, level_trace,"Gpe1Block : 0x%x\n", fadt->Gpe1Block); 84 VMM_LOG(mask_anonymous, level_trace,"Pm1EventLength : 0x%x\n", fadt->Pm1EventLength); 85 VMM_LOG(mask_anonymous, level_trace,"Pm1ControlLength : 0x%x\n", fadt->Pm1ControlLength); 86 VMM_LOG(mask_anonymous, level_trace,"Pm2ControlLength : 0x%x\n", fadt->Pm2ControlLength); 87 VMM_LOG(mask_anonymous, level_trace,"PmTimerLength : 0x%x\n", fadt->PmTimerLength); 88 VMM_LOG(mask_anonymous, level_trace,"Gpe0BlockLength : 0x%x\n", fadt->Gpe0BlockLength); 89 VMM_LOG(mask_anonymous, level_trace,"Gpe1BlockLength : 0x%x\n", fadt->Gpe1BlockLength); 90 VMM_LOG(mask_anonymous, level_trace,"Gpe1Base : 0x%x\n", fadt->Gpe1Base); 91 VMM_LOG(mask_anonymous, level_trace,"CstControl : 0x%x\n", fadt->CstControl); 92 VMM_LOG(mask_anonymous, level_trace,"C2Latency : 0x%x\n", fadt->C2Latency); 93 VMM_LOG(mask_anonymous, level_trace,"C3Latency : 0x%x\n", fadt->C3Latency); 94 VMM_LOG(mask_anonymous, level_trace,"FlushSize : 0x%x\n", fadt->FlushSize); 95 VMM_LOG(mask_anonymous, level_trace,"FlushStride : 0x%x\n", fadt->FlushStride); 96 VMM_LOG(mask_anonymous, level_trace,"DutyOffset : 0x%x\n", fadt->DutyOffset); 97 VMM_LOG(mask_anonymous, level_trace,"DutyWidth : 0x%x\n", fadt->DutyWidth); 98 VMM_LOG(mask_anonymous, level_trace,"DayAlarm : 0x%x\n", fadt->DayAlarm); 99 VMM_LOG(mask_anonymous, level_trace,"MonthAlarm : 0x%x\n", fadt->MonthAlarm); 100 VMM_LOG(mask_anonymous, level_trace,"Century : 0x%x\n", fadt->Century); 101 VMM_LOG(mask_anonymous, level_trace,"BootFlags : 0x%x\n", fadt->BootFlags); 102 VMM_LOG(mask_anonymous, level_trace,"Flags : 0x%x\n", fadt->Flags); 103 VMM_LOG(mask_anonymous, level_trace,"ResetRegister : 0x%x\n", fadt->ResetRegister); 104 VMM_LOG(mask_anonymous, level_trace,"ResetValue : 0x%x\n", fadt->ResetValue); 105 VMM_LOG(mask_anonymous, level_trace,"XFacs : 0x%x\n", fadt->XFacs); 106 VMM_LOG(mask_anonymous, level_trace,"XDsdt : 0x%x\n", fadt->XDsdt); 107 VMM_LOG(mask_anonymous, level_trace,"XPm1aEventBlock : 0x%x\n", fadt->XPm1aEventBlock); 108 VMM_LOG(mask_anonymous, level_trace,"XPm1bEventBlock : 0x%x\n", fadt->XPm1bEventBlock); 109 VMM_LOG(mask_anonymous, level_trace,"XPm1aControlBlock : 0x%x\n", fadt->XPm1aControlBlock); 110 VMM_LOG(mask_anonymous, level_trace,"XPm1bControlBlock : 0x%x\n", fadt->XPm1bControlBlock); 111 VMM_LOG(mask_anonymous, level_trace,"XPm2ControlBlock : 0x%x\n", fadt->XPm2ControlBlock); 112 VMM_LOG(mask_anonymous, level_trace,"XPm2ControlBlock : 0x%x\n", fadt->XPm2ControlBlock); 113 VMM_LOG(mask_anonymous, level_trace,"XPmTimerBlock : 0x%x\n", fadt->XPmTimerBlock); 114 VMM_LOG(mask_anonymous, level_trace,"XGpe0Block : 0x%x\n", fadt->XGpe0Block); 115 VMM_LOG(mask_anonymous, level_trace,"XGpe1Block : 0x%x\n", fadt->XGpe1Block); 116 VMM_LOG(mask_anonymous, level_trace,"===================================\n"); 117 } 118 119 120 void vmm_acpi_print_facs(ACPI_TABLE_FACS *facs) 121 { 122 VMM_LOG(mask_anonymous, level_trace,"===============FACS================\n"); 123 VMM_LOG(mask_anonymous, level_trace,"Signature : %c%c%c%c\n", 124 facs->Signature[0], 125 facs->Signature[1], 126 facs->Signature[2], 127 facs->Signature[3]); 128 VMM_LOG(mask_anonymous, level_trace,"Length : %d\n", facs->Length); 129 VMM_LOG(mask_anonymous, level_trace,"HardwareSignature : 0x%x\n", facs->HardwareSignature); 130 VMM_LOG(mask_anonymous, level_trace,"FirmwareWakingVector : 0x%x\n", facs->FirmwareWakingVector); 131 VMM_LOG(mask_anonymous, level_trace,"Flags : 0x%x\n", facs->Flags); 132 VMM_LOG(mask_anonymous, level_trace,"XFirmwareWakingVector : 0x%x\n", facs->XFirmwareWakingVector); 133 VMM_LOG(mask_anonymous, level_trace,"Version : %d\n", facs->Version); 134 } 135 #pragma warning (pop) 136 137 INLINE VOID *acpi_map_memory(UINT64 where) 138 { 139 HVA hva; 140 hmm_hpa_to_hva((HPA) where, &hva); 141 return (void*) hva; 142 } 143 144 /* Calculate acpi table checksum */ 145 INLINE UINT8 checksum(UINT8 * buffer, UINT32 length) 146 { 147 int sum = 0; 148 UINT8 *i = buffer; 149 buffer += length; 150 for (; i < buffer; sum += *(i++)) ; 151 return (char) sum; 152 } 153 154 /* Scan for RSDP table and return mapped address of rsdp, if found */ 155 INLINE ACPI_TABLE_RSDP *scan_for_rsdp(void *addr, UINT32 length) 156 { 157 ACPI_TABLE_RSDP *rsdp, *result = NULL; 158 unsigned char *begin; 159 unsigned char *i, *end; 160 161 begin = addr; 162 end = begin + length; 163 164 /* Search from given start address for the requested length */ 165 for (i = begin; i < end; i += ACPI_RSDP_SCAN_STEP) { 166 /* The signature and checksum must both be correct */ 167 if (vmm_memcmp((char *)i, "RSD PTR ", 8)) { 168 continue; 169 } 170 171 VMM_LOG(mask_anonymous, level_trace,"Got the rsdp header, now check the checksum\n"); 172 rsdp = (ACPI_TABLE_RSDP *)i; 173 174 /* Signature matches, check the appropriate checksum */ 175 if (!checksum((unsigned char *)rsdp, (rsdp->Revision < 2) ? 176 ACPI_RSDP_CHECKSUM_LENGTH : 177 ACPI_RSDP_XCHECKSUM_LENGTH)) { 178 /* Checksum valid, we have found a valid RSDP */ 179 VMM_LOG(mask_anonymous, level_trace,"Found acpi rsdp table\n"); 180 result = rsdp; 181 break; 182 } 183 } 184 return(result); 185 } 186 187 188 /* Find an acpi table with specified signature and return mapped address */ 189 INLINE ACPI_TABLE_HEADER * get_acpi_table_from_rsdp(ACPI_TABLE_RSDP *rsdp, char *sig) 190 { 191 ACPI_TABLE_HEADER *sdt = NULL; 192 ACPI_TABLE_HEADER *tbl = NULL; 193 int xsdt = 1; 194 int i; 195 int num; 196 char *offset; 197 198 /* Get xsdt pointer */ 199 if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress) { 200 VMM_LOG(mask_anonymous, level_trace,"rsdp->xsdt_physical_address %lx\n", 201 rsdp->XsdtPhysicalAddress); 202 sdt = acpi_map_memory(rsdp->XsdtPhysicalAddress); 203 } 204 205 /* Or get rsdt */ 206 if (!sdt && rsdp->RsdtPhysicalAddress) { 207 xsdt = 0; 208 VMM_LOG(mask_anonymous, level_trace,"rsdp->rsdt_physical_address = %x\n", 209 rsdp->RsdtPhysicalAddress); 210 sdt = acpi_map_memory(rsdp->RsdtPhysicalAddress); 211 } 212 213 /* Check if the rsdt/xsdt table pointer is NULL */ 214 if (NULL == sdt) { 215 VMM_LOG(mask_anonymous, level_error,"Map rsdt/xsdt error\n"); 216 return NULL; 217 } 218 219 /* Make sure the table checksum is correct */ 220 if (checksum((unsigned char *)sdt, sdt->Length)) { 221 VMM_LOG(mask_anonymous, level_error,"Wrong checksum in %s!\n", (xsdt)?"XSDT":"RSDT"); 222 return NULL; 223 } 224 225 VMM_LOG(mask_anonymous, level_trace,"xsdt/rsdt checksum verified!\n"); 226 227 /* Calculate the number of table pointers in the xsdt or rsdt table */ 228 num = (sdt->Length - sizeof(ACPI_TABLE_HEADER))/ 229 ((xsdt) ? sizeof(UINT64) : sizeof(UINT32)); 230 231 VMM_LOG(mask_anonymous, level_trace,"The number of table pointers in xsdt/rsdt = %d\n", 232 num); 233 234 /* Get to the table pointer area */ 235 offset = (char *)sdt + sizeof(ACPI_TABLE_HEADER); 236 237 /* Traverse the pointer list to get the desired acpi table */ 238 for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(UINT64) : sizeof(UINT32))) { 239 /* Get the address from the pointer entry */ 240 tbl= acpi_map_memory((UINT64) ((xsdt) ? (*(UINT64 *)offset):(*(UINT32 *)offset))); 241 242 /* Make sure address is valid */ 243 if (!tbl) { 244 continue; 245 } 246 247 VMM_LOG(mask_anonymous, level_trace,"Mapped ACPI table addr = %p, ", tbl); 248 VMM_LOG(mask_anonymous, level_trace,"Signature = %c%c%c%c\n", 249 tbl->Signature[0], 250 tbl->Signature[1], 251 tbl->Signature[2], 252 tbl->Signature[3]); 253 254 /* Verify table signature & table checksum */ 255 if ((0 == vmm_memcmp(tbl->Signature, sig, 4)) && 256 !checksum((unsigned char *)tbl, tbl->Length)) { 257 /* Found the table with matched signature */ 258 VMM_LOG(mask_anonymous, level_trace,"Found the table %s address = %p length = %x\n", sig, tbl, tbl->Length); 259 260 return tbl; 261 } 262 } 263 VMM_LOG(mask_anonymous, level_error,"Could not find %s table in XSDT/RSDT\n", sig); 264 return NULL; 265 } 266 267 ACPI_TABLE_HEADER * vmm_acpi_locate_table(char *sig) 268 { 269 ACPI_TABLE_RSDP *rsdp = NULL; 270 void *table = NULL; 271 272 /* Try 0x0 first for getting rsdp table */ 273 rsdp = scan_for_rsdp(acpi_map_memory(0), 0x400); 274 if (NULL == rsdp) { 275 /* Try 0xE0000 */ 276 VMM_LOG(mask_anonymous, level_trace,"Try 0xE0000 for ACPI RSDP table\n"); 277 rsdp = scan_for_rsdp(acpi_map_memory(0xE0000), 0x1FFFF); 278 } 279 280 if (NULL == rsdp) { 281 VMM_LOG(mask_anonymous, level_error,"Could not find the rsdp table\n"); 282 return NULL; 283 } 284 285 VMM_LOG(mask_anonymous, level_trace,"rsdp address %p\n", rsdp); 286 287 /* Get the specified table from rsdp */ 288 table = get_acpi_table_from_rsdp(rsdp, sig); 289 return table; 290 } 291 292 293 // SLP_TYP values are programmed in PM1A and PM1B control block registers 294 // to initiate power transition. Each Sx state has a corresponding SLP_TYP value. 295 // SLP_TYP values are stored in DSDT area of ACPI tables as AML packages 296 // Following code searches for these packages to retreive the SLP_TYPs 297 // 298 // Search for '_SX_' to get to start of package. 'X' stands for sleep state e.g. '_S3_' 299 // If '_SX_' is not found then it means the system does not support that sleep state. 300 // _SX_packages are in the following format 301 // 1 byte : Package Op (0x12) 302 // 1 byte 303 // + 'Package Length' size : 'Package Length' field. Refer ACPI spec for 304 // 'Package Length Encoding' High 2 bits of first byte 305 // indicates how many bytes are used by 'Package Length' 306 // If 0, then only the first byte is used 307 // If > 0 then following bytes (max 3) will be also used 308 // 309 // 1 byte : 'Number of Elements' 310 // 311 // 1 byte optional : There may be an optional 'Byte Prefix' (0x0A) present. 312 // 313 // 1 byte SLP_TYP_A : SLP_TYP value for PM1A control block 314 // 315 // 1 byte optional : There may be an optional 'Byte Prefix' (0x0A) present. 316 // 317 // 1 byte SLP_TYP_B : SLP_TYP value for PM1B control block 318 // 319 // Remaining bytes are ignored. 320 // 321 void vmm_acpi_retrieve_sleep_states(void) 322 { 323 ACPI_TABLE_HEADER *dsdt; 324 char *aml_ptr; 325 UINT8 sstate; 326 UINT32 i; 327 328 dsdt = acpi_map_memory((UINT64) fadt.Dsdt); 329 if (!dsdt) { 330 VMM_LOG(mask_anonymous, level_error,"[ACPI] DSDT not found\n"); 331 return; 332 } 333 334 VMM_LOG(mask_anonymous, level_trace,"SleepState | SleepTypeA | SleepTypeB\n"); 335 VMM_LOG(mask_anonymous, level_trace,"------------------------------------\n"); 336 337 for (sstate = ACPI_STATE_S0; sstate < ACPI_S_STATE_COUNT; ++sstate) { 338 aml_ptr = (char *) (dsdt + sizeof(ACPI_TABLE_HEADER)); 339 340 sleep_conversion_table[ACPI_PM1_CNTRL_REG_A][sstate] = 0xff; 341 sleep_conversion_table[ACPI_PM1_CNTRL_REG_B][sstate] = 0xff; 342 343 //Search for '_SX_' string where 'X' is the sleep state e.g. '_S3_' 344 for (i = 0; i < dsdt->Length - 8; i++) { 345 if (aml_ptr[0] == '_' && aml_ptr[1] == 'S' && aml_ptr[2] == ('0' + sstate) && aml_ptr[3] == '_') 346 break; 347 aml_ptr++; 348 } 349 if (i < dsdt->Length - 8) { 350 //Skip '_SX_' and Package Op 351 aml_ptr += 5; 352 353 //Skip 'Package Length' bytes indicated by the 2 high bits of 'Package Lead' byte 354 aml_ptr += (*aml_ptr >> 6); 355 356 //Skip 'Package Lead' byte 357 aml_ptr++; 358 359 //Skip 'Number of Elements' byte 360 aml_ptr++; 361 362 //Skip 'Byte Prefix' if found 363 if (*aml_ptr == 0x0a) 364 aml_ptr++; 365 366 //This should be SLP_TYP value for PM1A_CNT_BLK 367 sleep_conversion_table[ACPI_PM1_CNTRL_REG_A][sstate] = *aml_ptr; 368 aml_ptr++; 369 370 //Skip 'Byte Prefix' if found 371 if (*aml_ptr == 0x0a) 372 aml_ptr++; 373 374 //This should be SLP_TYP value for PM1B_CNT_BLK 375 sleep_conversion_table[ACPI_PM1_CNTRL_REG_B][sstate] = *aml_ptr; 376 } 377 378 VMM_LOG(mask_anonymous, level_trace," %3d | %3d | %3d\n", 379 sstate, 380 sleep_conversion_table[ACPI_PM1_CNTRL_REG_A][sstate], 381 sleep_conversion_table[ACPI_PM1_CNTRL_REG_B][sstate]); 382 } 383 } 384 385 int vmm_acpi_init(HVA fadt_hva) 386 { 387 ACPI_TABLE_HEADER *pTable; 388 389 pTable = (ACPI_TABLE_HEADER *)fadt_hva; 390 391 if (NULL != pTable) { 392 //Keep a local copy of fadt to avoid losing the tables if OS reuses acpi memory 393 fadt = *(ACPI_TABLE_FADT *) pTable; 394 vmm_acpi_print_fadt((ACPI_TABLE_FADT *) pTable); 395 } 396 #ifdef ENABLE_PM_S3 397 // Get Sleep Data 398 vmm_acpi_retrieve_sleep_states(); 399 #endif 400 return 1; 401 } 402 403 UINT16 vmm_acpi_smi_cmd_port(void) 404 { 405 return (UINT16) fadt.SmiCommand; 406 } 407 408 UINT8 vmm_acpi_pm_port_size(void) 409 { 410 return fadt.Pm1ControlLength; 411 } 412 413 UINT32 vmm_acpi_pm_port_a(void) 414 { 415 return fadt.Pm1aControlBlock; 416 } 417 418 UINT32 vmm_acpi_pm_port_b(void) 419 { 420 return fadt.Pm1bControlBlock; 421 } 422 423 unsigned vmm_acpi_sleep_type_to_state(unsigned pm_reg_id, unsigned sleep_type) 424 { 425 int sstate; 426 427 if (pm_reg_id >= ACPI_PM1_CNTRL_REG_COUNT) { 428 VMM_LOG(mask_anonymous, level_error,"[ACPI] got bad input. pm_reg_id(%d) sleep_type(%d)\n", 429 pm_reg_id, sleep_type); 430 return 0; 431 } 432 for (sstate = ACPI_STATE_S0; sstate < ACPI_S_STATE_COUNT; ++sstate) { 433 if (sleep_conversion_table[pm_reg_id][sstate] == (char) sleep_type) { 434 return sstate; // found 435 } 436 } 437 VMM_LOG(mask_anonymous, level_error,"[ACPI] got bad input. pm_reg_id(%d) sleep_type(%d)\n", 438 pm_reg_id, sleep_type); 439 return 0; // sleep_type not recognized 440 } 441 442 int vmm_acpi_waking_vector(UINT32 *p_waking_vector, UINT64 *p_extended_waking_vector) 443 { 444 ACPI_TABLE_FACS *p_facs; 445 446 p_facs = (ACPI_TABLE_FACS *) (size_t) fadt.Facs; 447 if (NULL == p_facs) { 448 p_facs = (ACPI_TABLE_FACS *) fadt.XFacs; 449 } 450 if (NULL == p_facs) { 451 VMM_LOG(mask_anonymous, level_error,"[acpi] FACS is not detected. S3 is not supported by the platform\n"); 452 return -1; // error 453 } 454 VMM_LOG(mask_anonymous, level_trace,"[acpi] FirmwareWakingVector=%P XFirmwareWakingVector=%P\n", 455 p_facs->FirmwareWakingVector, p_facs->XFirmwareWakingVector); 456 *p_waking_vector = p_facs->FirmwareWakingVector; 457 *p_extended_waking_vector = p_facs->XFirmwareWakingVector; 458 return 0; // OK 459 } 460 #else 461 UINT16 vmm_acpi_smi_cmd_port(void) 462 { 463 //return (UINT16) fadt.SmiCommand; 464 465 //ACPI is gone, we can only support late launch. 466 // it should never come here. Let's put a 467 // deadloop. The whole function is just to make 468 //compiler happy. 469 VMM_DEADLOOP(); 470 return 0; 471 } 472 473 #endif //USE_ACPI 474