xref: /netbsd-src/sys/external/bsd/acpica/dist/tools/examples/examples.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
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