1 /******************************************************************************
2  *
3  * Module Name: nsinit - namespace initialization
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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 "acpi.h"
45 #include "accommon.h"
46 #include "acnamesp.h"
47 #include "acdispat.h"
48 #include "acinterp.h"
49 #include "acevents.h"
50 
51 #define _COMPONENT          ACPI_NAMESPACE
52         ACPI_MODULE_NAME    ("nsinit")
53 
54 /* Local prototypes */
55 
56 static ACPI_STATUS
57 AcpiNsInitOneObject (
58     ACPI_HANDLE             ObjHandle,
59     UINT32                  Level,
60     void                    *Context,
61     void                    **ReturnValue);
62 
63 static ACPI_STATUS
64 AcpiNsInitOneDevice (
65     ACPI_HANDLE             ObjHandle,
66     UINT32                  NestingLevel,
67     void                    *Context,
68     void                    **ReturnValue);
69 
70 static ACPI_STATUS
71 AcpiNsFindIniMethods (
72     ACPI_HANDLE             ObjHandle,
73     UINT32                  NestingLevel,
74     void                    *Context,
75     void                    **ReturnValue);
76 
77 
78 /*******************************************************************************
79  *
80  * FUNCTION:    AcpiNsInitializeObjects
81  *
82  * PARAMETERS:  None
83  *
84  * RETURN:      Status
85  *
86  * DESCRIPTION: Walk the entire namespace and perform any necessary
87  *              initialization on the objects found therein
88  *
89  ******************************************************************************/
90 
91 ACPI_STATUS
92 AcpiNsInitializeObjects (
93     void)
94 {
95     ACPI_STATUS             Status;
96     ACPI_INIT_WALK_INFO     Info;
97 
98 
99     ACPI_FUNCTION_TRACE (NsInitializeObjects);
100 
101 
102     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
103         "**** Starting initialization of namespace objects ****\n"));
104     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
105         "Completing Region/Field/Buffer/Package initialization:\n"));
106 
107     /* Set all init info to zero */
108 
109     memset (&Info, 0, sizeof (ACPI_INIT_WALK_INFO));
110 
111     /* Walk entire namespace from the supplied root */
112 
113     Status = AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
114         ACPI_UINT32_MAX, AcpiNsInitOneObject, NULL,
115         &Info, NULL);
116     if (ACPI_FAILURE (Status))
117     {
118         ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace"));
119     }
120 
121     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
122         "    Initialized %u/%u Regions %u/%u Fields %u/%u "
123         "Buffers %u/%u Packages (%u nodes)\n",
124         Info.OpRegionInit,  Info.OpRegionCount,
125         Info.FieldInit,     Info.FieldCount,
126         Info.BufferInit,    Info.BufferCount,
127         Info.PackageInit,   Info.PackageCount, Info.ObjectCount));
128 
129     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
130         "%u Control Methods found\n%u Op Regions found\n",
131         Info.MethodCount, Info.OpRegionCount));
132 
133     return_ACPI_STATUS (AE_OK);
134 }
135 
136 
137 /*******************************************************************************
138  *
139  * FUNCTION:    AcpiNsInitializeDevices
140  *
141  * PARAMETERS:  None
142  *
143  * RETURN:      ACPI_STATUS
144  *
145  * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
146  *              This means running _INI on all present devices.
147  *
148  *              Note: We install PCI config space handler on region access,
149  *              not here.
150  *
151  ******************************************************************************/
152 
153 ACPI_STATUS
154 AcpiNsInitializeDevices (
155     UINT32                  Flags)
156 {
157     ACPI_STATUS             Status = AE_OK;
158     ACPI_DEVICE_WALK_INFO   Info;
159 
160 
161     ACPI_FUNCTION_TRACE (NsInitializeDevices);
162 
163 
164     if (!(Flags & ACPI_NO_DEVICE_INIT))
165     {
166         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
167             "[Init] Initializing ACPI Devices\n"));
168 
169         /* Init counters */
170 
171         Info.DeviceCount = 0;
172         Info.Num_STA = 0;
173         Info.Num_INI = 0;
174 
175         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
176             "Initializing Device/Processor/Thermal objects "
177             "and executing _INI/_STA methods:\n"));
178 
179         /* Tree analysis: find all subtrees that contain _INI methods */
180 
181         Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
182             ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, NULL, &Info, NULL);
183         if (ACPI_FAILURE (Status))
184         {
185             goto ErrorExit;
186         }
187 
188         /* Allocate the evaluation information block */
189 
190         Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
191         if (!Info.EvaluateInfo)
192         {
193             Status = AE_NO_MEMORY;
194             goto ErrorExit;
195         }
196 
197         /*
198          * Execute the "global" _INI method that may appear at the root.
199          * This support is provided for Windows compatibility (Vista+) and
200          * is not part of the ACPI specification.
201          */
202         Info.EvaluateInfo->PrefixNode = AcpiGbl_RootNode;
203         Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
204         Info.EvaluateInfo->Parameters = NULL;
205         Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;
206 
207         Status = AcpiNsEvaluate (Info.EvaluateInfo);
208         if (ACPI_SUCCESS (Status))
209         {
210             Info.Num_INI++;
211         }
212     }
213 
214     /*
215      * Run all _REG methods
216      *
217      * Note: Any objects accessed by the _REG methods will be automatically
218      * initialized, even if they contain executable AML (see the call to
219      * AcpiNsInitializeObjects below).
220      */
221     if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT))
222     {
223         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
224             "[Init] Executing _REG OpRegion methods\n"));
225 
226         Status = AcpiEvInitializeOpRegions ();
227         if (ACPI_FAILURE (Status))
228         {
229             goto ErrorExit;
230         }
231     }
232 
233     if (!(Flags & ACPI_NO_DEVICE_INIT))
234     {
235         /* Walk namespace to execute all _INIs on present devices */
236 
237         Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
238             ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, NULL, &Info, NULL);
239 
240         /*
241          * Any _OSI requests should be completed by now. If the BIOS has
242          * requested any Windows OSI strings, we will always truncate
243          * I/O addresses to 16 bits -- for Windows compatibility.
244          */
245         if (AcpiGbl_OsiData >= ACPI_OSI_WIN_2000)
246         {
247             AcpiGbl_TruncateIoAddresses = TRUE;
248         }
249 
250         ACPI_FREE (Info.EvaluateInfo);
251         if (ACPI_FAILURE (Status))
252         {
253             goto ErrorExit;
254         }
255 
256         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
257             "    Executed %u _INI methods requiring %u _STA executions "
258             "(examined %u objects)\n",
259             Info.Num_INI, Info.Num_STA, Info.DeviceCount));
260     }
261 
262     return_ACPI_STATUS (Status);
263 
264 
265 ErrorExit:
266     ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization"));
267     return_ACPI_STATUS (Status);
268 }
269 
270 
271 /*******************************************************************************
272  *
273  * FUNCTION:    AcpiNsInitOneObject
274  *
275  * PARAMETERS:  ObjHandle       - Node
276  *              Level           - Current nesting level
277  *              Context         - Points to a init info struct
278  *              ReturnValue     - Not used
279  *
280  * RETURN:      Status
281  *
282  * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every object
283  *              within the  namespace.
284  *
285  *              Currently, the only objects that require initialization are:
286  *              1) Methods
287  *              2) Op Regions
288  *
289  ******************************************************************************/
290 
291 static ACPI_STATUS
292 AcpiNsInitOneObject (
293     ACPI_HANDLE             ObjHandle,
294     UINT32                  Level,
295     void                    *Context,
296     void                    **ReturnValue)
297 {
298     ACPI_OBJECT_TYPE        Type;
299     ACPI_STATUS             Status = AE_OK;
300     ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
301     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
302     ACPI_OPERAND_OBJECT     *ObjDesc;
303 
304 
305     ACPI_FUNCTION_NAME (NsInitOneObject);
306 
307 
308     Info->ObjectCount++;
309 
310     /* And even then, we are only interested in a few object types */
311 
312     Type = AcpiNsGetType (ObjHandle);
313     ObjDesc = AcpiNsGetAttachedObject (Node);
314     if (!ObjDesc)
315     {
316         return (AE_OK);
317     }
318 
319     /* Increment counters for object types we are looking for */
320 
321     switch (Type)
322     {
323     case ACPI_TYPE_REGION:
324 
325         Info->OpRegionCount++;
326         break;
327 
328     case ACPI_TYPE_BUFFER_FIELD:
329 
330         Info->FieldCount++;
331         break;
332 
333     case ACPI_TYPE_LOCAL_BANK_FIELD:
334 
335         Info->FieldCount++;
336         break;
337 
338     case ACPI_TYPE_BUFFER:
339 
340         Info->BufferCount++;
341         break;
342 
343     case ACPI_TYPE_PACKAGE:
344 
345         Info->PackageCount++;
346         break;
347 
348     default:
349 
350         /* No init required, just exit now */
351 
352         return (AE_OK);
353     }
354 
355     /* If the object is already initialized, nothing else to do */
356 
357     if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
358     {
359         return (AE_OK);
360     }
361 
362     /* Must lock the interpreter before executing AML code */
363 
364     AcpiExEnterInterpreter ();
365 
366     /*
367      * Each of these types can contain executable AML code within the
368      * declaration.
369      */
370     switch (Type)
371     {
372     case ACPI_TYPE_REGION:
373 
374         Info->OpRegionInit++;
375         Status = AcpiDsGetRegionArguments (ObjDesc);
376         break;
377 
378     case ACPI_TYPE_BUFFER_FIELD:
379 
380         Info->FieldInit++;
381         Status = AcpiDsGetBufferFieldArguments (ObjDesc);
382         break;
383 
384     case ACPI_TYPE_LOCAL_BANK_FIELD:
385 
386         Info->FieldInit++;
387         Status = AcpiDsGetBankFieldArguments (ObjDesc);
388         break;
389 
390     case ACPI_TYPE_BUFFER:
391 
392         Info->BufferInit++;
393         Status = AcpiDsGetBufferArguments (ObjDesc);
394         break;
395 
396     case ACPI_TYPE_PACKAGE:
397 
398         Info->PackageInit++;
399         Status = AcpiDsGetPackageArguments (ObjDesc);
400         break;
401 
402     default:
403 
404         /* No other types can get here */
405 
406         break;
407     }
408 
409     if (ACPI_FAILURE (Status))
410     {
411         ACPI_EXCEPTION ((AE_INFO, Status,
412             "Could not execute arguments for [%4.4s] (%s)",
413             AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
414     }
415 
416     /*
417      * We ignore errors from above, and always return OK, since we don't want
418      * to abort the walk on any single error.
419      */
420     AcpiExExitInterpreter ();
421     return (AE_OK);
422 }
423 
424 
425 /*******************************************************************************
426  *
427  * FUNCTION:    AcpiNsFindIniMethods
428  *
429  * PARAMETERS:  ACPI_WALK_CALLBACK
430  *
431  * RETURN:      ACPI_STATUS
432  *
433  * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
434  *              device/processor/thermal objects, and marks the entire subtree
435  *              with a SUBTREE_HAS_INI flag. This flag is used during the
436  *              subsequent device initialization walk to avoid entire subtrees
437  *              that do not contain an _INI.
438  *
439  ******************************************************************************/
440 
441 static ACPI_STATUS
442 AcpiNsFindIniMethods (
443     ACPI_HANDLE             ObjHandle,
444     UINT32                  NestingLevel,
445     void                    *Context,
446     void                    **ReturnValue)
447 {
448     ACPI_DEVICE_WALK_INFO   *Info = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
449     ACPI_NAMESPACE_NODE     *Node;
450     ACPI_NAMESPACE_NODE     *ParentNode;
451 
452 
453     /* Keep count of device/processor/thermal objects */
454 
455     Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
456     if ((Node->Type == ACPI_TYPE_DEVICE)    ||
457         (Node->Type == ACPI_TYPE_PROCESSOR) ||
458         (Node->Type == ACPI_TYPE_THERMAL))
459     {
460         Info->DeviceCount++;
461         return (AE_OK);
462     }
463 
464     /* We are only looking for methods named _INI */
465 
466     if (!ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__INI))
467     {
468         return (AE_OK);
469     }
470 
471     /*
472      * The only _INI methods that we care about are those that are
473      * present under Device, Processor, and Thermal objects.
474      */
475     ParentNode = Node->Parent;
476     switch (ParentNode->Type)
477     {
478     case ACPI_TYPE_DEVICE:
479     case ACPI_TYPE_PROCESSOR:
480     case ACPI_TYPE_THERMAL:
481 
482         /* Mark parent and bubble up the INI present flag to the root */
483 
484         while (ParentNode)
485         {
486             ParentNode->Flags |= ANOBJ_SUBTREE_HAS_INI;
487             ParentNode = ParentNode->Parent;
488         }
489         break;
490 
491     default:
492 
493         break;
494     }
495 
496     return (AE_OK);
497 }
498 
499 
500 /*******************************************************************************
501  *
502  * FUNCTION:    AcpiNsInitOneDevice
503  *
504  * PARAMETERS:  ACPI_WALK_CALLBACK
505  *
506  * RETURN:      ACPI_STATUS
507  *
508  * DESCRIPTION: This is called once per device soon after ACPI is enabled
509  *              to initialize each device. It determines if the device is
510  *              present, and if so, calls _INI.
511  *
512  ******************************************************************************/
513 
514 static ACPI_STATUS
515 AcpiNsInitOneDevice (
516     ACPI_HANDLE             ObjHandle,
517     UINT32                  NestingLevel,
518     void                    *Context,
519     void                    **ReturnValue)
520 {
521     ACPI_DEVICE_WALK_INFO   *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
522     ACPI_EVALUATE_INFO      *Info = WalkInfo->EvaluateInfo;
523     UINT32                  Flags;
524     ACPI_STATUS             Status;
525     ACPI_NAMESPACE_NODE     *DeviceNode;
526 
527 
528     ACPI_FUNCTION_TRACE (NsInitOneDevice);
529 
530 
531     /* We are interested in Devices, Processors and ThermalZones only */
532 
533     DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
534     if ((DeviceNode->Type != ACPI_TYPE_DEVICE)    &&
535         (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
536         (DeviceNode->Type != ACPI_TYPE_THERMAL))
537     {
538         return_ACPI_STATUS (AE_OK);
539     }
540 
541     /*
542      * Because of an earlier namespace analysis, all subtrees that contain an
543      * _INI method are tagged.
544      *
545      * If this device subtree does not contain any _INI methods, we
546      * can exit now and stop traversing this entire subtree.
547      */
548     if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
549     {
550         return_ACPI_STATUS (AE_CTRL_DEPTH);
551     }
552 
553     /*
554      * Run _STA to determine if this device is present and functioning. We
555      * must know this information for two important reasons (from ACPI spec):
556      *
557      * 1) We can only run _INI if the device is present.
558      * 2) We must abort the device tree walk on this subtree if the device is
559      *    not present and is not functional (we will not examine the children)
560      *
561      * The _STA method is not required to be present under the device, we
562      * assume the device is present if _STA does not exist.
563      */
564     ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
565         ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));
566 
567     Status = AcpiUtExecute_STA (DeviceNode, &Flags);
568     if (ACPI_FAILURE (Status))
569     {
570         /* Ignore error and move on to next device */
571 
572         return_ACPI_STATUS (AE_OK);
573     }
574 
575     /*
576      * Flags == -1 means that _STA was not found. In this case, we assume that
577      * the device is both present and functional.
578      *
579      * From the ACPI spec, description of _STA:
580      *
581      * "If a device object (including the processor object) does not have an
582      * _STA object, then OSPM assumes that all of the above bits are set (in
583      * other words, the device is present, ..., and functioning)"
584      */
585     if (Flags != ACPI_UINT32_MAX)
586     {
587         WalkInfo->Num_STA++;
588     }
589 
590     /*
591      * Examine the PRESENT and FUNCTIONING status bits
592      *
593      * Note: ACPI spec does not seem to specify behavior for the present but
594      * not functioning case, so we assume functioning if present.
595      */
596     if (!(Flags & ACPI_STA_DEVICE_PRESENT))
597     {
598         /* Device is not present, we must examine the Functioning bit */
599 
600         if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
601         {
602             /*
603              * Device is not present but is "functioning". In this case,
604              * we will not run _INI, but we continue to examine the children
605              * of this device.
606              *
607              * From the ACPI spec, description of _STA: (Note - no mention
608              * of whether to run _INI or not on the device in question)
609              *
610              * "_STA may return bit 0 clear (not present) with bit 3 set
611              * (device is functional). This case is used to indicate a valid
612              * device for which no device driver should be loaded (for example,
613              * a bridge device.) Children of this device may be present and
614              * valid. OSPM should continue enumeration below a device whose
615              * _STA returns this bit combination"
616              */
617             return_ACPI_STATUS (AE_OK);
618         }
619         else
620         {
621             /*
622              * Device is not present and is not functioning. We must abort the
623              * walk of this subtree immediately -- don't look at the children
624              * of such a device.
625              *
626              * From the ACPI spec, description of _INI:
627              *
628              * "If the _STA method indicates that the device is not present,
629              * OSPM will not run the _INI and will not examine the children
630              * of the device for _INI methods"
631              */
632             return_ACPI_STATUS (AE_CTRL_DEPTH);
633         }
634     }
635 
636     /*
637      * The device is present or is assumed present if no _STA exists.
638      * Run the _INI if it exists (not required to exist)
639      *
640      * Note: We know there is an _INI within this subtree, but it may not be
641      * under this particular device, it may be lower in the branch.
642      */
643     ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
644         ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));
645 
646     memset (Info, 0, sizeof (ACPI_EVALUATE_INFO));
647     Info->PrefixNode = DeviceNode;
648     Info->RelativePathname = METHOD_NAME__INI;
649     Info->Parameters = NULL;
650     Info->Flags = ACPI_IGNORE_RETURN_VALUE;
651 
652     Status = AcpiNsEvaluate (Info);
653     if (ACPI_SUCCESS (Status))
654     {
655         WalkInfo->Num_INI++;
656     }
657 
658 #ifdef ACPI_DEBUG_OUTPUT
659     else if (Status != AE_NOT_FOUND)
660     {
661         /* Ignore error and move on to next device */
662 
663         char *ScopeName = AcpiNsGetNormalizedPathname (DeviceNode, TRUE);
664 
665         ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
666             ScopeName));
667         ACPI_FREE (ScopeName);
668     }
669 #endif
670 
671     /* Ignore errors from above */
672 
673     Status = AE_OK;
674 
675     /*
676      * The _INI method has been run if present; call the Global Initialization
677      * Handler for this device.
678      */
679     if (AcpiGbl_InitHandler)
680     {
681         Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
682     }
683 
684     return_ACPI_STATUS (Status);
685 }
686