1 /****************************************************************************** 2 * 3 * Module Name: examples - Example ACPICA initialization and execution code 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 "examples.h" 45 46 #define _COMPONENT ACPI_EXAMPLE 47 ACPI_MODULE_NAME ("examples") 48 49 50 /****************************************************************************** 51 * 52 * ACPICA Example Code 53 * 54 * This module contains examples of how the host OS should interface to the 55 * ACPICA subsystem. 56 * 57 * 1) How to use the platform/acenv.h file and how to set configuration 58 * options. 59 * 60 * 2) main - using the debug output mechanism and the error/warning output 61 * macros. 62 * 63 * 3) Two examples of the ACPICA initialization sequence. The first is a 64 * initialization with no "early" ACPI table access. The second shows 65 * how to use ACPICA to obtain the tables very early during kernel 66 * initialization, even before dynamic memory is available. 67 * 68 * 4) How to invoke a control method, including argument setup and how to 69 * access the return value. 70 * 71 *****************************************************************************/ 72 73 74 /* Local Prototypes */ 75 76 static ACPI_STATUS 77 InitializeFullAcpica (void); 78 79 static ACPI_STATUS 80 InstallHandlers (void); 81 82 static void 83 NotifyHandler ( 84 ACPI_HANDLE Device, 85 UINT32 Value, 86 void *Context); 87 88 static ACPI_STATUS 89 RegionHandler ( 90 UINT32 Function, 91 ACPI_PHYSICAL_ADDRESS Address, 92 UINT32 BitWidth, 93 UINT64 *Value, 94 void *HandlerContext, 95 void *RegionContext); 96 97 static ACPI_STATUS 98 RegionInit ( 99 ACPI_HANDLE RegionHandle, 100 UINT32 Function, 101 void *HandlerContext, 102 void **RegionContext); 103 104 static void 105 ExecuteMAIN (void); 106 107 static void 108 ExecuteOSI (void); 109 110 ACPI_STATUS 111 InitializeAcpiTables ( 112 void); 113 114 ACPI_STATUS 115 InitializeAcpi ( 116 void); 117 118 119 /****************************************************************************** 120 * 121 * FUNCTION: main 122 * 123 * PARAMETERS: argc, argv 124 * 125 * RETURN: Status 126 * 127 * DESCRIPTION: Main routine. Shows the use of the various output macros, as 128 * well as the use of the debug layer/level globals. 129 * 130 *****************************************************************************/ 131 132 int ACPI_SYSTEM_XFACE 133 main ( 134 int argc, 135 char **argv) 136 { 137 138 ACPI_DEBUG_INITIALIZE (); /* For debug version only */ 139 140 printf (ACPI_COMMON_SIGNON ("ACPI Example Code")); 141 142 /* Initialize the local ACPI tables (RSDP/RSDT/XSDT/FADT/DSDT/FACS) */ 143 144 ExInitializeAcpiTables (); 145 146 /* Initialize the ACPICA subsystem */ 147 148 InitializeFullAcpica (); 149 150 /* Example warning and error output */ 151 152 ACPI_INFO ((AE_INFO, "Example ACPICA info message")); 153 ACPI_WARNING ((AE_INFO, "Example ACPICA warning message")); 154 ACPI_ERROR ((AE_INFO, "Example ACPICA error message")); 155 ACPI_EXCEPTION ((AE_INFO, AE_AML_OPERAND_TYPE, 156 "Example ACPICA exception message")); 157 158 ExecuteOSI (); 159 ExecuteMAIN (); 160 return (0); 161 } 162 163 164 /****************************************************************************** 165 * 166 * Example ACPICA initialization code. This shows a full initialization with 167 * no early ACPI table access. 168 * 169 *****************************************************************************/ 170 171 static ACPI_STATUS 172 InitializeFullAcpica (void) 173 { 174 ACPI_STATUS Status; 175 176 177 /* Initialize the ACPICA subsystem */ 178 179 Status = AcpiInitializeSubsystem (); 180 if (ACPI_FAILURE (Status)) 181 { 182 ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA")); 183 return (Status); 184 } 185 186 /* Initialize the ACPICA Table Manager and get all ACPI tables */ 187 188 ACPI_INFO ((AE_INFO, "Loading ACPI tables")); 189 190 Status = AcpiInitializeTables (NULL, 16, FALSE); 191 if (ACPI_FAILURE (Status)) 192 { 193 ACPI_EXCEPTION ((AE_INFO, Status, "While initializing Table Manager")); 194 return (Status); 195 } 196 197 /* Create the ACPI namespace from ACPI tables */ 198 199 Status = AcpiLoadTables (); 200 if (ACPI_FAILURE (Status)) 201 { 202 ACPI_EXCEPTION ((AE_INFO, Status, "While loading ACPI tables")); 203 return (Status); 204 } 205 206 /* Install local handlers */ 207 208 Status = InstallHandlers (); 209 if (ACPI_FAILURE (Status)) 210 { 211 ACPI_EXCEPTION ((AE_INFO, Status, "While installing handlers")); 212 return (Status); 213 } 214 215 /* Initialize the ACPI hardware */ 216 217 Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION); 218 if (ACPI_FAILURE (Status)) 219 { 220 ACPI_EXCEPTION ((AE_INFO, Status, "While enabling ACPICA")); 221 return (Status); 222 } 223 224 /* Complete the ACPI namespace object initialization */ 225 226 Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION); 227 if (ACPI_FAILURE (Status)) 228 { 229 ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA objects")); 230 return (Status); 231 } 232 233 return (AE_OK); 234 } 235 236 237 /****************************************************************************** 238 * 239 * Example ACPICA initialization code with early ACPI table access. This shows 240 * an initialization that requires early access to ACPI tables (before 241 * kernel dynamic memory is available) 242 * 243 *****************************************************************************/ 244 245 /* 246 * The purpose of this static table array is to avoid the use of kernel 247 * dynamic memory which may not be available during early ACPI table 248 * access. 249 */ 250 #define ACPI_MAX_INIT_TABLES 16 251 static ACPI_TABLE_DESC TableArray[ACPI_MAX_INIT_TABLES]; 252 253 254 /* 255 * This function would be called early in kernel initialization. After this 256 * is called, all ACPI tables are available to the host. 257 */ 258 ACPI_STATUS 259 InitializeAcpiTables ( 260 void) 261 { 262 ACPI_STATUS Status; 263 264 265 /* Initialize the ACPICA Table Manager and get all ACPI tables */ 266 267 Status = AcpiInitializeTables (TableArray, ACPI_MAX_INIT_TABLES, TRUE); 268 return (Status); 269 } 270 271 272 /* 273 * This function would be called after the kernel is initialized and 274 * dynamic/virtual memory is available. It completes the initialization of 275 * the ACPICA subsystem. 276 */ 277 ACPI_STATUS 278 InitializeAcpi ( 279 void) 280 { 281 ACPI_STATUS Status; 282 283 284 /* Initialize the ACPICA subsystem */ 285 286 Status = AcpiInitializeSubsystem (); 287 if (ACPI_FAILURE (Status)) 288 { 289 return (Status); 290 } 291 292 /* Copy the root table list to dynamic memory */ 293 294 Status = AcpiReallocateRootTable (); 295 if (ACPI_FAILURE (Status)) 296 { 297 return (Status); 298 } 299 300 /* Create the ACPI namespace from ACPI tables */ 301 302 Status = AcpiLoadTables (); 303 if (ACPI_FAILURE (Status)) 304 { 305 return (Status); 306 } 307 308 /* Install local handlers */ 309 310 Status = InstallHandlers (); 311 if (ACPI_FAILURE (Status)) 312 { 313 ACPI_EXCEPTION ((AE_INFO, Status, "While installing handlers")); 314 return (Status); 315 } 316 317 /* Initialize the ACPI hardware */ 318 319 Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION); 320 if (ACPI_FAILURE (Status)) 321 { 322 return (Status); 323 } 324 325 /* Complete the ACPI namespace object initialization */ 326 327 Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION); 328 if (ACPI_FAILURE (Status)) 329 { 330 return (Status); 331 } 332 333 return (AE_OK); 334 } 335 336 337 /****************************************************************************** 338 * 339 * Example ACPICA handler and handler installation 340 * 341 *****************************************************************************/ 342 343 static void 344 NotifyHandler ( 345 ACPI_HANDLE Device, 346 UINT32 Value, 347 void *Context) 348 { 349 350 ACPI_INFO ((AE_INFO, "Received a notify 0x%X", Value)); 351 } 352 353 354 static ACPI_STATUS 355 RegionInit ( 356 ACPI_HANDLE RegionHandle, 357 UINT32 Function, 358 void *HandlerContext, 359 void **RegionContext) 360 { 361 362 if (Function == ACPI_REGION_DEACTIVATE) 363 { 364 *RegionContext = NULL; 365 } 366 else 367 { 368 *RegionContext = RegionHandle; 369 } 370 371 return (AE_OK); 372 } 373 374 375 static ACPI_STATUS 376 RegionHandler ( 377 UINT32 Function, 378 ACPI_PHYSICAL_ADDRESS Address, 379 UINT32 BitWidth, 380 UINT64 *Value, 381 void *HandlerContext, 382 void *RegionContext) 383 { 384 385 ACPI_INFO ((AE_INFO, "Received a region access")); 386 387 return (AE_OK); 388 } 389 390 391 static ACPI_STATUS 392 InstallHandlers (void) 393 { 394 ACPI_STATUS Status; 395 396 397 /* Install global notify handler */ 398 399 Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, 400 ACPI_SYSTEM_NOTIFY, NotifyHandler, NULL); 401 if (ACPI_FAILURE (Status)) 402 { 403 ACPI_EXCEPTION ((AE_INFO, Status, "While installing Notify handler")); 404 return (Status); 405 } 406 407 Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT, 408 ACPI_ADR_SPACE_SYSTEM_MEMORY, RegionHandler, RegionInit, NULL); 409 if (ACPI_FAILURE (Status)) 410 { 411 ACPI_EXCEPTION ((AE_INFO, Status, "While installing an OpRegion handler")); 412 return (Status); 413 } 414 415 return (AE_OK); 416 } 417 418 419 /****************************************************************************** 420 * 421 * Examples of control method execution. 422 * 423 * _OSI is a predefined method that is implemented internally within ACPICA. 424 * 425 * Shows the following elements: 426 * 427 * 1) How to setup a control method argument and argument list 428 * 2) How to setup the return value object 429 * 3) How to invoke AcpiEvaluateObject 430 * 4) How to check the returned ACPI_STATUS 431 * 5) How to analyze the return value 432 * 433 *****************************************************************************/ 434 435 static void 436 ExecuteOSI (void) 437 { 438 ACPI_STATUS Status; 439 ACPI_OBJECT_LIST ArgList; 440 ACPI_OBJECT Arg[1]; 441 ACPI_BUFFER ReturnValue; 442 ACPI_OBJECT *Object; 443 444 445 ACPI_INFO ((AE_INFO, "Executing _OSI reserved method")); 446 447 /* Setup input argument */ 448 449 ArgList.Count = 1; 450 ArgList.Pointer = Arg; 451 452 Arg[0].Type = ACPI_TYPE_STRING; 453 Arg[0].String.Pointer = "Windows 2001"; 454 Arg[0].String.Length = strlen (Arg[0].String.Pointer); 455 456 /* Ask ACPICA to allocate space for the return object */ 457 458 ReturnValue.Length = ACPI_ALLOCATE_BUFFER; 459 460 Status = AcpiEvaluateObject (NULL, "\\_OSI", &ArgList, &ReturnValue); 461 if (ACPI_FAILURE (Status)) 462 { 463 ACPI_EXCEPTION ((AE_INFO, Status, "While executing _OSI")); 464 return; 465 } 466 467 /* Ensure that the return object is large enough */ 468 469 if (ReturnValue.Length < sizeof (ACPI_OBJECT)) 470 { 471 AcpiOsPrintf ("Return value from _OSI method too small, %.8X\n", 472 ReturnValue.Length); 473 goto ErrorExit; 474 } 475 476 /* Expect an integer return value from execution of _OSI */ 477 478 Object = ReturnValue.Pointer; 479 if (Object->Type != ACPI_TYPE_INTEGER) 480 { 481 AcpiOsPrintf ("Invalid return type from _OSI, %.2X\n", Object->Type); 482 } 483 484 ACPI_INFO ((AE_INFO, "_OSI returned 0x%8.8X", 485 (UINT32) Object->Integer.Value)); 486 487 488 ErrorExit: 489 490 /* Free a buffer created via ACPI_ALLOCATE_BUFFER */ 491 492 AcpiOsFree (ReturnValue.Pointer); 493 } 494 495 496 /****************************************************************************** 497 * 498 * Execute an actual control method in the DSDT (MAIN) 499 * 500 *****************************************************************************/ 501 502 static void 503 ExecuteMAIN (void) 504 { 505 ACPI_STATUS Status; 506 ACPI_OBJECT_LIST ArgList; 507 ACPI_OBJECT Arg[1]; 508 ACPI_BUFFER ReturnValue; 509 ACPI_OBJECT *Object; 510 511 512 ACPI_INFO ((AE_INFO, "Executing MAIN method")); 513 514 /* Setup input argument */ 515 516 ArgList.Count = 1; 517 ArgList.Pointer = Arg; 518 519 Arg[0].Type = ACPI_TYPE_STRING; 520 Arg[0].String.Pointer = "Method [MAIN] is executing"; 521 Arg[0].String.Length = strlen (Arg[0].String.Pointer); 522 523 /* Ask ACPICA to allocate space for the return object */ 524 525 ReturnValue.Length = ACPI_ALLOCATE_BUFFER; 526 527 Status = AcpiEvaluateObject (NULL, "\\MAIN", &ArgList, &ReturnValue); 528 if (ACPI_FAILURE (Status)) 529 { 530 ACPI_EXCEPTION ((AE_INFO, Status, "While executing MAIN")); 531 return; 532 } 533 534 if (ReturnValue.Pointer) 535 { 536 /* Obtain and validate the returned ACPI_OBJECT */ 537 538 Object = ReturnValue.Pointer; 539 if (Object->Type == ACPI_TYPE_STRING) 540 { 541 AcpiOsPrintf ("Method [MAIN] returned: \"%s\"\n", 542 Object->String.Pointer); 543 } 544 545 ACPI_FREE (ReturnValue.Pointer); 546 } 547 } 548