xref: /netbsd-src/sys/external/bsd/acpica/dist/tools/acpiexec/aeinstall.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
1 /******************************************************************************
2  *
3  * Module Name: aeinstall - Installation of operation region handlers
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 "aecommon.h"
45 
46 #define _COMPONENT          ACPI_TOOLS
47         ACPI_MODULE_NAME    ("aeinstall")
48 
49 
50 static ACPI_STATUS
51 AeRegionInit (
52     ACPI_HANDLE             RegionHandle,
53     UINT32                  Function,
54     void                    *HandlerContext,
55     void                    **RegionContext);
56 
57 static ACPI_STATUS
58 AeInstallEcHandler (
59     ACPI_HANDLE             ObjHandle,
60     UINT32                  Level,
61     void                    *Context,
62     void                    **ReturnValue);
63 
64 static ACPI_STATUS
65 AeInstallPciHandler (
66     ACPI_HANDLE             ObjHandle,
67     UINT32                  Level,
68     void                    *Context,
69     void                    **ReturnValue);
70 
71 static ACPI_STATUS
72 AeInstallGedHandler (
73     ACPI_HANDLE             ObjHandle,
74     UINT32                  Level,
75     void                    *Context,
76     void                    **ReturnValue);
77 
78 
79 BOOLEAN                     AcpiGbl_DisplayRegionAccess = FALSE;
80 ACPI_CONNECTION_INFO        AeMyContext;
81 
82 
83 /*
84  * We will override some of the default region handlers, especially
85  * the SystemMemory handler, which must be implemented locally.
86  * These handlers are installed "early" - before any _REG methods
87  * are executed - since they are special in the sense that the ACPI spec
88  * declares that they must "always be available". Cannot override the
89  * DataTable region handler either -- needed for test execution.
90  *
91  * NOTE: The local region handler will simulate access to these address
92  * spaces by creating a memory buffer behind each operation region.
93  */
94 static ACPI_ADR_SPACE_TYPE  DefaultSpaceIdList[] =
95 {
96     ACPI_ADR_SPACE_SYSTEM_MEMORY,
97     ACPI_ADR_SPACE_SYSTEM_IO,
98     ACPI_ADR_SPACE_PCI_CONFIG,
99     ACPI_ADR_SPACE_EC
100 };
101 
102 /*
103  * We will install handlers for some of the various address space IDs.
104  * Test one user-defined address space (used by aslts).
105  */
106 #define ACPI_ADR_SPACE_USER_DEFINED1        0x80
107 #define ACPI_ADR_SPACE_USER_DEFINED2        0xE4
108 
109 static ACPI_ADR_SPACE_TYPE  SpaceIdList[] =
110 {
111     ACPI_ADR_SPACE_SMBUS,
112     ACPI_ADR_SPACE_CMOS,
113     ACPI_ADR_SPACE_PCI_BAR_TARGET,
114     ACPI_ADR_SPACE_IPMI,
115     ACPI_ADR_SPACE_GPIO,
116     ACPI_ADR_SPACE_GSBUS,
117     ACPI_ADR_SPACE_PLATFORM_COMM,
118     ACPI_ADR_SPACE_PLATFORM_RT,
119     ACPI_ADR_SPACE_FIXED_HARDWARE,
120     ACPI_ADR_SPACE_USER_DEFINED1,
121     ACPI_ADR_SPACE_USER_DEFINED2
122 };
123 
124 
125 /******************************************************************************
126  *
127  * FUNCTION:    AeRegionInit
128  *
129  * PARAMETERS:  Region init handler
130  *
131  * RETURN:      Status
132  *
133  * DESCRIPTION: Opregion init function.
134  *
135  *****************************************************************************/
136 
137 static ACPI_STATUS
AeRegionInit(ACPI_HANDLE RegionHandle,UINT32 Function,void * HandlerContext,void ** RegionContext)138 AeRegionInit (
139     ACPI_HANDLE                 RegionHandle,
140     UINT32                      Function,
141     void                        *HandlerContext,
142     void                        **RegionContext)
143 {
144 
145     if (Function == ACPI_REGION_DEACTIVATE)
146     {
147         *RegionContext = NULL;
148     }
149     else
150     {
151         *RegionContext = RegionHandle;
152     }
153 
154     return (AE_OK);
155 }
156 
157 
158 /******************************************************************************
159  *
160  * FUNCTION:    AeOverrideRegionHandlers
161  *
162  * PARAMETERS:  None
163  *
164  * RETURN:      None
165  *
166  * DESCRIPTION: Override the default region handlers for memory, i/o, and
167  *              pci_config. Also install a handler for EC. This is part of
168  *              the "install early handlers" functionality.
169  *
170  *****************************************************************************/
171 
172 void
AeOverrideRegionHandlers(void)173 AeOverrideRegionHandlers (
174     void)
175 {
176     UINT32                  i;
177     ACPI_STATUS             Status;
178 
179     /*
180      * Install handlers that will override the default handlers for some of
181      * the space IDs.
182      */
183     for (i = 0; i < ACPI_ARRAY_LENGTH (DefaultSpaceIdList); i++)
184     {
185         /* Install handler at the root object */
186 
187         Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT,
188             DefaultSpaceIdList[i], AeRegionHandler, AeRegionInit,
189             &AeMyContext);
190 
191         if (ACPI_FAILURE (Status))
192         {
193             ACPI_EXCEPTION ((AE_INFO, Status,
194                 "Could not install an OpRegion handler for %s space(%u)",
195                 AcpiUtGetRegionName ((UINT8) DefaultSpaceIdList[i]),
196                 DefaultSpaceIdList[i]));
197         }
198     }
199 }
200 
201 
202 /******************************************************************************
203  *
204  * FUNCTION:    AeInstallRegionHandlers
205  *
206  * PARAMETERS:  None
207  *
208  * RETURN:      None
209  *
210  * DESCRIPTION: Install handlers for the address spaces other than
211  *              SystemMemory, SystemIO, and PCI_CONFIG.
212  *
213  *****************************************************************************/
214 
215 void
AeInstallRegionHandlers(void)216 AeInstallRegionHandlers (
217     void)
218 {
219     UINT32                  i;
220     ACPI_STATUS             Status;
221 
222 
223     /*
224      * Install handlers for some of the "device driver" address spaces
225      * such as SMBus, etc.
226      */
227     for (i = 0; i < ACPI_ARRAY_LENGTH (SpaceIdList); i++)
228     {
229         /* Install handler at the root object */
230 
231         Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT,
232             SpaceIdList[i], AeRegionHandler, AeRegionInit,
233             &AeMyContext);
234 
235         if (ACPI_FAILURE (Status))
236         {
237             ACPI_EXCEPTION ((AE_INFO, Status,
238                 "Could not install an OpRegion handler for %s space(%u)",
239                 AcpiUtGetRegionName((UINT8) SpaceIdList[i]), SpaceIdList[i]));
240             return;
241         }
242     }
243 }
244 
245 /*******************************************************************************
246  *
247  * FUNCTION:    AeInstallGedHandler
248  *
249  * PARAMETERS:  ACPI_WALK_NAMESPACE callback
250  *
251  * RETURN:      Status
252  *
253  * DESCRIPTION: Walk entire namespace, install a handler for every GED
254  *              device found.
255  *
256  ******************************************************************************/
257 static ACPI_STATUS
AeInstallGedHandler(ACPI_HANDLE ObjHandle,UINT32 Level,void * Context,void ** ReturnValue)258 AeInstallGedHandler (
259     ACPI_HANDLE             ObjHandle,
260     UINT32                  Level,
261     void                    *Context,
262     void                    **ReturnValue)
263 {
264 
265 	ACPI_BUFFER             ReturnBuffer;
266 	ACPI_STATUS Status;
267 	ACPI_RESOURCE *ResourceList;
268 	ACPI_RESOURCE_EXTENDED_IRQ *extended_irq_rsc;
269     ACPI_NAMESPACE_NODE     *Node;
270 	ACPI_NAMESPACE_NODE		*EvtMethodNode;
271 
272     ACPI_FUNCTION_ENTRY();
273 
274 	/* Obtain the Namespace Node of this GED object handle. */
275 	Node = AcpiNsValidateHandle (ObjHandle);
276 	if (!Node)
277 	{
278 		return (AE_BAD_PARAMETER);
279 	}
280 
281 	/*
282 	 * A GED device must have one _EVT method.
283 	 * Obtain the _EVT method and store it in the global
284 	 * GED register.
285 	 */
286 	Status = AcpiNsSearchOneScope (
287 		*ACPI_CAST_PTR (ACPI_NAME, METHOD_NAME__EVT),
288 		Node,
289 		ACPI_TYPE_METHOD,
290 		&EvtMethodNode
291 	);
292 	if (ACPI_FAILURE (Status))
293 	{
294 		AcpiOsPrintf ("Failed to obtain _EVT method for the GED device.\n");
295 		return Status;
296 	}
297 
298 	ReturnBuffer.Pointer = NULL;
299     ReturnBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
300 
301 	Status = AcpiGetCurrentResources (ObjHandle, &ReturnBuffer);
302 	if (ACPI_FAILURE (Status))
303 	{
304 		AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n",
305 			AcpiFormatException (Status));
306 		return Status;
307 	}
308 
309 	/* Traverse the _CRS resource list */
310 	ResourceList = ACPI_CAST_PTR (ACPI_RESOURCE, ReturnBuffer.Pointer);
311 	while (ResourceList->Type != ACPI_RESOURCE_TYPE_END_TAG) {
312 
313 		switch (ResourceList->Type) {
314 		 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: {
315 
316 			/*
317 			 * Found an Interrupt resource. Link the interrupt resource
318 			 * and the _EVT method of this GED device in the GED event handler list.
319 			 */
320 			ACPI_GED_HANDLER_INFO *GedHandler =
321 			ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
322 			if (!GedHandler)
323 			{
324 				return AE_NO_MEMORY;
325 			}
326 
327 			GedHandler->Next = AcpiGbl_GedHandlerList;
328 			AcpiGbl_GedHandlerList = GedHandler;
329 
330 			extended_irq_rsc = &ResourceList->Data.ExtendedIrq;
331 
332 			GedHandler->IntId = extended_irq_rsc->Interrupts[0];
333 			GedHandler->EvtMethod = EvtMethodNode;
334 
335 			AcpiOsPrintf ("Interrupt ID %d\n", extended_irq_rsc->Interrupts[0]);
336 
337 			break;
338 		 }
339 		 default:
340 
341 			AcpiOsPrintf ("Resource type %X\n", ResourceList->Type);
342 		}
343 
344 		ResourceList = ACPI_NEXT_RESOURCE (ResourceList);
345 	}
346 
347 	return AE_OK;
348 }
349 
350 /*******************************************************************************
351  *
352  * FUNCTION:    AeInstallDeviceHandlers
353  *
354  * PARAMETERS:  None
355  *
356  * RETURN:      Status
357  *
358  * DESCRIPTION: Install handlers for all EC, PCI and GED devices in the namespace
359  *
360  ******************************************************************************/
361 
362 ACPI_STATUS
AeInstallDeviceHandlers(void)363 AeInstallDeviceHandlers (
364     void)
365 {
366 
367     /* Find all Embedded Controller devices */
368 
369     AcpiGetDevices ("PNP0C09", AeInstallEcHandler, NULL, NULL);
370 
371     /* Install a PCI handler */
372 
373     AcpiGetDevices ("PNP0A08", AeInstallPciHandler, NULL, NULL);
374 
375     /* Install a GED handler */
376 
377     AcpiGetDevices ("ACPI0013", AeInstallGedHandler, NULL, NULL);
378 
379     return (AE_OK);
380 }
381 
382 
383 /*******************************************************************************
384  *
385  * FUNCTION:    AeInstallEcHandler
386  *
387  * PARAMETERS:  ACPI_WALK_NAMESPACE callback
388  *
389  * RETURN:      Status
390  *
391  * DESCRIPTION: Walk entire namespace, install a handler for every EC
392  *              device found.
393  *
394  ******************************************************************************/
395 
396 static ACPI_STATUS
AeInstallEcHandler(ACPI_HANDLE ObjHandle,UINT32 Level,void * Context,void ** ReturnValue)397 AeInstallEcHandler (
398     ACPI_HANDLE             ObjHandle,
399     UINT32                  Level,
400     void                    *Context,
401     void                    **ReturnValue)
402 {
403     ACPI_STATUS             Status;
404 
405 
406     /* Install the handler for this EC device */
407 
408     Status = AcpiInstallAddressSpaceHandler (ObjHandle,
409         ACPI_ADR_SPACE_EC, AeRegionHandler, AeRegionInit, &AeMyContext);
410     if (ACPI_FAILURE (Status))
411     {
412         ACPI_EXCEPTION ((AE_INFO, Status,
413             "Could not install an OpRegion handler for EC device (%p)",
414             ObjHandle));
415     }
416 
417     return (Status);
418 }
419 
420 
421 /*******************************************************************************
422  *
423  * FUNCTION:    AeInstallPciHandler
424  *
425  * PARAMETERS:  ACPI_WALK_NAMESPACE callback
426  *
427  * RETURN:      Status
428  *
429  * DESCRIPTION: Walk entire namespace, install a handler for every PCI
430  *              device found.
431  *
432  ******************************************************************************/
433 
434 static ACPI_STATUS
AeInstallPciHandler(ACPI_HANDLE ObjHandle,UINT32 Level,void * Context,void ** ReturnValue)435 AeInstallPciHandler (
436     ACPI_HANDLE             ObjHandle,
437     UINT32                  Level,
438     void                    *Context,
439     void                    **ReturnValue)
440 {
441     ACPI_STATUS             Status;
442 
443 
444     /* Install memory and I/O handlers for the PCI device */
445 
446     Status = AcpiInstallAddressSpaceHandler (ObjHandle,
447         ACPI_ADR_SPACE_SYSTEM_IO, AeRegionHandler, AeRegionInit,
448         &AeMyContext);
449     if (ACPI_FAILURE (Status))
450     {
451         ACPI_EXCEPTION ((AE_INFO, Status,
452             "Could not install an OpRegion handler for PCI device (%p)",
453             ObjHandle));
454     }
455 
456     Status = AcpiInstallAddressSpaceHandler (ObjHandle,
457         ACPI_ADR_SPACE_SYSTEM_MEMORY, AeRegionHandler, AeRegionInit,
458         &AeMyContext);
459     if (ACPI_FAILURE (Status))
460     {
461         ACPI_EXCEPTION ((AE_INFO, Status,
462             "Could not install an OpRegion handler for PCI device (%p)",
463             ObjHandle));
464     }
465 
466     return (AE_CTRL_TERMINATE);
467 }
468