1/****************************************************************************** 2 * 3 * Module Name: examples - Example ACPICA initialization and execution code 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 76static ACPI_STATUS 77InitializeFullAcpica (void); 78 79static ACPI_STATUS 80InstallHandlers (void); 81 82static void 83NotifyHandler ( 84 ACPI_HANDLE Device, 85 UINT32 Value, 86 void *Context); 87 88static ACPI_STATUS 89RegionHandler ( 90 UINT32 Function, 91 ACPI_PHYSICAL_ADDRESS Address, 92 UINT32 BitWidth, 93 UINT64 *Value, 94 void *HandlerContext, 95 void *RegionContext); 96 97static ACPI_STATUS 98RegionInit ( 99 ACPI_HANDLE RegionHandle, 100 UINT32 Function, 101 void *HandlerContext, 102 void **RegionContext); 103 104static void 105ExecuteMAIN (void); 106 107ACPI_STATUS 108InitializeAcpiTables ( 109 void); 110 111ACPI_STATUS 112InitializeAcpi ( 113 void); 114 115 116/****************************************************************************** 117 * 118 * FUNCTION: main 119 * 120 * PARAMETERS: argc, argv 121 * 122 * RETURN: Status 123 * 124 * DESCRIPTION: Main routine. Shows the use of the various output macros, as 125 * well as the use of the debug layer/level globals. 126 * 127 *****************************************************************************/ 128 129int ACPI_SYSTEM_XFACE 130main ( 131 int argc, 132 char **argv) 133{ 134 135 ACPI_DEBUG_INITIALIZE (); /* For debug version only */ 136 137 printf (ACPI_COMMON_SIGNON ("ACPI Example Code")); 138 139 /* Initialize the local ACPI tables (RSDP/RSDT/XSDT/FADT/DSDT/FACS) */ 140 141 ExInitializeAcpiTables (); 142 143 /* Initialize the ACPICA subsystem */ 144 145 InitializeFullAcpica (); 146 147 /* Example warning and error output */ 148 149 ACPI_INFO (("Example ACPICA info message")); 150 ACPI_WARNING ((AE_INFO, "Example ACPICA warning message")); 151 ACPI_ERROR ((AE_INFO, "Example ACPICA error message")); 152 ACPI_EXCEPTION ((AE_INFO, AE_AML_OPERAND_TYPE, 153 "Example ACPICA exception message")); 154 155 ExecuteOSI (NULL, 0); 156 ExecuteMAIN (); 157 return (0); 158} 159 160 161/****************************************************************************** 162 * 163 * Example ACPICA initialization code. This shows a full initialization with 164 * no early ACPI table access. 165 * 166 *****************************************************************************/ 167 168static ACPI_STATUS 169InitializeFullAcpica (void) 170{ 171 ACPI_STATUS Status; 172 173 174 /* Initialize the ACPICA subsystem */ 175 176 Status = AcpiInitializeSubsystem (); 177 if (ACPI_FAILURE (Status)) 178 { 179 ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA")); 180 return (Status); 181 } 182 183 /* Initialize the ACPICA Table Manager and get all ACPI tables */ 184 185 ACPI_INFO (("Loading ACPI tables")); 186 187 Status = AcpiInitializeTables (NULL, 16, FALSE); 188 if (ACPI_FAILURE (Status)) 189 { 190 ACPI_EXCEPTION ((AE_INFO, Status, "While initializing Table Manager")); 191 return (Status); 192 } 193 194 /* Install local handlers */ 195 196 Status = InstallHandlers (); 197 if (ACPI_FAILURE (Status)) 198 { 199 ACPI_EXCEPTION ((AE_INFO, Status, "While installing handlers")); 200 return (Status); 201 } 202 203 /* Initialize the ACPI hardware */ 204 205 Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION); 206 if (ACPI_FAILURE (Status)) 207 { 208 ACPI_EXCEPTION ((AE_INFO, Status, "While enabling ACPICA")); 209 return (Status); 210 } 211 212 /* Create the ACPI namespace from ACPI tables */ 213 214 Status = AcpiLoadTables (); 215 if (ACPI_FAILURE (Status)) 216 { 217 ACPI_EXCEPTION ((AE_INFO, Status, "While loading ACPI tables")); 218 return (Status); 219 } 220 221 /* Complete the ACPI namespace object initialization */ 222 223 Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION); 224 if (ACPI_FAILURE (Status)) 225 { 226 ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA objects")); 227 return (Status); 228 } 229 230 return (AE_OK); 231} 232 233 234/****************************************************************************** 235 * 236 * Example ACPICA initialization code with early ACPI table access. This shows 237 * an initialization that requires early access to ACPI tables (before 238 * kernel dynamic memory is available) 239 * 240 *****************************************************************************/ 241 242/* 243 * The purpose of this static table array is to avoid the use of kernel 244 * dynamic memory which may not be available during early ACPI table 245 * access. 246 */ 247#define ACPI_MAX_INIT_TABLES 16 248static ACPI_TABLE_DESC TableArray[ACPI_MAX_INIT_TABLES]; 249 250 251/* 252 * This function would be called early in kernel initialization. After this 253 * is called, all ACPI tables are available to the host. 254 */ 255ACPI_STATUS 256InitializeAcpiTables ( 257 void) 258{ 259 ACPI_STATUS Status; 260 261 262 /* Initialize the ACPICA Table Manager and get all ACPI tables */ 263 264 Status = AcpiInitializeTables (TableArray, ACPI_MAX_INIT_TABLES, TRUE); 265 return (Status); 266} 267 268 269/* 270 * This function would be called after the kernel is initialized and 271 * dynamic/virtual memory is available. It completes the initialization of 272 * the ACPICA subsystem. 273 */ 274ACPI_STATUS 275InitializeAcpi ( 276 void) 277{ 278 ACPI_STATUS Status; 279 280 281 /* Initialize the ACPICA subsystem */ 282 283 Status = AcpiInitializeSubsystem (); 284 if (ACPI_FAILURE (Status)) 285 { 286 return (Status); 287 } 288 289 /* Copy the root table list to dynamic memory */ 290 291 Status = AcpiReallocateRootTable (); 292 if (ACPI_FAILURE (Status)) 293 { 294 return (Status); 295 } 296 297 /* Install local handlers */ 298 299 Status = InstallHandlers (); 300 if (ACPI_FAILURE (Status)) 301 { 302 ACPI_EXCEPTION ((AE_INFO, Status, "While installing handlers")); 303 return (Status); 304 } 305 306 /* Initialize the ACPI hardware */ 307 308 Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION); 309 if (ACPI_FAILURE (Status)) 310 { 311 return (Status); 312 } 313 314 /* Create the ACPI namespace from ACPI tables */ 315 316 Status = AcpiLoadTables (); 317 if (ACPI_FAILURE (Status)) 318 { 319 return (Status); 320 } 321 322 /* Complete the ACPI namespace object initialization */ 323 324 Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION); 325 if (ACPI_FAILURE (Status)) 326 { 327 return (Status); 328 } 329 330 return (AE_OK); 331} 332 333 334/****************************************************************************** 335 * 336 * Example ACPICA handler and handler installation 337 * 338 *****************************************************************************/ 339 340static void 341NotifyHandler ( 342 ACPI_HANDLE Device, 343 UINT32 Value, 344 void *Context) 345{ 346 347 ACPI_INFO (("Received a notify 0x%X", Value)); 348} 349 350 351static ACPI_STATUS 352RegionInit ( 353 ACPI_HANDLE RegionHandle, 354 UINT32 Function, 355 void *HandlerContext, 356 void **RegionContext) 357{ 358 359 if (Function == ACPI_REGION_DEACTIVATE) 360 { 361 *RegionContext = NULL; 362 } 363 else 364 { 365 *RegionContext = RegionHandle; 366 } 367 368 return (AE_OK); 369} 370 371 372static ACPI_STATUS 373RegionHandler ( 374 UINT32 Function, 375 ACPI_PHYSICAL_ADDRESS Address, 376 UINT32 BitWidth, 377 UINT64 *Value, 378 void *HandlerContext, 379 void *RegionContext) 380{ 381 382 ACPI_INFO (("Received a region access")); 383 384 return (AE_OK); 385} 386 387 388static ACPI_STATUS 389InstallHandlers (void) 390{ 391 ACPI_STATUS Status; 392 393 394 /* Install global notify handler */ 395 396 Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, 397 ACPI_SYSTEM_NOTIFY, NotifyHandler, NULL); 398 if (ACPI_FAILURE (Status)) 399 { 400 ACPI_EXCEPTION ((AE_INFO, Status, "While installing Notify handler")); 401 return (Status); 402 } 403 404 Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT, 405 ACPI_ADR_SPACE_SYSTEM_MEMORY, RegionHandler, RegionInit, NULL); 406 if (ACPI_FAILURE (Status)) 407 { 408 ACPI_EXCEPTION ((AE_INFO, Status, "While installing an OpRegion handler")); 409 return (Status); 410 } 411 412 return (AE_OK); 413} 414 415 416/****************************************************************************** 417 * 418 * Examples of control method execution. 419 * 420 * _OSI is a predefined method that is implemented internally within ACPICA. 421 * 422 * Shows the following elements: 423 * 424 * 1) How to setup a control method argument and argument list 425 * 2) How to setup the return value object 426 * 3) How to invoke AcpiEvaluateObject 427 * 4) How to check the returned ACPI_STATUS 428 * 5) How to analyze the return value 429 * 430 *****************************************************************************/ 431 432ACPI_STATUS 433ExecuteOSI ( 434 char *OsiString, 435 UINT64 ExpectedResult) 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 (("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 (AE_OK); 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 (UINT32) 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 (("_OSI returned 0x%8.8X", 484 (UINT32) Object->Integer.Value)); 485 486 487ErrorExit: 488 489 /* Free a buffer created via ACPI_ALLOCATE_BUFFER */ 490 491 AcpiOsFree (ReturnValue.Pointer); 492 return (AE_OK); 493} 494 495 496/****************************************************************************** 497 * 498 * Execute an actual control method in the DSDT (MAIN) 499 * 500 *****************************************************************************/ 501 502static void 503ExecuteMAIN (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 (("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