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