1 | /****************************************************************************** |
2 | * |
3 | * Module Name: nsload - namespace loading/expanding/contracting procedures |
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 "actables.h" |
49 | #include "acinterp.h" |
50 | |
51 | |
52 | #define _COMPONENT ACPI_NAMESPACE |
53 | ACPI_MODULE_NAME ("nsload" ) |
54 | |
55 | /* Local prototypes */ |
56 | |
57 | #ifdef ACPI_FUTURE_IMPLEMENTATION |
58 | ACPI_STATUS |
59 | AcpiNsUnloadNamespace ( |
60 | ACPI_HANDLE Handle); |
61 | |
62 | static ACPI_STATUS |
63 | AcpiNsDeleteSubtree ( |
64 | ACPI_HANDLE StartHandle); |
65 | #endif |
66 | |
67 | |
68 | #ifndef ACPI_NO_METHOD_EXECUTION |
69 | /******************************************************************************* |
70 | * |
71 | * FUNCTION: AcpiNsLoadTable |
72 | * |
73 | * PARAMETERS: TableIndex - Index for table to be loaded |
74 | * Node - Owning NS node |
75 | * |
76 | * RETURN: Status |
77 | * |
78 | * DESCRIPTION: Load one ACPI table into the namespace |
79 | * |
80 | ******************************************************************************/ |
81 | |
82 | ACPI_STATUS |
83 | AcpiNsLoadTable ( |
84 | UINT32 TableIndex, |
85 | ACPI_NAMESPACE_NODE *Node) |
86 | { |
87 | ACPI_STATUS Status; |
88 | |
89 | |
90 | ACPI_FUNCTION_TRACE (NsLoadTable); |
91 | |
92 | |
93 | /* If table already loaded into namespace, just return */ |
94 | |
95 | if (AcpiTbIsTableLoaded (TableIndex)) |
96 | { |
97 | Status = AE_ALREADY_EXISTS; |
98 | goto Unlock; |
99 | } |
100 | |
101 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
102 | "**** Loading table into namespace ****\n" )); |
103 | |
104 | Status = AcpiTbAllocateOwnerId (TableIndex); |
105 | if (ACPI_FAILURE (Status)) |
106 | { |
107 | goto Unlock; |
108 | } |
109 | |
110 | /* |
111 | * Parse the table and load the namespace with all named |
112 | * objects found within. Control methods are NOT parsed |
113 | * at this time. In fact, the control methods cannot be |
114 | * parsed until the entire namespace is loaded, because |
115 | * if a control method makes a forward reference (call) |
116 | * to another control method, we can't continue parsing |
117 | * because we don't know how many arguments to parse next! |
118 | */ |
119 | Status = AcpiNsParseTable (TableIndex, Node); |
120 | if (ACPI_SUCCESS (Status)) |
121 | { |
122 | AcpiTbSetTableLoadedFlag (TableIndex, TRUE); |
123 | } |
124 | else |
125 | { |
126 | /* |
127 | * On error, delete any namespace objects created by this table. |
128 | * We cannot initialize these objects, so delete them. There are |
129 | * a couple of expecially bad cases: |
130 | * AE_ALREADY_EXISTS - namespace collision. |
131 | * AE_NOT_FOUND - the target of a Scope operator does not |
132 | * exist. This target of Scope must already exist in the |
133 | * namespace, as per the ACPI specification. |
134 | */ |
135 | AcpiNsDeleteNamespaceByOwner ( |
136 | AcpiGbl_RootTableList.Tables[TableIndex].OwnerId); |
137 | |
138 | AcpiTbReleaseOwnerId (TableIndex); |
139 | return_ACPI_STATUS (Status); |
140 | } |
141 | |
142 | Unlock: |
143 | if (ACPI_FAILURE (Status)) |
144 | { |
145 | return_ACPI_STATUS (Status); |
146 | } |
147 | |
148 | /* |
149 | * Now we can parse the control methods. We always parse |
150 | * them here for a sanity check, and if configured for |
151 | * just-in-time parsing, we delete the control method |
152 | * parse trees. |
153 | */ |
154 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
155 | "**** Begin Table Object Initialization\n" )); |
156 | |
157 | Status = AcpiDsInitializeObjects (TableIndex, Node); |
158 | |
159 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
160 | "**** Completed Table Object Initialization\n" )); |
161 | |
162 | /* |
163 | * Execute any module-level code that was detected during the table load |
164 | * phase. Although illegal since ACPI 2.0, there are many machines that |
165 | * contain this type of code. Each block of detected executable AML code |
166 | * outside of any control method is wrapped with a temporary control |
167 | * method object and placed on a global list. The methods on this list |
168 | * are executed below. |
169 | * |
170 | * This case executes the module-level code for each table immediately |
171 | * after the table has been loaded. This provides compatibility with |
172 | * other ACPI implementations. Optionally, the execution can be deferred |
173 | * until later, see AcpiInitializeObjects. |
174 | */ |
175 | if (!AcpiGbl_ParseTableAsTermList && !AcpiGbl_GroupModuleLevelCode) |
176 | { |
177 | AcpiNsExecModuleCodeList (); |
178 | } |
179 | |
180 | return_ACPI_STATUS (Status); |
181 | } |
182 | |
183 | |
184 | #ifdef ACPI_OBSOLETE_FUNCTIONS |
185 | /******************************************************************************* |
186 | * |
187 | * FUNCTION: AcpiLoadNamespace |
188 | * |
189 | * PARAMETERS: None |
190 | * |
191 | * RETURN: Status |
192 | * |
193 | * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. |
194 | * (DSDT points to either the BIOS or a buffer.) |
195 | * |
196 | ******************************************************************************/ |
197 | |
198 | ACPI_STATUS |
199 | AcpiNsLoadNamespace ( |
200 | void) |
201 | { |
202 | ACPI_STATUS Status; |
203 | |
204 | |
205 | ACPI_FUNCTION_TRACE (AcpiLoadNameSpace); |
206 | |
207 | |
208 | /* There must be at least a DSDT installed */ |
209 | |
210 | if (AcpiGbl_DSDT == NULL) |
211 | { |
212 | ACPI_ERROR ((AE_INFO, "DSDT is not in memory" )); |
213 | return_ACPI_STATUS (AE_NO_ACPI_TABLES); |
214 | } |
215 | |
216 | /* |
217 | * Load the namespace. The DSDT is required, |
218 | * but the SSDT and PSDT tables are optional. |
219 | */ |
220 | Status = AcpiNsLoadTableByType (ACPI_TABLE_ID_DSDT); |
221 | if (ACPI_FAILURE (Status)) |
222 | { |
223 | return_ACPI_STATUS (Status); |
224 | } |
225 | |
226 | /* Ignore exceptions from these */ |
227 | |
228 | (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_SSDT); |
229 | (void) AcpiNsLoadTableByType (ACPI_TABLE_ID_PSDT); |
230 | |
231 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, |
232 | "ACPI Namespace successfully loaded at root %p\n" , |
233 | AcpiGbl_RootNode)); |
234 | |
235 | return_ACPI_STATUS (Status); |
236 | } |
237 | #endif |
238 | |
239 | #ifdef ACPI_FUTURE_IMPLEMENTATION |
240 | /******************************************************************************* |
241 | * |
242 | * FUNCTION: AcpiNsDeleteSubtree |
243 | * |
244 | * PARAMETERS: StartHandle - Handle in namespace where search begins |
245 | * |
246 | * RETURNS Status |
247 | * |
248 | * DESCRIPTION: Walks the namespace starting at the given handle and deletes |
249 | * all objects, entries, and scopes in the entire subtree. |
250 | * |
251 | * Namespace/Interpreter should be locked or the subsystem should |
252 | * be in shutdown before this routine is called. |
253 | * |
254 | ******************************************************************************/ |
255 | |
256 | static ACPI_STATUS |
257 | AcpiNsDeleteSubtree ( |
258 | ACPI_HANDLE StartHandle) |
259 | { |
260 | ACPI_STATUS Status; |
261 | ACPI_HANDLE ChildHandle; |
262 | ACPI_HANDLE ParentHandle; |
263 | ACPI_HANDLE NextChildHandle; |
264 | ACPI_HANDLE Dummy; |
265 | UINT32 Level; |
266 | |
267 | |
268 | ACPI_FUNCTION_TRACE (NsDeleteSubtree); |
269 | |
270 | |
271 | ParentHandle = StartHandle; |
272 | ChildHandle = NULL; |
273 | Level = 1; |
274 | |
275 | /* |
276 | * Traverse the tree of objects until we bubble back up |
277 | * to where we started. |
278 | */ |
279 | while (Level > 0) |
280 | { |
281 | /* Attempt to get the next object in this scope */ |
282 | |
283 | Status = AcpiGetNextObject (ACPI_TYPE_ANY, ParentHandle, |
284 | ChildHandle, &NextChildHandle); |
285 | |
286 | ChildHandle = NextChildHandle; |
287 | |
288 | /* Did we get a new object? */ |
289 | |
290 | if (ACPI_SUCCESS (Status)) |
291 | { |
292 | /* Check if this object has any children */ |
293 | |
294 | if (ACPI_SUCCESS (AcpiGetNextObject (ACPI_TYPE_ANY, ChildHandle, |
295 | NULL, &Dummy))) |
296 | { |
297 | /* |
298 | * There is at least one child of this object, |
299 | * visit the object |
300 | */ |
301 | Level++; |
302 | ParentHandle = ChildHandle; |
303 | ChildHandle = NULL; |
304 | } |
305 | } |
306 | else |
307 | { |
308 | /* |
309 | * No more children in this object, go back up to |
310 | * the object's parent |
311 | */ |
312 | Level--; |
313 | |
314 | /* Delete all children now */ |
315 | |
316 | AcpiNsDeleteChildren (ChildHandle); |
317 | |
318 | ChildHandle = ParentHandle; |
319 | Status = AcpiGetParent (ParentHandle, &ParentHandle); |
320 | if (ACPI_FAILURE (Status)) |
321 | { |
322 | return_ACPI_STATUS (Status); |
323 | } |
324 | } |
325 | } |
326 | |
327 | /* Now delete the starting object, and we are done */ |
328 | |
329 | AcpiNsRemoveNode (ChildHandle); |
330 | return_ACPI_STATUS (AE_OK); |
331 | } |
332 | |
333 | |
334 | /******************************************************************************* |
335 | * |
336 | * FUNCTION: AcpiNsUnloadNameSpace |
337 | * |
338 | * PARAMETERS: Handle - Root of namespace subtree to be deleted |
339 | * |
340 | * RETURN: Status |
341 | * |
342 | * DESCRIPTION: Shrinks the namespace, typically in response to an undocking |
343 | * event. Deletes an entire subtree starting from (and |
344 | * including) the given handle. |
345 | * |
346 | ******************************************************************************/ |
347 | |
348 | ACPI_STATUS |
349 | AcpiNsUnloadNamespace ( |
350 | ACPI_HANDLE Handle) |
351 | { |
352 | ACPI_STATUS Status; |
353 | |
354 | |
355 | ACPI_FUNCTION_TRACE (NsUnloadNameSpace); |
356 | |
357 | |
358 | /* Parameter validation */ |
359 | |
360 | if (!AcpiGbl_RootNode) |
361 | { |
362 | return_ACPI_STATUS (AE_NO_NAMESPACE); |
363 | } |
364 | |
365 | if (!Handle) |
366 | { |
367 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
368 | } |
369 | |
370 | /* This function does the real work */ |
371 | |
372 | Status = AcpiNsDeleteSubtree (Handle); |
373 | return_ACPI_STATUS (Status); |
374 | } |
375 | #endif |
376 | #endif |
377 | |