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