1 | /******************************************************************************* |
2 | * |
3 | * Module Name: nsobject - Utilities for objects attached to namespace |
4 | * table entries |
5 | * |
6 | ******************************************************************************/ |
7 | |
8 | /* |
9 | * Copyright (C) 2000 - 2016, Intel Corp. |
10 | * All rights reserved. |
11 | * |
12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions |
14 | * are met: |
15 | * 1. Redistributions of source code must retain the above copyright |
16 | * notice, this list of conditions, and the following disclaimer, |
17 | * without modification. |
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
19 | * substantially similar to the "NO WARRANTY" disclaimer below |
20 | * ("Disclaimer") and any redistribution must be conditioned upon |
21 | * including a substantially similar Disclaimer requirement for further |
22 | * binary redistribution. |
23 | * 3. Neither the names of the above-listed copyright holders nor the names |
24 | * of any contributors may be used to endorse or promote products derived |
25 | * from this software without specific prior written permission. |
26 | * |
27 | * Alternatively, this software may be distributed under the terms of the |
28 | * GNU General Public License ("GPL") version 2 as published by the Free |
29 | * Software Foundation. |
30 | * |
31 | * NO WARRANTY |
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
42 | * POSSIBILITY OF SUCH DAMAGES. |
43 | */ |
44 | |
45 | #include "acpi.h" |
46 | #include "accommon.h" |
47 | #include "acnamesp.h" |
48 | |
49 | |
50 | #define _COMPONENT ACPI_NAMESPACE |
51 | ACPI_MODULE_NAME ("nsobject" ) |
52 | |
53 | |
54 | /******************************************************************************* |
55 | * |
56 | * FUNCTION: AcpiNsAttachObject |
57 | * |
58 | * PARAMETERS: Node - Parent Node |
59 | * Object - Object to be attached |
60 | * Type - Type of object, or ACPI_TYPE_ANY if not |
61 | * known |
62 | * |
63 | * RETURN: Status |
64 | * |
65 | * DESCRIPTION: Record the given object as the value associated with the |
66 | * name whose ACPI_HANDLE is passed. If Object is NULL |
67 | * and Type is ACPI_TYPE_ANY, set the name as having no value. |
68 | * Note: Future may require that the Node->Flags field be passed |
69 | * as a parameter. |
70 | * |
71 | * MUTEX: Assumes namespace is locked |
72 | * |
73 | ******************************************************************************/ |
74 | |
75 | ACPI_STATUS |
76 | AcpiNsAttachObject ( |
77 | ACPI_NAMESPACE_NODE *Node, |
78 | ACPI_OPERAND_OBJECT *Object, |
79 | ACPI_OBJECT_TYPE Type) |
80 | { |
81 | ACPI_OPERAND_OBJECT *ObjDesc; |
82 | ACPI_OPERAND_OBJECT *LastObjDesc; |
83 | ACPI_OBJECT_TYPE ObjectType = ACPI_TYPE_ANY; |
84 | |
85 | |
86 | ACPI_FUNCTION_TRACE (NsAttachObject); |
87 | |
88 | |
89 | /* |
90 | * Parameter validation |
91 | */ |
92 | if (!Node) |
93 | { |
94 | /* Invalid handle */ |
95 | |
96 | ACPI_ERROR ((AE_INFO, "Null NamedObj handle" )); |
97 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
98 | } |
99 | |
100 | if (!Object && (ACPI_TYPE_ANY != Type)) |
101 | { |
102 | /* Null object */ |
103 | |
104 | ACPI_ERROR ((AE_INFO, |
105 | "Null object, but type not ACPI_TYPE_ANY" )); |
106 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
107 | } |
108 | |
109 | if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) |
110 | { |
111 | /* Not a name handle */ |
112 | |
113 | ACPI_ERROR ((AE_INFO, "Invalid handle %p [%s]" , |
114 | Node, AcpiUtGetDescriptorName (Node))); |
115 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
116 | } |
117 | |
118 | /* Check if this object is already attached */ |
119 | |
120 | if (Node->Object == Object) |
121 | { |
122 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
123 | "Obj %p already installed in NameObj %p\n" , |
124 | Object, Node)); |
125 | |
126 | return_ACPI_STATUS (AE_OK); |
127 | } |
128 | |
129 | /* If null object, we will just install it */ |
130 | |
131 | if (!Object) |
132 | { |
133 | ObjDesc = NULL; |
134 | ObjectType = ACPI_TYPE_ANY; |
135 | } |
136 | |
137 | /* |
138 | * If the source object is a namespace Node with an attached object, |
139 | * we will use that (attached) object |
140 | */ |
141 | else if ((ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) && |
142 | ((ACPI_NAMESPACE_NODE *) Object)->Object) |
143 | { |
144 | /* |
145 | * Value passed is a name handle and that name has a |
146 | * non-null value. Use that name's value and type. |
147 | */ |
148 | ObjDesc = ((ACPI_NAMESPACE_NODE *) Object)->Object; |
149 | ObjectType = ((ACPI_NAMESPACE_NODE *) Object)->Type; |
150 | } |
151 | |
152 | /* |
153 | * Otherwise, we will use the parameter object, but we must type |
154 | * it first |
155 | */ |
156 | else |
157 | { |
158 | ObjDesc = (ACPI_OPERAND_OBJECT *) Object; |
159 | |
160 | /* Use the given type */ |
161 | |
162 | ObjectType = Type; |
163 | } |
164 | |
165 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n" , |
166 | ObjDesc, Node, AcpiUtGetNodeName (Node))); |
167 | |
168 | /* Detach an existing attached object if present */ |
169 | |
170 | if (Node->Object) |
171 | { |
172 | AcpiNsDetachObject (Node); |
173 | } |
174 | |
175 | if (ObjDesc) |
176 | { |
177 | /* |
178 | * Must increment the new value's reference count |
179 | * (if it is an internal object) |
180 | */ |
181 | AcpiUtAddReference (ObjDesc); |
182 | |
183 | /* |
184 | * Handle objects with multiple descriptors - walk |
185 | * to the end of the descriptor list |
186 | */ |
187 | LastObjDesc = ObjDesc; |
188 | while (LastObjDesc->Common.NextObject) |
189 | { |
190 | LastObjDesc = LastObjDesc->Common.NextObject; |
191 | } |
192 | |
193 | /* Install the object at the front of the object list */ |
194 | |
195 | LastObjDesc->Common.NextObject = Node->Object; |
196 | } |
197 | |
198 | Node->Type = (UINT8) ObjectType; |
199 | Node->Object = ObjDesc; |
200 | |
201 | return_ACPI_STATUS (AE_OK); |
202 | } |
203 | |
204 | |
205 | /******************************************************************************* |
206 | * |
207 | * FUNCTION: AcpiNsDetachObject |
208 | * |
209 | * PARAMETERS: Node - A Namespace node whose object will be detached |
210 | * |
211 | * RETURN: None. |
212 | * |
213 | * DESCRIPTION: Detach/delete an object associated with a namespace node. |
214 | * if the object is an allocated object, it is freed. |
215 | * Otherwise, the field is simply cleared. |
216 | * |
217 | ******************************************************************************/ |
218 | |
219 | void |
220 | AcpiNsDetachObject ( |
221 | ACPI_NAMESPACE_NODE *Node) |
222 | { |
223 | ACPI_OPERAND_OBJECT *ObjDesc; |
224 | |
225 | |
226 | ACPI_FUNCTION_TRACE (NsDetachObject); |
227 | |
228 | |
229 | ObjDesc = Node->Object; |
230 | |
231 | if (!ObjDesc || |
232 | (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA)) |
233 | { |
234 | return_VOID; |
235 | } |
236 | |
237 | if (Node->Flags & ANOBJ_ALLOCATED_BUFFER) |
238 | { |
239 | /* Free the dynamic aml buffer */ |
240 | |
241 | if (ObjDesc->Common.Type == ACPI_TYPE_METHOD) |
242 | { |
243 | ACPI_FREE (ObjDesc->Method.AmlStart); |
244 | } |
245 | } |
246 | |
247 | /* Clear the Node entry in all cases */ |
248 | |
249 | Node->Object = NULL; |
250 | if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) |
251 | { |
252 | /* Unlink object from front of possible object list */ |
253 | |
254 | Node->Object = ObjDesc->Common.NextObject; |
255 | |
256 | /* Handle possible 2-descriptor object */ |
257 | |
258 | if (Node->Object && |
259 | (Node->Object->Common.Type != ACPI_TYPE_LOCAL_DATA)) |
260 | { |
261 | Node->Object = Node->Object->Common.NextObject; |
262 | } |
263 | |
264 | /* |
265 | * Detach the object from any data objects (which are still held by |
266 | * the namespace node) |
267 | */ |
268 | if (ObjDesc->Common.NextObject && |
269 | ((ObjDesc->Common.NextObject)->Common.Type == ACPI_TYPE_LOCAL_DATA)) |
270 | { |
271 | ObjDesc->Common.NextObject = NULL; |
272 | } |
273 | } |
274 | |
275 | /* Reset the node type to untyped */ |
276 | |
277 | Node->Type = ACPI_TYPE_ANY; |
278 | |
279 | ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n" , |
280 | Node, AcpiUtGetNodeName (Node), ObjDesc)); |
281 | |
282 | /* Remove one reference on the object (and all subobjects) */ |
283 | |
284 | AcpiUtRemoveReference (ObjDesc); |
285 | return_VOID; |
286 | } |
287 | |
288 | |
289 | /******************************************************************************* |
290 | * |
291 | * FUNCTION: AcpiNsGetAttachedObject |
292 | * |
293 | * PARAMETERS: Node - Namespace node |
294 | * |
295 | * RETURN: Current value of the object field from the Node whose |
296 | * handle is passed |
297 | * |
298 | * DESCRIPTION: Obtain the object attached to a namespace node. |
299 | * |
300 | ******************************************************************************/ |
301 | |
302 | ACPI_OPERAND_OBJECT * |
303 | AcpiNsGetAttachedObject ( |
304 | ACPI_NAMESPACE_NODE *Node) |
305 | { |
306 | ACPI_FUNCTION_TRACE_PTR (NsGetAttachedObject, Node); |
307 | |
308 | |
309 | if (!Node) |
310 | { |
311 | ACPI_WARNING ((AE_INFO, "Null Node ptr" )); |
312 | return_PTR (NULL); |
313 | } |
314 | |
315 | if (!Node->Object || |
316 | ((ACPI_GET_DESCRIPTOR_TYPE (Node->Object) != ACPI_DESC_TYPE_OPERAND) && |
317 | (ACPI_GET_DESCRIPTOR_TYPE (Node->Object) != ACPI_DESC_TYPE_NAMED)) || |
318 | ((Node->Object)->Common.Type == ACPI_TYPE_LOCAL_DATA)) |
319 | { |
320 | return_PTR (NULL); |
321 | } |
322 | |
323 | return_PTR (Node->Object); |
324 | } |
325 | |
326 | |
327 | /******************************************************************************* |
328 | * |
329 | * FUNCTION: AcpiNsGetSecondaryObject |
330 | * |
331 | * PARAMETERS: Node - Namespace node |
332 | * |
333 | * RETURN: Current value of the object field from the Node whose |
334 | * handle is passed. |
335 | * |
336 | * DESCRIPTION: Obtain a secondary object associated with a namespace node. |
337 | * |
338 | ******************************************************************************/ |
339 | |
340 | ACPI_OPERAND_OBJECT * |
341 | AcpiNsGetSecondaryObject ( |
342 | ACPI_OPERAND_OBJECT *ObjDesc) |
343 | { |
344 | ACPI_FUNCTION_TRACE_PTR (NsGetSecondaryObject, ObjDesc); |
345 | |
346 | |
347 | if ((!ObjDesc) || |
348 | (ObjDesc->Common.Type== ACPI_TYPE_LOCAL_DATA) || |
349 | (!ObjDesc->Common.NextObject) || |
350 | ((ObjDesc->Common.NextObject)->Common.Type == ACPI_TYPE_LOCAL_DATA)) |
351 | { |
352 | return_PTR (NULL); |
353 | } |
354 | |
355 | return_PTR (ObjDesc->Common.NextObject); |
356 | } |
357 | |
358 | |
359 | /******************************************************************************* |
360 | * |
361 | * FUNCTION: AcpiNsAttachData |
362 | * |
363 | * PARAMETERS: Node - Namespace node |
364 | * Handler - Handler to be associated with the data |
365 | * Data - Data to be attached |
366 | * |
367 | * RETURN: Status |
368 | * |
369 | * DESCRIPTION: Low-level attach data. Create and attach a Data object. |
370 | * |
371 | ******************************************************************************/ |
372 | |
373 | ACPI_STATUS |
374 | AcpiNsAttachData ( |
375 | ACPI_NAMESPACE_NODE *Node, |
376 | ACPI_OBJECT_HANDLER Handler, |
377 | void *Data) |
378 | { |
379 | ACPI_OPERAND_OBJECT *PrevObjDesc; |
380 | ACPI_OPERAND_OBJECT *ObjDesc; |
381 | ACPI_OPERAND_OBJECT *DataDesc; |
382 | |
383 | |
384 | /* We only allow one attachment per handler */ |
385 | |
386 | PrevObjDesc = NULL; |
387 | ObjDesc = Node->Object; |
388 | while (ObjDesc) |
389 | { |
390 | if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) && |
391 | (ObjDesc->Data.Handler == Handler)) |
392 | { |
393 | return (AE_ALREADY_EXISTS); |
394 | } |
395 | |
396 | PrevObjDesc = ObjDesc; |
397 | ObjDesc = ObjDesc->Common.NextObject; |
398 | } |
399 | |
400 | /* Create an internal object for the data */ |
401 | |
402 | DataDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_DATA); |
403 | if (!DataDesc) |
404 | { |
405 | return (AE_NO_MEMORY); |
406 | } |
407 | |
408 | DataDesc->Data.Handler = Handler; |
409 | DataDesc->Data.Pointer = Data; |
410 | |
411 | /* Install the data object */ |
412 | |
413 | if (PrevObjDesc) |
414 | { |
415 | PrevObjDesc->Common.NextObject = DataDesc; |
416 | } |
417 | else |
418 | { |
419 | Node->Object = DataDesc; |
420 | } |
421 | |
422 | return (AE_OK); |
423 | } |
424 | |
425 | |
426 | /******************************************************************************* |
427 | * |
428 | * FUNCTION: AcpiNsDetachData |
429 | * |
430 | * PARAMETERS: Node - Namespace node |
431 | * Handler - Handler associated with the data |
432 | * |
433 | * RETURN: Status |
434 | * |
435 | * DESCRIPTION: Low-level detach data. Delete the data node, but the caller |
436 | * is responsible for the actual data. |
437 | * |
438 | ******************************************************************************/ |
439 | |
440 | ACPI_STATUS |
441 | AcpiNsDetachData ( |
442 | ACPI_NAMESPACE_NODE *Node, |
443 | ACPI_OBJECT_HANDLER Handler) |
444 | { |
445 | ACPI_OPERAND_OBJECT *ObjDesc; |
446 | ACPI_OPERAND_OBJECT *PrevObjDesc; |
447 | |
448 | |
449 | PrevObjDesc = NULL; |
450 | ObjDesc = Node->Object; |
451 | while (ObjDesc) |
452 | { |
453 | if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) && |
454 | (ObjDesc->Data.Handler == Handler)) |
455 | { |
456 | if (PrevObjDesc) |
457 | { |
458 | PrevObjDesc->Common.NextObject = ObjDesc->Common.NextObject; |
459 | } |
460 | else |
461 | { |
462 | Node->Object = ObjDesc->Common.NextObject; |
463 | } |
464 | |
465 | AcpiUtRemoveReference (ObjDesc); |
466 | return (AE_OK); |
467 | } |
468 | |
469 | PrevObjDesc = ObjDesc; |
470 | ObjDesc = ObjDesc->Common.NextObject; |
471 | } |
472 | |
473 | return (AE_NOT_FOUND); |
474 | } |
475 | |
476 | |
477 | /******************************************************************************* |
478 | * |
479 | * FUNCTION: AcpiNsGetAttachedData |
480 | * |
481 | * PARAMETERS: Node - Namespace node |
482 | * Handler - Handler associated with the data |
483 | * Data - Where the data is returned |
484 | * |
485 | * RETURN: Status |
486 | * |
487 | * DESCRIPTION: Low level interface to obtain data previously associated with |
488 | * a namespace node. |
489 | * |
490 | ******************************************************************************/ |
491 | |
492 | ACPI_STATUS |
493 | AcpiNsGetAttachedData ( |
494 | ACPI_NAMESPACE_NODE *Node, |
495 | ACPI_OBJECT_HANDLER Handler, |
496 | void **Data) |
497 | { |
498 | ACPI_OPERAND_OBJECT *ObjDesc; |
499 | |
500 | |
501 | ObjDesc = Node->Object; |
502 | while (ObjDesc) |
503 | { |
504 | if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) && |
505 | (ObjDesc->Data.Handler == Handler)) |
506 | { |
507 | *Data = ObjDesc->Data.Pointer; |
508 | return (AE_OK); |
509 | } |
510 | |
511 | ObjDesc = ObjDesc->Common.NextObject; |
512 | } |
513 | |
514 | return (AE_NOT_FOUND); |
515 | } |
516 | |