1 /******************************************************************************
   2  *
   3  * Module Name: oswintbl - Windows OSL for obtaining ACPI tables
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2013, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 #include "acpi.h"
  45 #include "accommon.h"
  46 #include "acutils.h"
  47 #include <stdio.h>
  48 
  49 #ifdef WIN32
  50 #pragma warning(disable:4115)   /* warning C4115: (caused by rpcasync.h) */
  51 #include <windows.h>
  52 
  53 #elif WIN64
  54 #include <windowsx.h>
  55 #endif
  56 
  57 #define _COMPONENT          ACPI_OS_SERVICES
  58         ACPI_MODULE_NAME    ("oswintbl")
  59 
  60 /* Local prototypes */
  61 
  62 static char *
  63 WindowsFormatException (
  64     LONG                WinStatus);
  65 
  66 /* Globals */
  67 
  68 #define LOCAL_BUFFER_SIZE           64
  69 
  70 static char             KeyBuffer[LOCAL_BUFFER_SIZE];
  71 static char             ErrorBuffer[LOCAL_BUFFER_SIZE];
  72 
  73 /*
  74  * Tables supported in the Windows registry. SSDTs are not placed into
  75  * the registry, a limitation.
  76  */
  77 static char             *SupportedTables[] =
  78 {
  79     "DSDT",
  80     "RSDT",
  81     "FACS",
  82     "FACP"
  83 };
  84 
  85 /* Max index for table above */
  86 
  87 #define ACPI_OS_MAX_TABLE_INDEX     3
  88 
  89 
  90 /******************************************************************************
  91  *
  92  * FUNCTION:    WindowsFormatException
  93  *
  94  * PARAMETERS:  WinStatus       - Status from a Windows system call
  95  *
  96  * RETURN:      Formatted (ascii) exception code. Front-end to Windows
  97  *              FormatMessage interface.
  98  *
  99  * DESCRIPTION: Decode a windows exception
 100  *
 101  *****************************************************************************/
 102 
 103 static char *
 104 WindowsFormatException (
 105     LONG                WinStatus)
 106 {
 107 
 108     ErrorBuffer[0] = 0;
 109     FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, WinStatus, 0,
 110         ErrorBuffer, LOCAL_BUFFER_SIZE, NULL);
 111 
 112     return (ErrorBuffer);
 113 }
 114 
 115 
 116 /******************************************************************************
 117  *
 118  * FUNCTION:    AcpiOsGetTableByAddress
 119  *
 120  * PARAMETERS:  Address         - Physical address of the ACPI table
 121  *              Table           - Where a pointer to the table is returned
 122  *
 123  * RETURN:      Status; Table buffer is returned if AE_OK.
 124  *              AE_NOT_FOUND: A valid table was not found at the address
 125  *
 126  * DESCRIPTION: Get an ACPI table via a physical memory address.
 127  *
 128  * NOTE:        Cannot be implemented without a Windows device driver.
 129  *
 130  *****************************************************************************/
 131 
 132 ACPI_STATUS
 133 AcpiOsGetTableByAddress (
 134     ACPI_PHYSICAL_ADDRESS   Address,
 135     ACPI_TABLE_HEADER       **Table)
 136 {
 137 
 138     fprintf (stderr, "Get table by address is not supported on Windows\n");
 139     return (AE_SUPPORT);
 140 }
 141 
 142 
 143 /******************************************************************************
 144  *
 145  * FUNCTION:    AcpiOsGetTableByIndex
 146  *
 147  * PARAMETERS:  Index           - Which table to get
 148  *              Table           - Where a pointer to the table is returned
 149  *              Instance        - Where a pointer to the table instance no. is
 150  *                                returned
 151  *              Address         - Where the table physical address is returned
 152  *
 153  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
 154  *              AE_LIMIT: Index is beyond valid limit
 155  *
 156  * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
 157  *              AE_LIMIT when an invalid index is reached. Index is not
 158  *              necessarily an index into the RSDT/XSDT.
 159  *              Table is obtained from the Windows registry.
 160  *
 161  * NOTE:        Cannot get the physical address from the windows registry;
 162  *              zero is returned instead.
 163  *
 164  *****************************************************************************/
 165 
 166 ACPI_STATUS
 167 AcpiOsGetTableByIndex (
 168     UINT32                  Index,
 169     ACPI_TABLE_HEADER       **Table,
 170     UINT32                  *Instance,
 171     ACPI_PHYSICAL_ADDRESS   *Address)
 172 {
 173     ACPI_STATUS             Status;
 174 
 175 
 176     if (Index > ACPI_OS_MAX_TABLE_INDEX)
 177     {
 178         return (AE_LIMIT);
 179     }
 180 
 181     Status = AcpiOsGetTableByName (SupportedTables[Index], 0, Table, Address);
 182     return (Status);
 183 }
 184 
 185 
 186 /******************************************************************************
 187  *
 188  * FUNCTION:    AcpiOsGetTableByName
 189  *
 190  * PARAMETERS:  Signature       - ACPI Signature for desired table. Must be
 191  *                                a null terminated 4-character string.
 192  *              Instance        - For SSDTs (0...n). Use 0 otherwise.
 193  *              Table           - Where a pointer to the table is returned
 194  *              Address         - Where the table physical address is returned
 195  *
 196  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
 197  *              AE_LIMIT: Instance is beyond valid limit
 198  *              AE_NOT_FOUND: A table with the signature was not found
 199  *
 200  * DESCRIPTION: Get an ACPI table via a table signature (4 ASCII characters).
 201  *              Returns AE_LIMIT when an invalid instance is reached.
 202  *              Table is obtained from the Windows registry.
 203  *
 204  * NOTE:        Assumes the input signature is uppercase.
 205  *              Cannot get the physical address from the windows registry;
 206  *              zero is returned instead.
 207  *
 208  *****************************************************************************/
 209 
 210 ACPI_STATUS
 211 AcpiOsGetTableByName (
 212     char                    *Signature,
 213     UINT32                  Instance,
 214     ACPI_TABLE_HEADER       **Table,
 215     ACPI_PHYSICAL_ADDRESS   *Address)
 216 {
 217     HKEY                    Handle = NULL;
 218     LONG                    WinStatus;
 219     ULONG                   Type;
 220     ULONG                   NameSize;
 221     ULONG                   DataSize;
 222     HKEY                    SubKey;
 223     ULONG                   i;
 224     ACPI_TABLE_HEADER       *ReturnTable;
 225 
 226 
 227     /*
 228      * Windows has no SSDTs in the registry, so multiple instances are
 229      * not supported.
 230      */
 231     if (Instance > 0)
 232     {
 233         return (AE_LIMIT);
 234     }
 235 
 236     /* Get a handle to the table key */
 237 
 238     while (1)
 239     {
 240         ACPI_STRCPY (KeyBuffer, "HARDWARE\\ACPI\\");
 241         if (AcpiUtSafeStrcat (KeyBuffer, sizeof (KeyBuffer), Signature))
 242         {
 243             return (AE_BUFFER_OVERFLOW);
 244         }
 245 
 246         WinStatus = RegOpenKeyEx (HKEY_LOCAL_MACHINE, KeyBuffer,
 247             0L, KEY_READ, &Handle);
 248 
 249         if (WinStatus != ERROR_SUCCESS)
 250         {
 251             /*
 252              * Somewhere along the way, MS changed the registry entry for
 253              * the FADT from
 254              * HARDWARE/ACPI/FACP  to
 255              * HARDWARE/ACPI/FADT.
 256              *
 257              * This code allows for both.
 258              */
 259             if (ACPI_COMPARE_NAME (Signature, "FACP"))
 260             {
 261                 Signature = "FADT";
 262             }
 263             else if (ACPI_COMPARE_NAME (Signature, "XSDT"))
 264             {
 265                 Signature = "RSDT";
 266             }
 267             else
 268             {
 269                 fprintf (stderr,
 270                     "Could not find %s in registry at %s: %s (WinStatus=0x%X)\n",
 271                     Signature, KeyBuffer, WindowsFormatException (WinStatus), WinStatus);
 272                 return (AE_NOT_FOUND);
 273             }
 274         }
 275         else
 276         {
 277             break;
 278         }
 279     }
 280 
 281     /* Actual data for the table is down a couple levels */
 282 
 283     for (i = 0; ;)
 284     {
 285         WinStatus = RegEnumKey (Handle, i, KeyBuffer, sizeof (KeyBuffer));
 286         i++;
 287         if (WinStatus == ERROR_NO_MORE_ITEMS)
 288         {
 289             break;
 290         }
 291 
 292         WinStatus = RegOpenKey (Handle, KeyBuffer, &SubKey);
 293         if (WinStatus != ERROR_SUCCESS)
 294         {
 295             fprintf (stderr, "Could not open %s entry: %s\n",
 296                 Signature, WindowsFormatException (WinStatus));
 297             return (AE_ERROR);
 298         }
 299 
 300         RegCloseKey (Handle);
 301         Handle = SubKey;
 302         i = 0;
 303     }
 304 
 305     /* Find the (binary) table entry */
 306 
 307     for (i = 0; ; i++)
 308     {
 309         NameSize = sizeof (KeyBuffer);
 310         WinStatus = RegEnumValue (Handle, i, KeyBuffer, &NameSize, NULL,
 311             &Type, NULL, 0);
 312         if (WinStatus != ERROR_SUCCESS)
 313         {
 314             fprintf (stderr, "Could not get %s registry entry: %s\n",
 315                 Signature, WindowsFormatException (WinStatus));
 316             return (AE_ERROR);
 317         }
 318 
 319         if (Type == REG_BINARY)
 320         {
 321             break;
 322         }
 323     }
 324 
 325     /* Get the size of the table */
 326 
 327     WinStatus = RegQueryValueEx (Handle, KeyBuffer, NULL, NULL,
 328         NULL, &DataSize);
 329     if (WinStatus != ERROR_SUCCESS)
 330     {
 331         fprintf (stderr, "Could not read the %s table size: %s\n",
 332             Signature, WindowsFormatException (WinStatus));
 333         return (AE_ERROR);
 334     }
 335 
 336     /* Allocate a new buffer for the table */
 337 
 338     ReturnTable = malloc (DataSize);
 339     if (!ReturnTable)
 340     {
 341         goto Cleanup;
 342     }
 343 
 344     /* Get the actual table from the registry */
 345 
 346     WinStatus = RegQueryValueEx (Handle, KeyBuffer, NULL, NULL,
 347         (UCHAR *) ReturnTable, &DataSize);
 348     if (WinStatus != ERROR_SUCCESS)
 349     {
 350         fprintf (stderr, "Could not read %s data: %s\n",
 351             Signature, WindowsFormatException (WinStatus));
 352         free (ReturnTable);
 353         return (AE_ERROR);
 354     }
 355 
 356 Cleanup:
 357     RegCloseKey (Handle);
 358 
 359     *Table = ReturnTable;
 360     *Address = 0;
 361     return (AE_OK);
 362 }
 363 
 364 
 365 /* These are here for acpidump only, so we don't need to link oswinxf */
 366 
 367 #ifdef ACPI_DUMP_APP
 368 /******************************************************************************
 369  *
 370  * FUNCTION:    AcpiOsMapMemory
 371  *
 372  * PARAMETERS:  Where               - Physical address of memory to be mapped
 373  *              Length              - How much memory to map
 374  *
 375  * RETURN:      Pointer to mapped memory. Null on error.
 376  *
 377  * DESCRIPTION: Map physical memory into caller's address space
 378  *
 379  *****************************************************************************/
 380 
 381 void *
 382 AcpiOsMapMemory (
 383     ACPI_PHYSICAL_ADDRESS   Where,
 384     ACPI_SIZE               Length)
 385 {
 386 
 387     return (ACPI_TO_POINTER ((ACPI_SIZE) Where));
 388 }
 389 
 390 
 391 /******************************************************************************
 392  *
 393  * FUNCTION:    AcpiOsUnmapMemory
 394  *
 395  * PARAMETERS:  Where               - Logical address of memory to be unmapped
 396  *              Length              - How much memory to unmap
 397  *
 398  * RETURN:      None.
 399  *
 400  * DESCRIPTION: Delete a previously created mapping. Where and Length must
 401  *              correspond to a previous mapping exactly.
 402  *
 403  *****************************************************************************/
 404 
 405 void
 406 AcpiOsUnmapMemory (
 407     void                    *Where,
 408     ACPI_SIZE               Length)
 409 {
 410 
 411     return;
 412 }
 413 #endif