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
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 ACPI_STATUS
108 InitializeAcpiTables (
109 void);
110
111 ACPI_STATUS
112 InitializeAcpi (
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
129 int ACPI_SYSTEM_XFACE
main(int argc,char ** argv)130 main (
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
168 static ACPI_STATUS
InitializeFullAcpica(void)169 InitializeFullAcpica (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
248 static 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 */
255 ACPI_STATUS
InitializeAcpiTables(void)256 InitializeAcpiTables (
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 */
274 ACPI_STATUS
InitializeAcpi(void)275 InitializeAcpi (
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
340 static void
NotifyHandler(ACPI_HANDLE Device,UINT32 Value,void * Context)341 NotifyHandler (
342 ACPI_HANDLE Device,
343 UINT32 Value,
344 void *Context)
345 {
346
347 ACPI_INFO (("Received a notify 0x%X", Value));
348 }
349
350
351 static ACPI_STATUS
RegionInit(ACPI_HANDLE RegionHandle,UINT32 Function,void * HandlerContext,void ** RegionContext)352 RegionInit (
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
372 static ACPI_STATUS
RegionHandler(UINT32 Function,ACPI_PHYSICAL_ADDRESS Address,UINT32 BitWidth,UINT64 * Value,void * HandlerContext,void * RegionContext)373 RegionHandler (
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
388 static ACPI_STATUS
InstallHandlers(void)389 InstallHandlers (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
432 ACPI_STATUS
ExecuteOSI(char * OsiString,UINT64 ExpectedResult)433 ExecuteOSI (
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
487 ErrorExit:
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
502 static void
ExecuteMAIN(void)503 ExecuteMAIN (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