1 /****************************************************************************** 2 * 3 * Module Name: oswintbl - Windows OSL for obtaining ACPI tables 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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. Zero or more SSDTs are assumed to 75 * follow these tables. 76 */ 77 static char *SupportedTables[] = 78 { 79 "DSDT", 80 "RSDT", 81 "FACS", 82 "FACP" 83 }; 84 85 /* Number of table names for the table above. */ 86 87 #define ACPI_OS_NUM_TABLE_ENTRIES 4 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 char *Signature; 175 176 177 if (Index < ACPI_OS_NUM_TABLE_ENTRIES) 178 { 179 Signature = SupportedTables[Index]; 180 Index = 0; 181 } 182 else 183 { 184 Signature = ACPI_SIG_SSDT; 185 Index -= ACPI_OS_NUM_TABLE_ENTRIES; 186 } 187 188 Status = AcpiOsGetTableByName (Signature, Index, Table, Address); 189 190 if (ACPI_SUCCESS (Status)) 191 { 192 *Instance = Index; 193 } 194 else if (Status == AE_NOT_FOUND && ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT)) 195 { 196 /* Treat SSDTs that are not found as invalid index. */ 197 Status = (AE_LIMIT); 198 } 199 200 return (Status); 201 } 202 203 204 /****************************************************************************** 205 * 206 * FUNCTION: AcpiOsGetTableByName 207 * 208 * PARAMETERS: Signature - ACPI Signature for desired table. Must be 209 * a null terminated 4-character string. 210 * Instance - For SSDTs (0...n). Use 0 otherwise. 211 * Table - Where a pointer to the table is returned 212 * Address - Where the table physical address is returned 213 * 214 * RETURN: Status; Table buffer and physical address returned if AE_OK. 215 * AE_LIMIT: Instance is beyond valid limit 216 * AE_NOT_FOUND: A table with the signature was not found 217 * 218 * DESCRIPTION: Get an ACPI table via a table signature (4 ASCII characters). 219 * Returns AE_LIMIT when an invalid instance is reached. 220 * Table is obtained from the Windows registry. 221 * 222 * NOTE: Assumes the input signature is uppercase. 223 * Cannot get the physical address from the windows registry; 224 * zero is returned instead. 225 * 226 *****************************************************************************/ 227 228 ACPI_STATUS 229 AcpiOsGetTableByName ( 230 char *Signature, 231 UINT32 Instance, 232 ACPI_TABLE_HEADER **Table, 233 ACPI_PHYSICAL_ADDRESS *Address) 234 { 235 HKEY Handle = NULL; 236 LONG WinStatus; 237 ULONG Type; 238 ULONG NameSize; 239 ULONG DataSize; 240 HKEY SubKey; 241 ULONG i; 242 ACPI_TABLE_HEADER *ReturnTable; 243 ACPI_STATUS Status = AE_OK; 244 245 246 /* Multiple instances are only supported for SSDT tables. */ 247 248 if (Instance > 0 && !ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT)) 249 { 250 return (AE_LIMIT); 251 } 252 253 /* Get a handle to the table key */ 254 255 while (1) 256 { 257 strcpy (KeyBuffer, "HARDWARE\\ACPI\\"); 258 if (AcpiUtSafeStrcat (KeyBuffer, sizeof (KeyBuffer), Signature)) 259 { 260 return (AE_BUFFER_OVERFLOW); 261 } 262 263 /* 264 * Windows stores SSDT at SSDT, SSD1, ..., SSD9, SSDA, ..., SSDS, SSDT, 265 * SSDU, ..., SSDY. If the first (0th) and the 29th tables have the same 266 * OEM ID, Table ID and Revision, then the 29th entry will overwrite the 267 * first entry... Let's hope that we do not have that many entries. 268 */ 269 if (Instance > 0 && ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT)) 270 { 271 if (Instance < 10) 272 { 273 KeyBuffer[strlen (KeyBuffer) - 1] = '0' + (char) Instance; 274 } 275 else if (Instance < 29) 276 { 277 KeyBuffer[strlen (KeyBuffer) - 1] = 'A' + (char) (Instance - 10); 278 } 279 else 280 { 281 return (AE_LIMIT); 282 } 283 } 284 285 WinStatus = RegOpenKeyEx (HKEY_LOCAL_MACHINE, KeyBuffer, 286 0L, KEY_READ, &Handle); 287 288 if (WinStatus != ERROR_SUCCESS) 289 { 290 /* 291 * Somewhere along the way, MS changed the registry entry for 292 * the FADT from 293 * HARDWARE/ACPI/FACP to 294 * HARDWARE/ACPI/FADT. 295 * 296 * This code allows for both. 297 */ 298 if (ACPI_COMPARE_NAME (Signature, "FACP")) 299 { 300 Signature = "FADT"; 301 } 302 else if (ACPI_COMPARE_NAME (Signature, "XSDT")) 303 { 304 Signature = "RSDT"; 305 } 306 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT)) 307 { 308 /* SSDT may not be present on older Windows versions, but it is 309 * also possible that the index is not found. */ 310 return (AE_NOT_FOUND); 311 } 312 else 313 { 314 fprintf (stderr, 315 "Could not find %s in registry at %s: %s (WinStatus=0x%X)\n", 316 Signature, KeyBuffer, WindowsFormatException (WinStatus), WinStatus); 317 return (AE_NOT_FOUND); 318 } 319 } 320 else 321 { 322 break; 323 } 324 } 325 326 /* Actual data for the table is down a couple levels */ 327 328 for (i = 0; ;) 329 { 330 WinStatus = RegEnumKey (Handle, i, KeyBuffer, sizeof (KeyBuffer)); 331 i++; 332 if (WinStatus == ERROR_NO_MORE_ITEMS) 333 { 334 break; 335 } 336 337 WinStatus = RegOpenKey (Handle, KeyBuffer, &SubKey); 338 if (WinStatus != ERROR_SUCCESS) 339 { 340 fprintf (stderr, "Could not open %s entry: %s\n", 341 Signature, WindowsFormatException (WinStatus)); 342 Status = AE_ERROR; 343 goto Cleanup; 344 } 345 346 RegCloseKey (Handle); 347 Handle = SubKey; 348 i = 0; 349 } 350 351 /* Find the (binary) table entry */ 352 353 for (i = 0; ; i++) 354 { 355 NameSize = sizeof (KeyBuffer); 356 WinStatus = RegEnumValue (Handle, i, KeyBuffer, &NameSize, NULL, 357 &Type, NULL, 0); 358 if (WinStatus != ERROR_SUCCESS) 359 { 360 fprintf (stderr, "Could not get %s registry entry: %s\n", 361 Signature, WindowsFormatException (WinStatus)); 362 Status = AE_ERROR; 363 goto Cleanup; 364 } 365 366 if (Type == REG_BINARY) 367 { 368 break; 369 } 370 } 371 372 /* Get the size of the table */ 373 374 WinStatus = RegQueryValueEx (Handle, KeyBuffer, NULL, NULL, 375 NULL, &DataSize); 376 if (WinStatus != ERROR_SUCCESS) 377 { 378 fprintf (stderr, "Could not read the %s table size: %s\n", 379 Signature, WindowsFormatException (WinStatus)); 380 Status = AE_ERROR; 381 goto Cleanup; 382 } 383 384 /* Allocate a new buffer for the table */ 385 386 ReturnTable = malloc (DataSize); 387 if (!ReturnTable) 388 { 389 Status = AE_NO_MEMORY; 390 goto Cleanup; 391 } 392 393 /* Get the actual table from the registry */ 394 395 WinStatus = RegQueryValueEx (Handle, KeyBuffer, NULL, NULL, 396 (UCHAR *) ReturnTable, &DataSize); 397 if (WinStatus != ERROR_SUCCESS) 398 { 399 fprintf (stderr, "Could not read %s data: %s\n", 400 Signature, WindowsFormatException (WinStatus)); 401 free (ReturnTable); 402 Status = AE_ERROR; 403 goto Cleanup; 404 } 405 406 *Table = ReturnTable; 407 *Address = 0; 408 409 Cleanup: 410 RegCloseKey (Handle); 411 return (Status); 412 } 413 414 415 /* These are here for acpidump only, so we don't need to link oswinxf */ 416 417 #ifdef ACPI_DUMP_APP 418 /****************************************************************************** 419 * 420 * FUNCTION: AcpiOsMapMemory 421 * 422 * PARAMETERS: Where - Physical address of memory to be mapped 423 * Length - How much memory to map 424 * 425 * RETURN: Pointer to mapped memory. Null on error. 426 * 427 * DESCRIPTION: Map physical memory into caller's address space 428 * 429 *****************************************************************************/ 430 431 void * 432 AcpiOsMapMemory ( 433 ACPI_PHYSICAL_ADDRESS Where, 434 ACPI_SIZE Length) 435 { 436 437 return (ACPI_TO_POINTER ((ACPI_SIZE) Where)); 438 } 439 440 441 /****************************************************************************** 442 * 443 * FUNCTION: AcpiOsUnmapMemory 444 * 445 * PARAMETERS: Where - Logical address of memory to be unmapped 446 * Length - How much memory to unmap 447 * 448 * RETURN: None. 449 * 450 * DESCRIPTION: Delete a previously created mapping. Where and Length must 451 * correspond to a previous mapping exactly. 452 * 453 *****************************************************************************/ 454 455 void 456 AcpiOsUnmapMemory ( 457 void *Where, 458 ACPI_SIZE Length) 459 { 460 461 return; 462 } 463 #endif 464