1 /****************************************************************************** 2 * 3 * Module Name: examples - Example ACPICA initialization and execution code 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 #define __EXAMPLES_C__ 45 #include "examples.h" 46 47 #define _COMPONENT ACPI_EXAMPLE 48 ACPI_MODULE_NAME ("examples") 49 50 51 /****************************************************************************** 52 * 53 * ACPICA Example Code 54 * 55 * This module contains examples of how the host OS should interface to the 56 * ACPICA subsystem. 57 * 58 * 1) How to use the platform/acenv.h file and how to set configuration 59 * options. 60 * 61 * 2) main - using the debug output mechanism and the error/warning output 62 * macros. 63 * 64 * 3) Two examples of the ACPICA initialization sequence. The first is a 65 * initialization with no "early" ACPI table access. The second shows 66 * how to use ACPICA to obtain the tables very early during kernel 67 * initialization, even before dynamic memory is available. 68 * 69 * 4) How to invoke a control method, including argument setup and how to 70 * access the return value. 71 * 72 *****************************************************************************/ 73 74 75 /* Local Prototypes */ 76 77 static ACPI_STATUS 78 InitializeFullAcpica (void); 79 80 static ACPI_STATUS 81 InstallHandlers (void); 82 83 static void 84 NotifyHandler ( 85 ACPI_HANDLE Device, 86 UINT32 Value, 87 void *Context); 88 89 static ACPI_STATUS 90 RegionHandler ( 91 UINT32 Function, 92 ACPI_PHYSICAL_ADDRESS Address, 93 UINT32 BitWidth, 94 UINT64 *Value, 95 void *HandlerContext, 96 void *RegionContext); 97 98 static ACPI_STATUS 99 RegionInit ( 100 ACPI_HANDLE RegionHandle, 101 UINT32 Function, 102 void *HandlerContext, 103 void **RegionContext); 104 105 static void 106 ExecuteMAIN (void); 107 108 static void 109 ExecuteOSI (void); 110 111 ACPI_STATUS 112 InitializeAcpiTables ( 113 void); 114 115 ACPI_STATUS 116 InitializeAcpi ( 117 void); 118 119 120 /****************************************************************************** 121 * 122 * FUNCTION: main 123 * 124 * PARAMETERS: argc, argv 125 * 126 * RETURN: Status 127 * 128 * DESCRIPTION: Main routine. Shows the use of the various output macros, as 129 * well as the use of the debug layer/level globals. 130 * 131 *****************************************************************************/ 132 133 int ACPI_SYSTEM_XFACE 134 main ( 135 int argc, 136 char **argv) 137 { 138 139 ACPI_DEBUG_INITIALIZE (); /* For debug version only */ 140 141 printf (ACPI_COMMON_SIGNON ("ACPI Example Code")); 142 143 /* Initialize the local ACPI tables (RSDP/RSDT/XSDT/FADT/DSDT/FACS) */ 144 145 ExInitializeAcpiTables (); 146 147 /* Initialize the ACPICA subsystem */ 148 149 InitializeFullAcpica (); 150 151 /* Example warning and error output */ 152 153 ACPI_INFO ((AE_INFO, "Example ACPICA info message")); 154 ACPI_WARNING ((AE_INFO, "Example ACPICA warning message")); 155 ACPI_ERROR ((AE_INFO, "Example ACPICA error message")); 156 ACPI_EXCEPTION ((AE_INFO, AE_AML_OPERAND_TYPE, "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, ACPI_SYSTEM_NOTIFY, 400 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, ACPI_ADR_SPACE_SYSTEM_MEMORY, 408 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", (UINT32) Object->Integer.Value)); 485 486 487 ErrorExit: 488 489 /* Free a buffer created via ACPI_ALLOCATE_BUFFER */ 490 491 AcpiOsFree (ReturnValue.Pointer); 492 } 493 494 495 /****************************************************************************** 496 * 497 * Execute an actual control method in the DSDT (MAIN) 498 * 499 *****************************************************************************/ 500 501 static void 502 ExecuteMAIN (void) 503 { 504 ACPI_STATUS Status; 505 ACPI_OBJECT_LIST ArgList; 506 ACPI_OBJECT Arg[1]; 507 ACPI_BUFFER ReturnValue; 508 ACPI_OBJECT *Object; 509 510 511 ACPI_INFO ((AE_INFO, "Executing MAIN method")); 512 513 /* Setup input argument */ 514 515 ArgList.Count = 1; 516 ArgList.Pointer = Arg; 517 518 Arg[0].Type = ACPI_TYPE_STRING; 519 Arg[0].String.Pointer = "Method [MAIN] is executing"; 520 Arg[0].String.Length = strlen (Arg[0].String.Pointer); 521 522 /* Ask ACPICA to allocate space for the return object */ 523 524 ReturnValue.Length = ACPI_ALLOCATE_BUFFER; 525 526 Status = AcpiEvaluateObject (NULL, "\\MAIN", &ArgList, &ReturnValue); 527 if (ACPI_FAILURE (Status)) 528 { 529 ACPI_EXCEPTION ((AE_INFO, Status, "While executing MAIN")); 530 return; 531 } 532 533 if (ReturnValue.Pointer) 534 { 535 /* Obtain and validate the returned ACPI_OBJECT */ 536 537 Object = ReturnValue.Pointer; 538 if (Object->Type == ACPI_TYPE_STRING) 539 { 540 AcpiOsPrintf ("Method [MAIN] returned: \"%s\"\n", Object->String.Pointer); 541 } 542 543 ACPI_FREE (ReturnValue.Pointer); 544 } 545 } 546