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