1 /****************************************************************************** 2 * 3 * Module Name: examples - Example ACPICA initialization and execution code 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 "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 AcpiGbl_OverrideDefaultRegionHandlers = TRUE; 180 Status = AcpiInitializeSubsystem (); 181 if (ACPI_FAILURE (Status)) 182 { 183 ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA")); 184 return (Status); 185 } 186 187 /* Initialize the ACPICA Table Manager and get all ACPI tables */ 188 189 ACPI_INFO ((AE_INFO, "Loading ACPI tables")); 190 191 Status = AcpiInitializeTables (NULL, 16, FALSE); 192 if (ACPI_FAILURE (Status)) 193 { 194 ACPI_EXCEPTION ((AE_INFO, Status, "While initializing Table Manager")); 195 return (Status); 196 } 197 198 /* Install local handlers */ 199 200 Status = InstallHandlers (); 201 if (ACPI_FAILURE (Status)) 202 { 203 ACPI_EXCEPTION ((AE_INFO, Status, "While installing handlers")); 204 return (Status); 205 } 206 207 /* Initialize the ACPI hardware */ 208 209 Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION); 210 if (ACPI_FAILURE (Status)) 211 { 212 ACPI_EXCEPTION ((AE_INFO, Status, "While enabling ACPICA")); 213 return (Status); 214 } 215 216 /* Create the ACPI namespace from ACPI tables */ 217 218 Status = AcpiLoadTables (); 219 if (ACPI_FAILURE (Status)) 220 { 221 ACPI_EXCEPTION ((AE_INFO, Status, "While loading ACPI tables")); 222 return (Status); 223 } 224 225 /* Complete the ACPI namespace object initialization */ 226 227 Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION); 228 if (ACPI_FAILURE (Status)) 229 { 230 ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA objects")); 231 return (Status); 232 } 233 234 return (AE_OK); 235 } 236 237 238 /****************************************************************************** 239 * 240 * Example ACPICA initialization code with early ACPI table access. This shows 241 * an initialization that requires early access to ACPI tables (before 242 * kernel dynamic memory is available) 243 * 244 *****************************************************************************/ 245 246 /* 247 * The purpose of this static table array is to avoid the use of kernel 248 * dynamic memory which may not be available during early ACPI table 249 * access. 250 */ 251 #define ACPI_MAX_INIT_TABLES 16 252 static ACPI_TABLE_DESC TableArray[ACPI_MAX_INIT_TABLES]; 253 254 255 /* 256 * This function would be called early in kernel initialization. After this 257 * is called, all ACPI tables are available to the host. 258 */ 259 ACPI_STATUS 260 InitializeAcpiTables ( 261 void) 262 { 263 ACPI_STATUS Status; 264 265 266 /* Initialize the ACPICA Table Manager and get all ACPI tables */ 267 268 Status = AcpiInitializeTables (TableArray, ACPI_MAX_INIT_TABLES, TRUE); 269 return (Status); 270 } 271 272 273 /* 274 * This function would be called after the kernel is initialized and 275 * dynamic/virtual memory is available. It completes the initialization of 276 * the ACPICA subsystem. 277 */ 278 ACPI_STATUS 279 InitializeAcpi ( 280 void) 281 { 282 ACPI_STATUS Status; 283 284 285 /* Initialize the ACPICA subsystem */ 286 287 AcpiGbl_OverrideDefaultRegionHandlers = TRUE; 288 Status = AcpiInitializeSubsystem (); 289 if (ACPI_FAILURE (Status)) 290 { 291 return (Status); 292 } 293 294 /* Copy the root table list to dynamic memory */ 295 296 Status = AcpiReallocateRootTable (); 297 if (ACPI_FAILURE (Status)) 298 { 299 return (Status); 300 } 301 302 /* Install local handlers */ 303 304 Status = InstallHandlers (); 305 if (ACPI_FAILURE (Status)) 306 { 307 ACPI_EXCEPTION ((AE_INFO, Status, "While installing handlers")); 308 return (Status); 309 } 310 311 /* Initialize the ACPI hardware */ 312 313 Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION); 314 if (ACPI_FAILURE (Status)) 315 { 316 return (Status); 317 } 318 319 /* Create the ACPI namespace from ACPI tables */ 320 321 Status = AcpiLoadTables (); 322 if (ACPI_FAILURE (Status)) 323 { 324 return (Status); 325 } 326 327 /* Complete the ACPI namespace object initialization */ 328 329 Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION); 330 if (ACPI_FAILURE (Status)) 331 { 332 return (Status); 333 } 334 335 return (AE_OK); 336 } 337 338 339 /****************************************************************************** 340 * 341 * Example ACPICA handler and handler installation 342 * 343 *****************************************************************************/ 344 345 static void 346 NotifyHandler ( 347 ACPI_HANDLE Device, 348 UINT32 Value, 349 void *Context) 350 { 351 352 ACPI_INFO ((AE_INFO, "Received a notify 0x%X", Value)); 353 } 354 355 356 static ACPI_STATUS 357 RegionInit ( 358 ACPI_HANDLE RegionHandle, 359 UINT32 Function, 360 void *HandlerContext, 361 void **RegionContext) 362 { 363 364 if (Function == ACPI_REGION_DEACTIVATE) 365 { 366 *RegionContext = NULL; 367 } 368 else 369 { 370 *RegionContext = RegionHandle; 371 } 372 373 return (AE_OK); 374 } 375 376 377 static ACPI_STATUS 378 RegionHandler ( 379 UINT32 Function, 380 ACPI_PHYSICAL_ADDRESS Address, 381 UINT32 BitWidth, 382 UINT64 *Value, 383 void *HandlerContext, 384 void *RegionContext) 385 { 386 387 ACPI_INFO ((AE_INFO, "Received a region access")); 388 389 return (AE_OK); 390 } 391 392 393 static ACPI_STATUS 394 InstallHandlers (void) 395 { 396 ACPI_STATUS Status; 397 398 399 /* Install global notify handler */ 400 401 Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, 402 ACPI_SYSTEM_NOTIFY, NotifyHandler, NULL); 403 if (ACPI_FAILURE (Status)) 404 { 405 ACPI_EXCEPTION ((AE_INFO, Status, "While installing Notify handler")); 406 return (Status); 407 } 408 409 Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT, 410 ACPI_ADR_SPACE_SYSTEM_MEMORY, RegionHandler, RegionInit, NULL); 411 if (ACPI_FAILURE (Status)) 412 { 413 ACPI_EXCEPTION ((AE_INFO, Status, "While installing an OpRegion handler")); 414 return (Status); 415 } 416 417 return (AE_OK); 418 } 419 420 421 /****************************************************************************** 422 * 423 * Examples of control method execution. 424 * 425 * _OSI is a predefined method that is implemented internally within ACPICA. 426 * 427 * Shows the following elements: 428 * 429 * 1) How to setup a control method argument and argument list 430 * 2) How to setup the return value object 431 * 3) How to invoke AcpiEvaluateObject 432 * 4) How to check the returned ACPI_STATUS 433 * 5) How to analyze the return value 434 * 435 *****************************************************************************/ 436 437 static void 438 ExecuteOSI (void) 439 { 440 ACPI_STATUS Status; 441 ACPI_OBJECT_LIST ArgList; 442 ACPI_OBJECT Arg[1]; 443 ACPI_BUFFER ReturnValue; 444 ACPI_OBJECT *Object; 445 446 447 ACPI_INFO ((AE_INFO, "Executing _OSI reserved method")); 448 449 /* Setup input argument */ 450 451 ArgList.Count = 1; 452 ArgList.Pointer = Arg; 453 454 Arg[0].Type = ACPI_TYPE_STRING; 455 Arg[0].String.Pointer = "Windows 2001"; 456 Arg[0].String.Length = strlen (Arg[0].String.Pointer); 457 458 /* Ask ACPICA to allocate space for the return object */ 459 460 ReturnValue.Length = ACPI_ALLOCATE_BUFFER; 461 462 Status = AcpiEvaluateObject (NULL, "\\_OSI", &ArgList, &ReturnValue); 463 if (ACPI_FAILURE (Status)) 464 { 465 ACPI_EXCEPTION ((AE_INFO, Status, "While executing _OSI")); 466 return; 467 } 468 469 /* Ensure that the return object is large enough */ 470 471 if (ReturnValue.Length < sizeof (ACPI_OBJECT)) 472 { 473 AcpiOsPrintf ("Return value from _OSI method too small, %.8X\n", 474 ReturnValue.Length); 475 goto ErrorExit; 476 } 477 478 /* Expect an integer return value from execution of _OSI */ 479 480 Object = ReturnValue.Pointer; 481 if (Object->Type != ACPI_TYPE_INTEGER) 482 { 483 AcpiOsPrintf ("Invalid return type from _OSI, %.2X\n", Object->Type); 484 } 485 486 ACPI_INFO ((AE_INFO, "_OSI returned 0x%8.8X", 487 (UINT32) Object->Integer.Value)); 488 489 490 ErrorExit: 491 492 /* Free a buffer created via ACPI_ALLOCATE_BUFFER */ 493 494 AcpiOsFree (ReturnValue.Pointer); 495 } 496 497 498 /****************************************************************************** 499 * 500 * Execute an actual control method in the DSDT (MAIN) 501 * 502 *****************************************************************************/ 503 504 static void 505 ExecuteMAIN (void) 506 { 507 ACPI_STATUS Status; 508 ACPI_OBJECT_LIST ArgList; 509 ACPI_OBJECT Arg[1]; 510 ACPI_BUFFER ReturnValue; 511 ACPI_OBJECT *Object; 512 513 514 ACPI_INFO ((AE_INFO, "Executing MAIN method")); 515 516 /* Setup input argument */ 517 518 ArgList.Count = 1; 519 ArgList.Pointer = Arg; 520 521 Arg[0].Type = ACPI_TYPE_STRING; 522 Arg[0].String.Pointer = "Method [MAIN] is executing"; 523 Arg[0].String.Length = strlen (Arg[0].String.Pointer); 524 525 /* Ask ACPICA to allocate space for the return object */ 526 527 ReturnValue.Length = ACPI_ALLOCATE_BUFFER; 528 529 Status = AcpiEvaluateObject (NULL, "\\MAIN", &ArgList, &ReturnValue); 530 if (ACPI_FAILURE (Status)) 531 { 532 ACPI_EXCEPTION ((AE_INFO, Status, "While executing MAIN")); 533 return; 534 } 535 536 if (ReturnValue.Pointer) 537 { 538 /* Obtain and validate the returned ACPI_OBJECT */ 539 540 Object = ReturnValue.Pointer; 541 if (Object->Type == ACPI_TYPE_STRING) 542 { 543 AcpiOsPrintf ("Method [MAIN] returned: \"%s\"\n", 544 Object->String.Pointer); 545 } 546 547 ACPI_FREE (ReturnValue.Pointer); 548 } 549 } 550