xref: /netbsd-src/sys/external/bsd/acpica/dist/os_specific/service_layers/oswintbl.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /******************************************************************************
2  *
3  * Module Name: oswintbl - Windows OSL for obtaining ACPI tables
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2011, 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 
45 #include "acpi.h"
46 
47 #ifdef WIN32
48 #pragma warning(disable:4115)   /* warning C4115: (caused by rpcasync.h) */
49 #include <windows.h>
50 
51 #elif WIN64
52 #include <windowsx.h>
53 #endif
54 
55 #define _COMPONENT          ACPI_OS_SERVICES
56         ACPI_MODULE_NAME    ("oswintbl")
57 
58 
59 static char             KeyBuffer[64];
60 static char             ErrorBuffer[64];
61 
62 
63 /* Little front-end to win FormatMessage */
64 
65 char *
66 OsFormatException (
67     LONG                Status)
68 {
69 
70     ErrorBuffer[0] = 0;
71     FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, Status, 0,
72         ErrorBuffer, 64, NULL);
73 
74     return (ErrorBuffer);
75 }
76 
77 
78 /******************************************************************************
79  *
80  * FUNCTION:    OsGetTable
81  *
82  * PARAMETERS:  Signature       - ACPI Signature for desired table. must be
83  *                                  a null terminated string.
84  *
85  * RETURN:      Pointer to the table. NULL if failure.
86  *
87  * DESCRIPTION: Get an ACPI table from the Windows registry.
88  *
89  *****************************************************************************/
90 
91 ACPI_TABLE_HEADER *
92 OsGetTable (
93     char                *Signature)
94 {
95     HKEY                Handle = NULL;
96     ULONG               i;
97     LONG                Status;
98     ULONG               Type;
99     ULONG               NameSize;
100     ULONG               DataSize;
101     HKEY                SubKey;
102     ACPI_TABLE_HEADER   *ReturnTable;
103 
104 
105     /* Get a handle to the table key */
106 
107     while (1)
108     {
109         ACPI_STRCPY (KeyBuffer, "HARDWARE\\ACPI\\");
110         ACPI_STRCAT (KeyBuffer, Signature);
111 
112         Status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, KeyBuffer,
113                     0L, KEY_READ, &Handle);
114 
115         if (Status != ERROR_SUCCESS)
116         {
117             /*
118              * Somewhere along the way, MS changed the registry entry for
119              * the FADT from
120              * HARDWARE/ACPI/FACP  to
121              * HARDWARE/ACPI/FADT.
122              *
123              * This code allows for both.
124              */
125             if (ACPI_COMPARE_NAME (Signature, "FACP"))
126             {
127                 Signature = "FADT";
128             }
129             else
130             {
131                 AcpiOsPrintf (
132                     "Could not find %s in registry at %s: %s (Status=0x%X)\n",
133                     Signature, KeyBuffer, OsFormatException (Status), Status);
134                 return (NULL);
135             }
136         }
137         else
138         {
139             break;
140         }
141     }
142 
143     /* Actual data for table is down a couple levels */
144 
145     for (i = 0; ;)
146     {
147         Status = RegEnumKey (Handle, i, KeyBuffer, sizeof (KeyBuffer));
148         i += 1;
149         if (Status == ERROR_NO_MORE_ITEMS)
150         {
151             break;
152         }
153 
154         Status = RegOpenKey (Handle, KeyBuffer, &SubKey);
155         if (Status != ERROR_SUCCESS)
156         {
157             AcpiOsPrintf ("Could not open %s entry: %s\n",
158                 Signature, OsFormatException (Status));
159             return (NULL);
160         }
161 
162         RegCloseKey (Handle);
163         Handle = SubKey;
164         i = 0;
165     }
166 
167     /* Find the (binary) table entry */
168 
169     for (i = 0; ;)
170     {
171         NameSize = sizeof (KeyBuffer);
172         Status = RegEnumValue (Handle, i, KeyBuffer, &NameSize,
173                     NULL, &Type, NULL, 0);
174         if (Status != ERROR_SUCCESS)
175         {
176             AcpiOsPrintf ("Could not get %s registry entry: %s\n",
177                 Signature, OsFormatException (Status));
178             return (NULL);
179         }
180 
181         if (Type == REG_BINARY)
182         {
183             break;
184         }
185         i += 1;
186     }
187 
188     /* Get the size of the table */
189 
190     Status = RegQueryValueEx (Handle, KeyBuffer, NULL, NULL, NULL, &DataSize);
191     if (Status != ERROR_SUCCESS)
192     {
193         AcpiOsPrintf ("Could not read the %s table size: %s\n",
194             Signature, OsFormatException (Status));
195         return (NULL);
196     }
197 
198     /* Allocate a new buffer for the table */
199 
200     ReturnTable = AcpiOsAllocate (DataSize);
201     if (!ReturnTable)
202     {
203         goto Cleanup;
204     }
205 
206     /* Get the actual table from the registry */
207 
208     Status = RegQueryValueEx (Handle, KeyBuffer, NULL, NULL,
209                 (UCHAR *) ReturnTable, &DataSize);
210     if (Status != ERROR_SUCCESS)
211     {
212         AcpiOsPrintf ("Could not read %s data: %s\n",
213             Signature, OsFormatException (Status));
214         AcpiOsFree (ReturnTable);
215         return (NULL);
216     }
217 
218 Cleanup:
219     RegCloseKey (Handle);
220     return (ReturnTable);
221 }
222 
223