1 /******************************************************************************
2  *
3  * Module Name: aehandlers - Various handlers for acpiexec
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2013, 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 MERCHANTIBILITY 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    ("aehandlers")
48 
49 /* Local prototypes */
50 
51 static void
52 AeNotifyHandler1 (
53     ACPI_HANDLE             Device,
54     UINT32                  Value,
55     void                    *Context);
56 
57 static void
58 AeNotifyHandler2 (
59     ACPI_HANDLE             Device,
60     UINT32                  Value,
61     void                    *Context);
62 
63 static void
64 AeCommonNotifyHandler (
65     ACPI_HANDLE             Device,
66     UINT32                  Value,
67     UINT32                  HandlerId);
68 
69 static void
70 AeDeviceNotifyHandler (
71     ACPI_HANDLE             Device,
72     UINT32                  Value,
73     void                    *Context);
74 
75 static ACPI_STATUS
76 AeExceptionHandler (
77     ACPI_STATUS             AmlStatus,
78     ACPI_NAME               Name,
79     UINT16                  Opcode,
80     UINT32                  AmlOffset,
81     void                    *Context);
82 
83 static ACPI_STATUS
84 AeTableHandler (
85     UINT32                  Event,
86     void                    *Table,
87     void                    *Context);
88 
89 static ACPI_STATUS
90 AeRegionInit (
91     ACPI_HANDLE             RegionHandle,
92     UINT32                  Function,
93     void                    *HandlerContext,
94     void                    **RegionContext);
95 
96 static void
97 AeAttachedDataHandler (
98     ACPI_HANDLE             Object,
99     void                    *Data);
100 
101 static void
102 AeAttachedDataHandler2 (
103     ACPI_HANDLE             Object,
104     void                    *Data);
105 
106 static UINT32
107 AeInterfaceHandler (
108     ACPI_STRING             InterfaceName,
109     UINT32                  Supported);
110 
111 static ACPI_STATUS
112 AeInstallEcHandler (
113     ACPI_HANDLE             ObjHandle,
114     UINT32                  Level,
115     void                    *Context,
116     void                    **ReturnValue);
117 
118 static ACPI_STATUS
119 AeInstallPciHandler (
120     ACPI_HANDLE             ObjHandle,
121     UINT32                  Level,
122     void                    *Context,
123     void                    **ReturnValue);
124 
125 static ACPI_STATUS
126 AeInstallDeviceHandlers (
127     void);
128 
129 #if (!ACPI_REDUCED_HARDWARE)
130 static UINT32
131 AeEventHandler (
132     void                    *Context);
133 
134 static UINT32
135 AeSciHandler (
136     void                    *Context);
137 
138 static char                *TableEvents[] =
139 {
140     "LOAD",
141     "UNLOAD",
142     "UNKNOWN"
143 };
144 #endif /* !ACPI_REDUCED_HARDWARE */
145 
146 
147 static UINT32               SigintCount = 0;
148 static AE_DEBUG_REGIONS     AeRegions;
149 BOOLEAN                     AcpiGbl_DisplayRegionAccess = FALSE;
150 
151 /*
152  * We will override some of the default region handlers, especially the
153  * SystemMemory handler, which must be implemented locally. Do not override
154  * the PCI_Config handler since we would like to exercise the default handler
155  * code. These handlers are installed "early" - before any _REG methods
156  * are executed - since they are special in the sense that the ACPI spec
157  * declares that they must "always be available". Cannot override the
158  * DataTable region handler either -- needed for test execution.
159  */
160 static ACPI_ADR_SPACE_TYPE  DefaultSpaceIdList[] =
161 {
162     ACPI_ADR_SPACE_SYSTEM_MEMORY,
163     ACPI_ADR_SPACE_SYSTEM_IO
164 };
165 
166 /*
167  * We will install handlers for some of the various address space IDs.
168  * Test one user-defined address space (used by aslts).
169  */
170 #define ACPI_ADR_SPACE_USER_DEFINED1        0x80
171 #define ACPI_ADR_SPACE_USER_DEFINED2        0xE4
172 
173 static ACPI_ADR_SPACE_TYPE  SpaceIdList[] =
174 {
175     ACPI_ADR_SPACE_SMBUS,
176     ACPI_ADR_SPACE_CMOS,
177     ACPI_ADR_SPACE_PCI_BAR_TARGET,
178     ACPI_ADR_SPACE_IPMI,
179     ACPI_ADR_SPACE_GPIO,
180     ACPI_ADR_SPACE_GSBUS,
181     ACPI_ADR_SPACE_FIXED_HARDWARE,
182     ACPI_ADR_SPACE_USER_DEFINED1,
183     ACPI_ADR_SPACE_USER_DEFINED2
184 };
185 
186 static ACPI_CONNECTION_INFO   AeMyContext;
187 
188 
189 /******************************************************************************
190  *
191  * FUNCTION:    AeCtrlCHandler
192  *
193  * PARAMETERS:  Sig
194  *
195  * RETURN:      none
196  *
197  * DESCRIPTION: Control-C handler. Abort running control method if any.
198  *
199  *****************************************************************************/
200 
201 void ACPI_SYSTEM_XFACE
202 AeCtrlCHandler (
203     int                     Sig)
204 {
205 
206     signal (SIGINT, SIG_IGN);
207     SigintCount++;
208 
209     AcpiOsPrintf ("Caught a ctrl-c (#%u)\n\n", SigintCount);
210 
211     if (AcpiGbl_MethodExecuting)
212     {
213         AcpiGbl_AbortMethod = TRUE;
214         signal (SIGINT, AeCtrlCHandler);
215 
216         if (SigintCount < 10)
217         {
218             return;
219         }
220     }
221 
222     (void) AcpiOsTerminate ();
223     exit (0);
224 }
225 
226 
227 /******************************************************************************
228  *
229  * FUNCTION:    AeNotifyHandler(s)
230  *
231  * PARAMETERS:  Standard notify handler parameters
232  *
233  * RETURN:      Status
234  *
235  * DESCRIPTION: Notify handlers for AcpiExec utility. Used by the ASL
236  *              test suite(s) to communicate errors and other information to
237  *              this utility via the Notify() operator. Tests notify handling
238  *              and multiple notify handler support.
239  *
240  *****************************************************************************/
241 
242 static void
243 AeNotifyHandler1 (
244     ACPI_HANDLE             Device,
245     UINT32                  Value,
246     void                    *Context)
247 {
248     AeCommonNotifyHandler (Device, Value, 1);
249 }
250 
251 static void
252 AeNotifyHandler2 (
253     ACPI_HANDLE             Device,
254     UINT32                  Value,
255     void                    *Context)
256 {
257     AeCommonNotifyHandler (Device, Value, 2);
258 }
259 
260 static void
261 AeCommonNotifyHandler (
262     ACPI_HANDLE             Device,
263     UINT32                  Value,
264     UINT32                  HandlerId)
265 {
266     char                    *Type;
267 
268 
269     Type = "Device";
270     if (Value <= ACPI_MAX_SYS_NOTIFY)
271     {
272         Type = "System";
273     }
274 
275     switch (Value)
276     {
277 #if 0
278     case 0:
279 
280         printf ("[AcpiExec] Method Error 0x%X: Results not equal\n", Value);
281         if (AcpiGbl_DebugFile)
282         {
283             AcpiOsPrintf ("[AcpiExec] Method Error: Results not equal\n");
284         }
285         break;
286 
287     case 1:
288 
289         printf ("[AcpiExec] Method Error: Incorrect numeric result\n");
290         if (AcpiGbl_DebugFile)
291         {
292             AcpiOsPrintf ("[AcpiExec] Method Error: Incorrect numeric result\n");
293         }
294         break;
295 
296     case 2:
297 
298         printf ("[AcpiExec] Method Error: An operand was overwritten\n");
299         if (AcpiGbl_DebugFile)
300         {
301             AcpiOsPrintf ("[AcpiExec] Method Error: An operand was overwritten\n");
302         }
303         break;
304 
305 #endif
306 
307     default:
308 
309         printf ("[AcpiExec] Handler %u: Received a %s Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
310             HandlerId, Type, AcpiUtGetNodeName (Device), Device, Value,
311             AcpiUtGetNotifyName (Value));
312         if (AcpiGbl_DebugFile)
313         {
314             AcpiOsPrintf ("[AcpiExec] Handler %u: Received a %s notify, Value 0x%2.2X\n",
315                 HandlerId, Type, Value);
316         }
317 
318         (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
319         break;
320     }
321 }
322 
323 
324 /******************************************************************************
325  *
326  * FUNCTION:    AeSystemNotifyHandler
327  *
328  * PARAMETERS:  Standard notify handler parameters
329  *
330  * RETURN:      Status
331  *
332  * DESCRIPTION: System notify handler for AcpiExec utility. Used by the ASL
333  *              test suite(s) to communicate errors and other information to
334  *              this utility via the Notify() operator.
335  *
336  *****************************************************************************/
337 
338 static void
339 AeSystemNotifyHandler (
340     ACPI_HANDLE                 Device,
341     UINT32                      Value,
342     void                        *Context)
343 {
344 
345     printf ("[AcpiExec] Global:    Received a System Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
346         AcpiUtGetNodeName (Device), Device, Value,
347         AcpiUtGetNotifyName (Value));
348     if (AcpiGbl_DebugFile)
349     {
350         AcpiOsPrintf ("[AcpiExec] Global:    Received a System Notify, Value 0x%2.2X\n", Value);
351     }
352 
353     (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
354 }
355 
356 
357 /******************************************************************************
358  *
359  * FUNCTION:    AeDeviceNotifyHandler
360  *
361  * PARAMETERS:  Standard notify handler parameters
362  *
363  * RETURN:      Status
364  *
365  * DESCRIPTION: Device notify handler for AcpiExec utility. Used by the ASL
366  *              test suite(s) to communicate errors and other information to
367  *              this utility via the Notify() operator.
368  *
369  *****************************************************************************/
370 
371 static void
372 AeDeviceNotifyHandler (
373     ACPI_HANDLE                 Device,
374     UINT32                      Value,
375     void                        *Context)
376 {
377 
378     printf ("[AcpiExec] Global:    Received a Device Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
379         AcpiUtGetNodeName (Device), Device, Value,
380         AcpiUtGetNotifyName (Value));
381     if (AcpiGbl_DebugFile)
382     {
383         AcpiOsPrintf ("[AcpiExec] Global:    Received a Device Notify, Value 0x%2.2X\n", Value);
384     }
385 
386     (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
387 }
388 
389 
390 /******************************************************************************
391  *
392  * FUNCTION:    AeExceptionHandler
393  *
394  * PARAMETERS:  Standard exception handler parameters
395  *
396  * RETURN:      Status
397  *
398  * DESCRIPTION: System exception handler for AcpiExec utility.
399  *
400  *****************************************************************************/
401 
402 static ACPI_STATUS
403 AeExceptionHandler (
404     ACPI_STATUS             AmlStatus,
405     ACPI_NAME               Name,
406     UINT16                  Opcode,
407     UINT32                  AmlOffset,
408     void                    *Context)
409 {
410     ACPI_STATUS             NewAmlStatus = AmlStatus;
411     ACPI_STATUS             Status;
412     ACPI_BUFFER             ReturnObj;
413     ACPI_OBJECT_LIST        ArgList;
414     ACPI_OBJECT             Arg[3];
415     const char              *Exception;
416 
417 
418     Exception = AcpiFormatException (AmlStatus);
419     AcpiOsPrintf ("[AcpiExec] Exception %s during execution ", Exception);
420     if (Name)
421     {
422         AcpiOsPrintf ("of method [%4.4s]", (char *) &Name);
423     }
424     else
425     {
426         AcpiOsPrintf ("at module level (table load)");
427     }
428     AcpiOsPrintf (" Opcode [%s] @%X\n", AcpiPsGetOpcodeName (Opcode), AmlOffset);
429 
430     /*
431      * Invoke the _ERR method if present
432      *
433      * Setup parameter object
434      */
435     ArgList.Count = 3;
436     ArgList.Pointer = Arg;
437 
438     Arg[0].Type = ACPI_TYPE_INTEGER;
439     Arg[0].Integer.Value = AmlStatus;
440 
441     Arg[1].Type = ACPI_TYPE_STRING;
442     Arg[1].String.Pointer = ACPI_CAST_PTR (char, Exception);
443     Arg[1].String.Length = ACPI_STRLEN (Exception);
444 
445     Arg[2].Type = ACPI_TYPE_INTEGER;
446     Arg[2].Integer.Value = AcpiOsGetThreadId();
447 
448     /* Setup return buffer */
449 
450     ReturnObj.Pointer = NULL;
451     ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
452 
453     Status = AcpiEvaluateObject (NULL, "\\_ERR", &ArgList, &ReturnObj);
454     if (ACPI_SUCCESS (Status))
455     {
456         if (ReturnObj.Pointer)
457         {
458             /* Override original status */
459 
460             NewAmlStatus = (ACPI_STATUS)
461                 ((ACPI_OBJECT *) ReturnObj.Pointer)->Integer.Value;
462 
463             /* Free a buffer created via ACPI_ALLOCATE_BUFFER */
464 
465             AcpiOsFree (ReturnObj.Pointer);
466         }
467     }
468     else if (Status != AE_NOT_FOUND)
469     {
470         AcpiOsPrintf ("[AcpiExec] Could not execute _ERR method, %s\n",
471             AcpiFormatException (Status));
472     }
473 
474     /* Global override */
475 
476     if (AcpiGbl_IgnoreErrors)
477     {
478         NewAmlStatus = AE_OK;
479     }
480 
481     if (NewAmlStatus != AmlStatus)
482     {
483         AcpiOsPrintf ("[AcpiExec] Exception override, new status %s\n",
484             AcpiFormatException (NewAmlStatus));
485     }
486 
487     return (NewAmlStatus);
488 }
489 
490 
491 /******************************************************************************
492  *
493  * FUNCTION:    AeTableHandler
494  *
495  * PARAMETERS:  Table handler
496  *
497  * RETURN:      Status
498  *
499  * DESCRIPTION: System table handler for AcpiExec utility.
500  *
501  *****************************************************************************/
502 
503 static ACPI_STATUS
504 AeTableHandler (
505     UINT32                  Event,
506     void                    *Table,
507     void                    *Context)
508 {
509 #if (!ACPI_REDUCED_HARDWARE)
510     ACPI_STATUS             Status;
511 #endif /* !ACPI_REDUCED_HARDWARE */
512 
513 
514     if (Event > ACPI_NUM_TABLE_EVENTS)
515     {
516         Event = ACPI_NUM_TABLE_EVENTS;
517     }
518 
519 #if (!ACPI_REDUCED_HARDWARE)
520     /* Enable any GPEs associated with newly-loaded GPE methods */
521 
522     Status = AcpiUpdateAllGpes ();
523     AE_CHECK_OK (AcpiUpdateAllGpes, Status);
524 
525     printf ("[AcpiExec] Table Event %s, [%4.4s] %p\n",
526         TableEvents[Event], ((ACPI_TABLE_HEADER *) Table)->Signature, Table);
527 #endif /* !ACPI_REDUCED_HARDWARE */
528 
529     return (AE_OK);
530 }
531 
532 
533 /******************************************************************************
534  *
535  * FUNCTION:    AeGpeHandler
536  *
537  * DESCRIPTION: Common GPE handler for acpiexec
538  *
539  *****************************************************************************/
540 
541 UINT32
542 AeGpeHandler (
543     ACPI_HANDLE             GpeDevice,
544     UINT32                  GpeNumber,
545     void                    *Context)
546 {
547     ACPI_NAMESPACE_NODE     *DeviceNode = (ACPI_NAMESPACE_NODE *) GpeDevice;
548 
549 
550     AcpiOsPrintf ("[AcpiExec] GPE Handler received GPE%02X (GPE block %4.4s)\n",
551         GpeNumber, GpeDevice ? DeviceNode->Name.Ascii : "FADT");
552 
553     return (ACPI_REENABLE_GPE);
554 }
555 
556 
557 /******************************************************************************
558  *
559  * FUNCTION:    AeGlobalEventHandler
560  *
561  * DESCRIPTION: Global GPE/Fixed event handler
562  *
563  *****************************************************************************/
564 
565 void
566 AeGlobalEventHandler (
567     UINT32                  Type,
568     ACPI_HANDLE             Device,
569     UINT32                  EventNumber,
570     void                    *Context)
571 {
572     char                    *TypeName;
573 
574 
575     switch (Type)
576     {
577     case ACPI_EVENT_TYPE_GPE:
578 
579         TypeName = "GPE";
580         break;
581 
582     case ACPI_EVENT_TYPE_FIXED:
583 
584         TypeName = "FixedEvent";
585         break;
586 
587     default:
588 
589         TypeName = "UNKNOWN";
590         break;
591     }
592 
593     AcpiOsPrintf ("[AcpiExec] Global Event Handler received: Type %s Number %.2X Dev %p\n",
594         TypeName, EventNumber, Device);
595 }
596 
597 
598 /******************************************************************************
599  *
600  * FUNCTION:    AeAttachedDataHandler
601  *
602  * DESCRIPTION: Handler for deletion of nodes with attached data (attached via
603  *              AcpiAttachData)
604  *
605  *****************************************************************************/
606 
607 static void
608 AeAttachedDataHandler (
609     ACPI_HANDLE             Object,
610     void                    *Data)
611 {
612     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Data);
613 
614 
615     AcpiOsPrintf ("Received an attached data deletion (1) on %4.4s\n",
616         Node->Name.Ascii);
617 }
618 
619 
620 /******************************************************************************
621  *
622  * FUNCTION:    AeAttachedDataHandler2
623  *
624  * DESCRIPTION: Handler for deletion of nodes with attached data (attached via
625  *              AcpiAttachData)
626  *
627  *****************************************************************************/
628 
629 static void
630 AeAttachedDataHandler2 (
631     ACPI_HANDLE             Object,
632     void                    *Data)
633 {
634     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Data);
635 
636 
637     AcpiOsPrintf ("Received an attached data deletion (2) on %4.4s\n",
638         Node->Name.Ascii);
639 }
640 
641 
642 /******************************************************************************
643  *
644  * FUNCTION:    AeInterfaceHandler
645  *
646  * DESCRIPTION: Handler for _OSI invocations
647  *
648  *****************************************************************************/
649 
650 static UINT32
651 AeInterfaceHandler (
652     ACPI_STRING             InterfaceName,
653     UINT32                  Supported)
654 {
655     ACPI_FUNCTION_NAME (AeInterfaceHandler);
656 
657 
658     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
659         "Received _OSI (\"%s\"), is %ssupported\n",
660         InterfaceName, Supported == 0 ? "not " : ""));
661 
662     return (Supported);
663 }
664 
665 
666 #if (!ACPI_REDUCED_HARDWARE)
667 /******************************************************************************
668  *
669  * FUNCTION:    AeEventHandler, AeSciHandler
670  *
671  * DESCRIPTION: Handler for Fixed Events and SCIs
672  *
673  *****************************************************************************/
674 
675 static UINT32
676 AeEventHandler (
677     void                    *Context)
678 {
679     return (0);
680 }
681 
682 static UINT32
683 AeSciHandler (
684     void                    *Context)
685 {
686 
687     AcpiOsPrintf ("[AcpiExec] Received an SCI at handler\n");
688     return (0);
689 }
690 
691 #endif /* !ACPI_REDUCED_HARDWARE */
692 
693 
694 /******************************************************************************
695  *
696  * FUNCTION:    AeRegionInit
697  *
698  * PARAMETERS:  None
699  *
700  * RETURN:      Status
701  *
702  * DESCRIPTION: Opregion init function.
703  *
704  *****************************************************************************/
705 
706 static ACPI_STATUS
707 AeRegionInit (
708     ACPI_HANDLE                 RegionHandle,
709     UINT32                      Function,
710     void                        *HandlerContext,
711     void                        **RegionContext)
712 {
713 
714     if (Function == ACPI_REGION_DEACTIVATE)
715     {
716         *RegionContext = NULL;
717     }
718     else
719     {
720         *RegionContext = RegionHandle;
721     }
722 
723     return (AE_OK);
724 }
725 
726 
727 /*******************************************************************************
728  *
729  * FUNCTION:    AeInstallSciHandler
730  *
731  * PARAMETERS:  None
732  *
733  * RETURN:      Status
734  *
735  * DESCRIPTION: Install handler for SCIs. Exercise the code by doing an
736  *              install/remove/install.
737  *
738  ******************************************************************************/
739 
740 static ACPI_STATUS
741 AeInstallSciHandler (
742     void)
743 {
744     ACPI_STATUS             Status;
745 
746 
747     Status = AcpiInstallSciHandler (AeSciHandler, &AeMyContext);
748     if (ACPI_FAILURE (Status))
749     {
750         ACPI_EXCEPTION ((AE_INFO, Status,
751             "Could not install an SCI handler (1)"));
752     }
753 
754     Status = AcpiRemoveSciHandler (AeSciHandler);
755     if (ACPI_FAILURE (Status))
756     {
757         ACPI_EXCEPTION ((AE_INFO, Status,
758             "Could not remove an SCI handler"));
759     }
760 
761     Status = AcpiInstallSciHandler (AeSciHandler, &AeMyContext);
762     if (ACPI_FAILURE (Status))
763     {
764         ACPI_EXCEPTION ((AE_INFO, Status,
765             "Could not install an SCI handler (2)"));
766     }
767 
768     return (Status);
769 }
770 
771 
772 /*******************************************************************************
773  *
774  * FUNCTION:    AeInstallDeviceHandlers, AeInstallEcHandler,
775  *              AeInstallPciHandler
776  *
777  * PARAMETERS:  ACPI_WALK_NAMESPACE callback
778  *
779  * RETURN:      Status
780  *
781  * DESCRIPTION: Walk entire namespace, install a handler for every EC
782  *              and PCI device found.
783  *
784  ******************************************************************************/
785 
786 static ACPI_STATUS
787 AeInstallEcHandler (
788     ACPI_HANDLE             ObjHandle,
789     UINT32                  Level,
790     void                    *Context,
791     void                    **ReturnValue)
792 {
793     ACPI_STATUS             Status;
794 
795 
796     /* Install the handler for this EC device */
797 
798     Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_EC,
799         AeRegionHandler, AeRegionInit, &AeMyContext);
800     if (ACPI_FAILURE (Status))
801     {
802         ACPI_EXCEPTION ((AE_INFO, Status,
803             "Could not install an OpRegion handler for EC device (%p)",
804             ObjHandle));
805     }
806 
807     return (Status);
808 }
809 
810 static ACPI_STATUS
811 AeInstallPciHandler (
812     ACPI_HANDLE             ObjHandle,
813     UINT32                  Level,
814     void                    *Context,
815     void                    **ReturnValue)
816 {
817     ACPI_STATUS             Status;
818 
819 
820     /* Install memory and I/O handlers for the PCI device */
821 
822     Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_SYSTEM_IO,
823         AeRegionHandler, AeRegionInit, &AeMyContext);
824     if (ACPI_FAILURE (Status))
825     {
826         ACPI_EXCEPTION ((AE_INFO, Status,
827             "Could not install an OpRegion handler for PCI device (%p)",
828             ObjHandle));
829     }
830 
831     Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_SYSTEM_MEMORY,
832         AeRegionHandler, AeRegionInit, &AeMyContext);
833     if (ACPI_FAILURE (Status))
834     {
835         ACPI_EXCEPTION ((AE_INFO, Status,
836             "Could not install an OpRegion handler for PCI device (%p)",
837             ObjHandle));
838     }
839 
840     return (AE_CTRL_TERMINATE);
841 }
842 
843 static ACPI_STATUS
844 AeInstallDeviceHandlers (
845     void)
846 {
847 
848     /* Find all Embedded Controller devices */
849 
850     AcpiGetDevices ("PNP0C09", AeInstallEcHandler, NULL, NULL);
851 
852     /* Install a PCI handler */
853 
854     AcpiGetDevices ("PNP0A08", AeInstallPciHandler, NULL, NULL);
855     return (AE_OK);
856 }
857 
858 
859 /******************************************************************************
860  *
861  * FUNCTION:    AeInstallLateHandlers
862  *
863  * PARAMETERS:  None
864  *
865  * RETURN:      Status
866  *
867  * DESCRIPTION: Install handlers for the AcpiExec utility.
868  *
869  *****************************************************************************/
870 
871 ACPI_STATUS
872 AeInstallLateHandlers (
873     void)
874 {
875     ACPI_STATUS             Status;
876     UINT32                  i;
877 
878 
879 #if (!ACPI_REDUCED_HARDWARE)
880     if (!AcpiGbl_ReducedHardware)
881     {
882         /* Install a user SCI handler */
883 
884         Status = AeInstallSciHandler ();
885         AE_CHECK_OK (AeInstallSciHandler, Status);
886 
887         /* Install some fixed event handlers */
888 
889         Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, AeEventHandler, NULL);
890         AE_CHECK_OK (AcpiInstallFixedEventHandler, Status);
891 
892         Status = AcpiInstallFixedEventHandler (ACPI_EVENT_RTC, AeEventHandler, NULL);
893         AE_CHECK_OK (AcpiInstallFixedEventHandler, Status);
894     }
895 #endif /* !ACPI_REDUCED_HARDWARE */
896 
897     AeMyContext.Connection = NULL;
898     AeMyContext.AccessLength = 0xA5;
899 
900     /*
901      * We will install a handler for each EC device, directly under the EC
902      * device definition. This is unlike the other handlers which we install
903      * at the root node. Also install memory and I/O handlers at any PCI
904      * devices.
905      */
906     AeInstallDeviceHandlers ();
907 
908     /*
909      * Install handlers for some of the "device driver" address spaces
910      * such as SMBus, etc.
911      */
912     for (i = 0; i < ACPI_ARRAY_LENGTH (SpaceIdList); i++)
913     {
914         /* Install handler at the root object */
915 
916         Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT,
917                     SpaceIdList[i], AeRegionHandler,
918                     AeRegionInit, &AeMyContext);
919         if (ACPI_FAILURE (Status))
920         {
921             ACPI_EXCEPTION ((AE_INFO, Status,
922                 "Could not install an OpRegion handler for %s space(%u)",
923                 AcpiUtGetRegionName((UINT8) SpaceIdList[i]), SpaceIdList[i]));
924             return (Status);
925         }
926     }
927 
928     return (AE_OK);
929 }
930 
931 
932 /******************************************************************************
933  *
934  * FUNCTION:    AeInstallEarlyHandlers
935  *
936  * PARAMETERS:  None
937  *
938  * RETURN:      Status
939  *
940  * DESCRIPTION: Install handlers for the AcpiExec utility.
941  *
942  * Notes:       Don't install handler for PCI_Config, we want to use the
943  *              default handler to exercise that code.
944  *
945  *****************************************************************************/
946 
947 ACPI_STATUS
948 AeInstallEarlyHandlers (
949     void)
950 {
951     ACPI_STATUS             Status;
952     UINT32                  i;
953     ACPI_HANDLE             Handle;
954 
955 
956     ACPI_FUNCTION_ENTRY ();
957 
958 
959     Status = AcpiInstallInterfaceHandler (AeInterfaceHandler);
960     if (ACPI_FAILURE (Status))
961     {
962         printf ("Could not install interface handler, %s\n",
963             AcpiFormatException (Status));
964     }
965 
966     Status = AcpiInstallTableHandler (AeTableHandler, NULL);
967     if (ACPI_FAILURE (Status))
968     {
969         printf ("Could not install table handler, %s\n",
970             AcpiFormatException (Status));
971     }
972 
973     Status = AcpiInstallExceptionHandler (AeExceptionHandler);
974     if (ACPI_FAILURE (Status))
975     {
976         printf ("Could not install exception handler, %s\n",
977             AcpiFormatException (Status));
978     }
979 
980     /* Install global notify handlers */
981 
982     Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
983         AeSystemNotifyHandler, NULL);
984     if (ACPI_FAILURE (Status))
985     {
986         printf ("Could not install a global system notify handler, %s\n",
987             AcpiFormatException (Status));
988     }
989 
990     Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY,
991         AeDeviceNotifyHandler, NULL);
992     if (ACPI_FAILURE (Status))
993     {
994         printf ("Could not install a global notify handler, %s\n",
995             AcpiFormatException (Status));
996     }
997 
998     Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
999     if (ACPI_SUCCESS (Status))
1000     {
1001         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1002             AeNotifyHandler1, NULL);
1003         if (ACPI_FAILURE (Status))
1004         {
1005             printf ("Could not install a notify handler, %s\n",
1006                 AcpiFormatException (Status));
1007         }
1008 
1009         Status = AcpiRemoveNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1010             AeNotifyHandler1);
1011         if (ACPI_FAILURE (Status))
1012         {
1013             printf ("Could not remove a notify handler, %s\n",
1014                 AcpiFormatException (Status));
1015         }
1016 
1017         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1018             AeNotifyHandler1, NULL);
1019         AE_CHECK_OK (AcpiInstallNotifyHandler, Status);
1020 
1021         Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1022             AeNotifyHandler1);
1023         AE_CHECK_OK (AcpiRemoveNotifyHandler, Status);
1024 
1025 #if 0
1026         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1027             AeNotifyHandler1, NULL);
1028         if (ACPI_FAILURE (Status))
1029         {
1030             printf ("Could not install a notify handler, %s\n",
1031                 AcpiFormatException (Status));
1032         }
1033 #endif
1034 
1035         /* Install two handlers for _SB_ */
1036 
1037         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1038             AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567));
1039 
1040         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1041             AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF));
1042 
1043         /* Attempt duplicate handler installation, should fail */
1044 
1045         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1046             AeNotifyHandler1, ACPI_CAST_PTR (void, 0x77777777));
1047 
1048         Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
1049         AE_CHECK_OK (AcpiAttachData, Status);
1050 
1051         Status = AcpiDetachData (Handle, AeAttachedDataHandler);
1052         AE_CHECK_OK (AcpiDetachData, Status);
1053 
1054         Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
1055         AE_CHECK_OK (AcpiAttachData, Status);
1056 
1057         /* Test support for multiple attaches */
1058 
1059         Status = AcpiAttachData (Handle, AeAttachedDataHandler2, Handle);
1060         AE_CHECK_OK (AcpiAttachData, Status);
1061     }
1062     else
1063     {
1064         printf ("No _SB_ found, %s\n", AcpiFormatException (Status));
1065     }
1066 
1067 
1068     Status = AcpiGetHandle (NULL, "\\_TZ.TZ1", &Handle);
1069     if (ACPI_SUCCESS (Status))
1070     {
1071         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1072             AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567));
1073 
1074         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1075             AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF));
1076 
1077         Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1078             AeNotifyHandler1);
1079         Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1080             AeNotifyHandler2);
1081 
1082         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1083             AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF));
1084 
1085         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1086             AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567));
1087     }
1088 
1089     Status = AcpiGetHandle (NULL, "\\_PR.CPU0", &Handle);
1090     if (ACPI_SUCCESS (Status))
1091     {
1092         Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
1093             AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567));
1094 
1095         Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
1096             AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF));
1097     }
1098 
1099     /*
1100      * Install handlers that will override the default handlers for some of
1101      * the space IDs.
1102      */
1103     for (i = 0; i < ACPI_ARRAY_LENGTH (DefaultSpaceIdList); i++)
1104     {
1105         /* Install handler at the root object */
1106 
1107         Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT,
1108                     DefaultSpaceIdList[i], AeRegionHandler,
1109                     AeRegionInit, &AeMyContext);
1110         if (ACPI_FAILURE (Status))
1111         {
1112             ACPI_EXCEPTION ((AE_INFO, Status,
1113                 "Could not install a default OpRegion handler for %s space(%u)",
1114                 AcpiUtGetRegionName ((UINT8) DefaultSpaceIdList[i]),
1115                 DefaultSpaceIdList[i]));
1116             return (Status);
1117         }
1118     }
1119 
1120     /*
1121      * Initialize the global Region Handler space
1122      * MCW 3/23/00
1123      */
1124     AeRegions.NumberOfRegions = 0;
1125     AeRegions.RegionList = NULL;
1126     return (Status);
1127 }
1128 
1129 
1130 /******************************************************************************
1131  *
1132  * FUNCTION:    AeRegionHandler
1133  *
1134  * PARAMETERS:  Standard region handler parameters
1135  *
1136  * RETURN:      Status
1137  *
1138  * DESCRIPTION: Test handler - Handles some dummy regions via memory that can
1139  *              be manipulated in Ring 3. Simulates actual reads and writes.
1140  *
1141  *****************************************************************************/
1142 
1143 ACPI_STATUS
1144 AeRegionHandler (
1145     UINT32                  Function,
1146     ACPI_PHYSICAL_ADDRESS   Address,
1147     UINT32                  BitWidth,
1148     UINT64                  *Value,
1149     void                    *HandlerContext,
1150     void                    *RegionContext)
1151 {
1152 
1153     ACPI_OPERAND_OBJECT     *RegionObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, RegionContext);
1154     UINT8                   *Buffer = ACPI_CAST_PTR (UINT8, Value);
1155     ACPI_PHYSICAL_ADDRESS   BaseAddress;
1156     ACPI_SIZE               Length;
1157     BOOLEAN                 BufferExists;
1158     AE_REGION               *RegionElement;
1159     void                    *BufferValue;
1160     ACPI_STATUS             Status;
1161     UINT32                  ByteWidth;
1162     UINT32                  i;
1163     UINT8                   SpaceId;
1164     ACPI_CONNECTION_INFO    *MyContext;
1165     UINT32                  Value1;
1166     UINT32                  Value2;
1167     ACPI_RESOURCE           *Resource;
1168 
1169 
1170     ACPI_FUNCTION_NAME (AeRegionHandler);
1171 
1172     /*
1173      * If the object is not a region, simply return
1174      */
1175     if (RegionObject->Region.Type != ACPI_TYPE_REGION)
1176     {
1177         return (AE_OK);
1178     }
1179 
1180     /* Check that we actually got back our context parameter */
1181 
1182     if (HandlerContext != &AeMyContext)
1183     {
1184         printf ("Region handler received incorrect context %p, should be %p\n",
1185             HandlerContext, &AeMyContext);
1186     }
1187 
1188     MyContext = ACPI_CAST_PTR (ACPI_CONNECTION_INFO, HandlerContext);
1189 
1190     /*
1191      * Find the region's address space and length before searching
1192      * the linked list.
1193      */
1194     BaseAddress = RegionObject->Region.Address;
1195     Length = (ACPI_SIZE) RegionObject->Region.Length;
1196     SpaceId = RegionObject->Region.SpaceId;
1197 
1198     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Operation Region request on %s at 0x%X\n",
1199             AcpiUtGetRegionName (RegionObject->Region.SpaceId),
1200             (UINT32) Address));
1201 
1202     /*
1203      * Region support can be disabled with the -do option.
1204      * We use this to support dynamically loaded tables where we pass a valid
1205      * address to the AML.
1206      */
1207     if (AcpiGbl_DbOpt_NoRegionSupport)
1208     {
1209         BufferValue = ACPI_TO_POINTER (Address);
1210         ByteWidth = (BitWidth / 8);
1211 
1212         if (BitWidth % 8)
1213         {
1214             ByteWidth += 1;
1215         }
1216         goto DoFunction;
1217     }
1218 
1219     switch (SpaceId)
1220     {
1221     case ACPI_ADR_SPACE_SYSTEM_IO:
1222         /*
1223          * For I/O space, exercise the port validation
1224          * Note: ReadPort currently always returns all ones, length=BitLength
1225          */
1226         switch (Function & ACPI_IO_MASK)
1227         {
1228         case ACPI_READ:
1229 
1230             if (BitWidth == 64)
1231             {
1232                 /* Split the 64-bit request into two 32-bit requests */
1233 
1234                 Status = AcpiHwReadPort (Address, &Value1, 32);
1235                 AE_CHECK_OK (AcpiHwReadPort, Status);
1236                 Status = AcpiHwReadPort (Address+4, &Value2, 32);
1237                 AE_CHECK_OK (AcpiHwReadPort, Status);
1238 
1239                 *Value = Value1 | ((UINT64) Value2 << 32);
1240             }
1241             else
1242             {
1243                 Status = AcpiHwReadPort (Address, &Value1, BitWidth);
1244                 AE_CHECK_OK (AcpiHwReadPort, Status);
1245                 *Value = (UINT64) Value1;
1246             }
1247             break;
1248 
1249         case ACPI_WRITE:
1250 
1251             if (BitWidth == 64)
1252             {
1253                 /* Split the 64-bit request into two 32-bit requests */
1254 
1255                 Status = AcpiHwWritePort (Address, ACPI_LODWORD (*Value), 32);
1256                 AE_CHECK_OK (AcpiHwWritePort, Status);
1257                 Status = AcpiHwWritePort (Address+4, ACPI_HIDWORD (*Value), 32);
1258                 AE_CHECK_OK (AcpiHwWritePort, Status);
1259             }
1260             else
1261             {
1262                 Status = AcpiHwWritePort (Address, (UINT32) *Value, BitWidth);
1263                 AE_CHECK_OK (AcpiHwWritePort, Status);
1264             }
1265             break;
1266 
1267         default:
1268 
1269             Status = AE_BAD_PARAMETER;
1270             break;
1271         }
1272 
1273         if (ACPI_FAILURE (Status))
1274         {
1275             return (Status);
1276         }
1277 
1278         /* Now go ahead and simulate the hardware */
1279         break;
1280 
1281     /*
1282      * SMBus and GenericSerialBus support the various bidirectional
1283      * protocols.
1284      */
1285     case ACPI_ADR_SPACE_SMBUS:
1286     case ACPI_ADR_SPACE_GSBUS:  /* ACPI 5.0 */
1287 
1288         Length = 0;
1289 
1290         switch (Function & ACPI_IO_MASK)
1291         {
1292         case ACPI_READ:
1293 
1294             switch (Function >> 16)
1295             {
1296             case AML_FIELD_ATTRIB_QUICK:
1297             case AML_FIELD_ATTRIB_SEND_RCV:
1298             case AML_FIELD_ATTRIB_BYTE:
1299 
1300                 Length = 1;
1301                 break;
1302 
1303             case AML_FIELD_ATTRIB_WORD:
1304             case AML_FIELD_ATTRIB_WORD_CALL:
1305 
1306                 Length = 2;
1307                 break;
1308 
1309             case AML_FIELD_ATTRIB_BLOCK:
1310             case AML_FIELD_ATTRIB_BLOCK_CALL:
1311 
1312                 Length = 32;
1313                 break;
1314 
1315             case AML_FIELD_ATTRIB_MULTIBYTE:
1316             case AML_FIELD_ATTRIB_RAW_BYTES:
1317             case AML_FIELD_ATTRIB_RAW_PROCESS:
1318 
1319                 /* (-2) for status/length */
1320                 Length = MyContext->AccessLength - 2;
1321                 break;
1322 
1323             default:
1324 
1325                 break;
1326             }
1327             break;
1328 
1329         case ACPI_WRITE:
1330 
1331             switch (Function >> 16)
1332             {
1333             case AML_FIELD_ATTRIB_QUICK:
1334             case AML_FIELD_ATTRIB_SEND_RCV:
1335             case AML_FIELD_ATTRIB_BYTE:
1336             case AML_FIELD_ATTRIB_WORD:
1337             case AML_FIELD_ATTRIB_BLOCK:
1338 
1339                 Length = 0;
1340                 break;
1341 
1342             case AML_FIELD_ATTRIB_WORD_CALL:
1343                 Length = 2;
1344                 break;
1345 
1346             case AML_FIELD_ATTRIB_BLOCK_CALL:
1347                 Length = 32;
1348                 break;
1349 
1350             case AML_FIELD_ATTRIB_MULTIBYTE:
1351             case AML_FIELD_ATTRIB_RAW_BYTES:
1352             case AML_FIELD_ATTRIB_RAW_PROCESS:
1353 
1354                 /* (-2) for status/length */
1355                 Length = MyContext->AccessLength - 2;
1356                 break;
1357 
1358             default:
1359 
1360                 break;
1361             }
1362             break;
1363 
1364         default:
1365 
1366             break;
1367         }
1368 
1369         if (AcpiGbl_DisplayRegionAccess)
1370         {
1371             AcpiOsPrintf ("AcpiExec: %s "
1372                 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X",
1373                 AcpiUtGetRegionName (SpaceId),
1374                 (Function & ACPI_IO_MASK) ? "Write" : "Read ",
1375                 (UINT32) (Function >> 16),
1376                 (UINT32) Address, (UINT32) BaseAddress,
1377                 Length, BitWidth, Buffer[1]);
1378 
1379             /* GenericSerialBus has a Connection() parameter */
1380 
1381             if (SpaceId == ACPI_ADR_SPACE_GSBUS)
1382             {
1383                 Status = AcpiBufferToResource (MyContext->Connection,
1384                     MyContext->Length, &Resource);
1385 
1386                 AcpiOsPrintf (" [AccLen %.2X Conn %p]",
1387                     MyContext->AccessLength, MyContext->Connection);
1388             }
1389             AcpiOsPrintf ("\n");
1390         }
1391 
1392         /* Setup the return buffer. Note: ASLTS depends on these fill values */
1393 
1394         for (i = 0; i < Length; i++)
1395         {
1396             Buffer[i+2] = (UINT8) (0xA0 + i);
1397         }
1398 
1399         Buffer[0] = 0x7A;
1400         Buffer[1] = (UINT8) Length;
1401         return (AE_OK);
1402 
1403 
1404     case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */
1405 
1406         if (AcpiGbl_DisplayRegionAccess)
1407         {
1408             AcpiOsPrintf ("AcpiExec: IPMI "
1409                 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X\n",
1410                 (Function & ACPI_IO_MASK) ? "Write" : "Read ",
1411                 (UINT32) (Function >> 16), (UINT32) Address, (UINT32) BaseAddress,
1412                 Length, BitWidth, Buffer[1]);
1413         }
1414 
1415         /*
1416          * Regardless of a READ or WRITE, this handler is passed a 66-byte
1417          * buffer in which to return the IPMI status/length/data.
1418          *
1419          * Return some example data to show use of the bidirectional buffer
1420          */
1421         Buffer[0] = 0;       /* Status byte */
1422         Buffer[1] = 64;      /* Return buffer data length */
1423         Buffer[2] = 0;       /* Completion code */
1424         Buffer[3] = 0;       /* Reserved */
1425 
1426         /*
1427          * Fill the 66-byte buffer with the return data.
1428          * Note: ASLTS depends on these fill values.
1429          */
1430         for (i = 4; i < 66; i++)
1431         {
1432             Buffer[i] = (UINT8) (i);
1433         }
1434         return (AE_OK);
1435 
1436     default:
1437         break;
1438     }
1439 
1440     /*
1441      * Search through the linked list for this region's buffer
1442      */
1443     BufferExists = FALSE;
1444     RegionElement = AeRegions.RegionList;
1445 
1446     if (AeRegions.NumberOfRegions)
1447     {
1448         while (!BufferExists && RegionElement)
1449         {
1450             if (RegionElement->Address == BaseAddress &&
1451                 RegionElement->Length == Length &&
1452                 RegionElement->SpaceId == SpaceId)
1453             {
1454                 BufferExists = TRUE;
1455             }
1456             else
1457             {
1458                 RegionElement = RegionElement->NextRegion;
1459             }
1460         }
1461     }
1462 
1463     /*
1464      * If the Region buffer does not exist, create it now
1465      */
1466     if (!BufferExists)
1467     {
1468         /*
1469          * Do the memory allocations first
1470          */
1471         RegionElement = AcpiOsAllocate (sizeof (AE_REGION));
1472         if (!RegionElement)
1473         {
1474             return (AE_NO_MEMORY);
1475         }
1476 
1477         RegionElement->Buffer = AcpiOsAllocate (Length);
1478         if (!RegionElement->Buffer)
1479         {
1480             AcpiOsFree (RegionElement);
1481             return (AE_NO_MEMORY);
1482         }
1483 
1484         /* Initialize the region with the default fill value */
1485 
1486         ACPI_MEMSET (RegionElement->Buffer, AcpiGbl_RegionFillValue, Length);
1487 
1488         RegionElement->Address      = BaseAddress;
1489         RegionElement->Length       = Length;
1490         RegionElement->SpaceId      = SpaceId;
1491         RegionElement->NextRegion   = NULL;
1492 
1493         /*
1494          * Increment the number of regions and put this one
1495          *  at the head of the list as it will probably get accessed
1496          *  more often anyway.
1497          */
1498         AeRegions.NumberOfRegions += 1;
1499 
1500         if (AeRegions.RegionList)
1501         {
1502             RegionElement->NextRegion = AeRegions.RegionList;
1503         }
1504 
1505         AeRegions.RegionList = RegionElement;
1506     }
1507 
1508     /*
1509      * Calculate the size of the memory copy
1510      */
1511     ByteWidth = (BitWidth / 8);
1512 
1513     if (BitWidth % 8)
1514     {
1515         ByteWidth += 1;
1516     }
1517 
1518     /*
1519      * The buffer exists and is pointed to by RegionElement.
1520      * We now need to verify the request is valid and perform the operation.
1521      *
1522      * NOTE: RegionElement->Length is in bytes, therefore it we compare against
1523      * ByteWidth (see above)
1524      */
1525     if (((UINT64) Address + ByteWidth) >
1526         ((UINT64)(RegionElement->Address) + RegionElement->Length))
1527     {
1528         ACPI_WARNING ((AE_INFO,
1529             "Request on [%4.4s] is beyond region limit Req-0x%X+0x%X, Base=0x%X, Len-0x%X",
1530             (RegionObject->Region.Node)->Name.Ascii, (UINT32) Address,
1531             ByteWidth, (UINT32)(RegionElement->Address),
1532             RegionElement->Length));
1533 
1534         return (AE_AML_REGION_LIMIT);
1535     }
1536 
1537     /*
1538      * Get BufferValue to point to the "address" in the buffer
1539      */
1540     BufferValue = ((UINT8 *) RegionElement->Buffer +
1541                     ((UINT64) Address - (UINT64) RegionElement->Address));
1542 
1543 DoFunction:
1544     /*
1545      * Perform a read or write to the buffer space
1546      */
1547     switch (Function)
1548     {
1549     case ACPI_READ:
1550         /*
1551          * Set the pointer Value to whatever is in the buffer
1552          */
1553         ACPI_MEMCPY (Value, BufferValue, ByteWidth);
1554         break;
1555 
1556     case ACPI_WRITE:
1557         /*
1558          * Write the contents of Value to the buffer
1559          */
1560         ACPI_MEMCPY (BufferValue, Value, ByteWidth);
1561         break;
1562 
1563     default:
1564 
1565         return (AE_BAD_PARAMETER);
1566     }
1567 
1568     if (AcpiGbl_DisplayRegionAccess)
1569     {
1570         switch (SpaceId)
1571         {
1572         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1573 
1574             AcpiOsPrintf ("AcpiExec: SystemMemory "
1575                 "%s: Val %.8X Addr %.4X Width %X [REGION: BaseAddr %.4X Len %.2X]\n",
1576                 (Function & ACPI_IO_MASK) ? "Write" : "Read ",
1577                 (UINT32) *Value, (UINT32) Address, BitWidth, (UINT32) BaseAddress, Length);
1578             break;
1579 
1580         case ACPI_ADR_SPACE_GPIO:   /* ACPI 5.0 */
1581 
1582             /* This space is required to always be ByteAcc */
1583 
1584             Status = AcpiBufferToResource (MyContext->Connection,
1585                 MyContext->Length, &Resource);
1586 
1587             AcpiOsPrintf ("AcpiExec: GeneralPurposeIo "
1588                 "%s: Val %.8X Addr %.4X BaseAddr %.4X Len %.2X Width %X AccLen %.2X Conn %p\n",
1589                 (Function & ACPI_IO_MASK) ? "Write" : "Read ", (UINT32) *Value,
1590                 (UINT32) Address, (UINT32) BaseAddress, Length, BitWidth,
1591                 MyContext->AccessLength, MyContext->Connection);
1592             break;
1593 
1594         default:
1595 
1596             break;
1597         }
1598     }
1599 
1600     return (AE_OK);
1601 }
1602