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