oswintbl.c revision 1.1.1.3
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
62static char *
63WindowsFormatException (
64    LONG                WinStatus);
65
66/* Globals */
67
68#define LOCAL_BUFFER_SIZE           64
69
70static char             KeyBuffer[LOCAL_BUFFER_SIZE];
71static 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 */
77static 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
103static char *
104WindowsFormatException (
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
132ACPI_STATUS
133AcpiOsGetTableByAddress (
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
166ACPI_STATUS
167AcpiOsGetTableByIndex (
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
210ACPI_STATUS
211AcpiOsGetTableByName (
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
356Cleanup:
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
381void *
382AcpiOsMapMemory (
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
405void
406AcpiOsUnmapMemory (
407    void                    *Where,
408    ACPI_SIZE               Length)
409{
410
411    return;
412}
413#endif
414