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