1 | /****************************************************************************** |
2 | * |
3 | * Module Name: excreate - Named object creation |
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 "acinterp.h" |
47 | #include "amlcode.h" |
48 | #include "acnamesp.h" |
49 | |
50 | |
51 | #define _COMPONENT ACPI_EXECUTER |
52 | ACPI_MODULE_NAME ("excreate" ) |
53 | |
54 | |
55 | #ifndef ACPI_NO_METHOD_EXECUTION |
56 | /******************************************************************************* |
57 | * |
58 | * FUNCTION: AcpiExCreateAlias |
59 | * |
60 | * PARAMETERS: WalkState - Current state, contains operands |
61 | * |
62 | * RETURN: Status |
63 | * |
64 | * DESCRIPTION: Create a new named alias |
65 | * |
66 | ******************************************************************************/ |
67 | |
68 | ACPI_STATUS |
69 | AcpiExCreateAlias ( |
70 | ACPI_WALK_STATE *WalkState) |
71 | { |
72 | ACPI_NAMESPACE_NODE *TargetNode; |
73 | ACPI_NAMESPACE_NODE *AliasNode; |
74 | ACPI_STATUS Status = AE_OK; |
75 | |
76 | |
77 | ACPI_FUNCTION_TRACE (ExCreateAlias); |
78 | |
79 | |
80 | /* Get the source/alias operands (both namespace nodes) */ |
81 | |
82 | AliasNode = (ACPI_NAMESPACE_NODE *) WalkState->Operands[0]; |
83 | TargetNode = (ACPI_NAMESPACE_NODE *) WalkState->Operands[1]; |
84 | |
85 | if ((TargetNode->Type == ACPI_TYPE_LOCAL_ALIAS) || |
86 | (TargetNode->Type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) |
87 | { |
88 | /* |
89 | * Dereference an existing alias so that we don't create a chain |
90 | * of aliases. With this code, we guarantee that an alias is |
91 | * always exactly one level of indirection away from the |
92 | * actual aliased name. |
93 | */ |
94 | TargetNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, TargetNode->Object); |
95 | } |
96 | |
97 | /* |
98 | * For objects that can never change (i.e., the NS node will |
99 | * permanently point to the same object), we can simply attach |
100 | * the object to the new NS node. For other objects (such as |
101 | * Integers, buffers, etc.), we have to point the Alias node |
102 | * to the original Node. |
103 | */ |
104 | switch (TargetNode->Type) |
105 | { |
106 | |
107 | /* For these types, the sub-object can change dynamically via a Store */ |
108 | |
109 | case ACPI_TYPE_INTEGER: |
110 | case ACPI_TYPE_STRING: |
111 | case ACPI_TYPE_BUFFER: |
112 | case ACPI_TYPE_PACKAGE: |
113 | case ACPI_TYPE_BUFFER_FIELD: |
114 | /* |
115 | * These types open a new scope, so we need the NS node in order to access |
116 | * any children. |
117 | */ |
118 | case ACPI_TYPE_DEVICE: |
119 | case ACPI_TYPE_POWER: |
120 | case ACPI_TYPE_PROCESSOR: |
121 | case ACPI_TYPE_THERMAL: |
122 | case ACPI_TYPE_LOCAL_SCOPE: |
123 | /* |
124 | * The new alias has the type ALIAS and points to the original |
125 | * NS node, not the object itself. |
126 | */ |
127 | AliasNode->Type = ACPI_TYPE_LOCAL_ALIAS; |
128 | AliasNode->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode); |
129 | break; |
130 | |
131 | case ACPI_TYPE_METHOD: |
132 | /* |
133 | * Control method aliases need to be differentiated |
134 | */ |
135 | AliasNode->Type = ACPI_TYPE_LOCAL_METHOD_ALIAS; |
136 | AliasNode->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode); |
137 | break; |
138 | |
139 | default: |
140 | |
141 | /* Attach the original source object to the new Alias Node */ |
142 | |
143 | /* |
144 | * The new alias assumes the type of the target, and it points |
145 | * to the same object. The reference count of the object has an |
146 | * additional reference to prevent deletion out from under either the |
147 | * target node or the alias Node |
148 | */ |
149 | Status = AcpiNsAttachObject (AliasNode, |
150 | AcpiNsGetAttachedObject (TargetNode), TargetNode->Type); |
151 | break; |
152 | } |
153 | |
154 | /* Since both operands are Nodes, we don't need to delete them */ |
155 | |
156 | return_ACPI_STATUS (Status); |
157 | } |
158 | |
159 | |
160 | /******************************************************************************* |
161 | * |
162 | * FUNCTION: AcpiExCreateEvent |
163 | * |
164 | * PARAMETERS: WalkState - Current state |
165 | * |
166 | * RETURN: Status |
167 | * |
168 | * DESCRIPTION: Create a new event object |
169 | * |
170 | ******************************************************************************/ |
171 | |
172 | ACPI_STATUS |
173 | AcpiExCreateEvent ( |
174 | ACPI_WALK_STATE *WalkState) |
175 | { |
176 | ACPI_STATUS Status; |
177 | ACPI_OPERAND_OBJECT *ObjDesc; |
178 | |
179 | |
180 | ACPI_FUNCTION_TRACE (ExCreateEvent); |
181 | |
182 | |
183 | ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_EVENT); |
184 | if (!ObjDesc) |
185 | { |
186 | Status = AE_NO_MEMORY; |
187 | goto Cleanup; |
188 | } |
189 | |
190 | /* |
191 | * Create the actual OS semaphore, with zero initial units -- meaning |
192 | * that the event is created in an unsignalled state |
193 | */ |
194 | Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0, |
195 | &ObjDesc->Event.OsSemaphore); |
196 | if (ACPI_FAILURE (Status)) |
197 | { |
198 | goto Cleanup; |
199 | } |
200 | |
201 | /* Attach object to the Node */ |
202 | |
203 | Status = AcpiNsAttachObject ( |
204 | (ACPI_NAMESPACE_NODE *) WalkState->Operands[0], |
205 | ObjDesc, ACPI_TYPE_EVENT); |
206 | |
207 | Cleanup: |
208 | /* |
209 | * Remove local reference to the object (on error, will cause deletion |
210 | * of both object and semaphore if present.) |
211 | */ |
212 | AcpiUtRemoveReference (ObjDesc); |
213 | return_ACPI_STATUS (Status); |
214 | } |
215 | |
216 | |
217 | /******************************************************************************* |
218 | * |
219 | * FUNCTION: AcpiExCreateMutex |
220 | * |
221 | * PARAMETERS: WalkState - Current state |
222 | * |
223 | * RETURN: Status |
224 | * |
225 | * DESCRIPTION: Create a new mutex object |
226 | * |
227 | * Mutex (Name[0], SyncLevel[1]) |
228 | * |
229 | ******************************************************************************/ |
230 | |
231 | ACPI_STATUS |
232 | AcpiExCreateMutex ( |
233 | ACPI_WALK_STATE *WalkState) |
234 | { |
235 | ACPI_STATUS Status = AE_OK; |
236 | ACPI_OPERAND_OBJECT *ObjDesc; |
237 | |
238 | |
239 | ACPI_FUNCTION_TRACE_PTR (ExCreateMutex, ACPI_WALK_OPERANDS); |
240 | |
241 | |
242 | /* Create the new mutex object */ |
243 | |
244 | ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX); |
245 | if (!ObjDesc) |
246 | { |
247 | Status = AE_NO_MEMORY; |
248 | goto Cleanup; |
249 | } |
250 | |
251 | /* Create the actual OS Mutex */ |
252 | |
253 | Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex); |
254 | if (ACPI_FAILURE (Status)) |
255 | { |
256 | goto Cleanup; |
257 | } |
258 | |
259 | /* Init object and attach to NS node */ |
260 | |
261 | ObjDesc->Mutex.SyncLevel = (UINT8) WalkState->Operands[1]->Integer.Value; |
262 | ObjDesc->Mutex.Node = (ACPI_NAMESPACE_NODE *) WalkState->Operands[0]; |
263 | |
264 | Status = AcpiNsAttachObject ( |
265 | ObjDesc->Mutex.Node, ObjDesc, ACPI_TYPE_MUTEX); |
266 | |
267 | |
268 | Cleanup: |
269 | /* |
270 | * Remove local reference to the object (on error, will cause deletion |
271 | * of both object and semaphore if present.) |
272 | */ |
273 | AcpiUtRemoveReference (ObjDesc); |
274 | return_ACPI_STATUS (Status); |
275 | } |
276 | |
277 | |
278 | /******************************************************************************* |
279 | * |
280 | * FUNCTION: AcpiExCreateRegion |
281 | * |
282 | * PARAMETERS: AmlStart - Pointer to the region declaration AML |
283 | * AmlLength - Max length of the declaration AML |
284 | * SpaceId - Address space ID for the region |
285 | * WalkState - Current state |
286 | * |
287 | * RETURN: Status |
288 | * |
289 | * DESCRIPTION: Create a new operation region object |
290 | * |
291 | ******************************************************************************/ |
292 | |
293 | ACPI_STATUS |
294 | AcpiExCreateRegion ( |
295 | UINT8 *AmlStart, |
296 | UINT32 AmlLength, |
297 | UINT8 SpaceId, |
298 | ACPI_WALK_STATE *WalkState) |
299 | { |
300 | ACPI_STATUS Status; |
301 | ACPI_OPERAND_OBJECT *ObjDesc; |
302 | ACPI_NAMESPACE_NODE *Node; |
303 | ACPI_OPERAND_OBJECT *RegionObj2; |
304 | |
305 | |
306 | ACPI_FUNCTION_TRACE (ExCreateRegion); |
307 | |
308 | |
309 | /* Get the Namespace Node */ |
310 | |
311 | Node = WalkState->Op->Common.Node; |
312 | |
313 | /* |
314 | * If the region object is already attached to this node, |
315 | * just return |
316 | */ |
317 | if (AcpiNsGetAttachedObject (Node)) |
318 | { |
319 | return_ACPI_STATUS (AE_OK); |
320 | } |
321 | |
322 | /* |
323 | * Space ID must be one of the predefined IDs, or in the user-defined |
324 | * range |
325 | */ |
326 | if (!AcpiIsValidSpaceId (SpaceId)) |
327 | { |
328 | /* |
329 | * Print an error message, but continue. We don't want to abort |
330 | * a table load for this exception. Instead, if the region is |
331 | * actually used at runtime, abort the executing method. |
332 | */ |
333 | ACPI_ERROR ((AE_INFO, |
334 | "Invalid/unknown Address Space ID: 0x%2.2X" , SpaceId)); |
335 | } |
336 | |
337 | ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n" , |
338 | AcpiUtGetRegionName (SpaceId), SpaceId)); |
339 | |
340 | /* Create the region descriptor */ |
341 | |
342 | ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION); |
343 | if (!ObjDesc) |
344 | { |
345 | Status = AE_NO_MEMORY; |
346 | goto Cleanup; |
347 | } |
348 | |
349 | /* |
350 | * Remember location in AML stream of address & length |
351 | * operands since they need to be evaluated at run time. |
352 | */ |
353 | RegionObj2 = AcpiNsGetSecondaryObject (ObjDesc); |
354 | RegionObj2->Extra.AmlStart = AmlStart; |
355 | RegionObj2->Extra.AmlLength = AmlLength; |
356 | RegionObj2->Extra.Method_REG = NULL; |
357 | if (WalkState->ScopeInfo) |
358 | { |
359 | RegionObj2->Extra.ScopeNode = WalkState->ScopeInfo->Scope.Node; |
360 | } |
361 | else |
362 | { |
363 | RegionObj2->Extra.ScopeNode = Node; |
364 | } |
365 | |
366 | /* Init the region from the operands */ |
367 | |
368 | ObjDesc->Region.SpaceId = SpaceId; |
369 | ObjDesc->Region.Address = 0; |
370 | ObjDesc->Region.Length = 0; |
371 | ObjDesc->Region.Node = Node; |
372 | ObjDesc->Region.Handler = NULL; |
373 | ObjDesc->Common.Flags &= |
374 | ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_REG_CONNECTED | |
375 | AOPOBJ_OBJECT_INITIALIZED); |
376 | |
377 | /* Install the new region object in the parent Node */ |
378 | |
379 | Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_REGION); |
380 | |
381 | |
382 | Cleanup: |
383 | |
384 | /* Remove local reference to the object */ |
385 | |
386 | AcpiUtRemoveReference (ObjDesc); |
387 | return_ACPI_STATUS (Status); |
388 | } |
389 | |
390 | |
391 | /******************************************************************************* |
392 | * |
393 | * FUNCTION: AcpiExCreateProcessor |
394 | * |
395 | * PARAMETERS: WalkState - Current state |
396 | * |
397 | * RETURN: Status |
398 | * |
399 | * DESCRIPTION: Create a new processor object and populate the fields |
400 | * |
401 | * Processor (Name[0], CpuID[1], PblockAddr[2], PblockLength[3]) |
402 | * |
403 | ******************************************************************************/ |
404 | |
405 | ACPI_STATUS |
406 | AcpiExCreateProcessor ( |
407 | ACPI_WALK_STATE *WalkState) |
408 | { |
409 | ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; |
410 | ACPI_OPERAND_OBJECT *ObjDesc; |
411 | ACPI_STATUS Status; |
412 | |
413 | |
414 | ACPI_FUNCTION_TRACE_PTR (ExCreateProcessor, WalkState); |
415 | |
416 | |
417 | /* Create the processor object */ |
418 | |
419 | ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PROCESSOR); |
420 | if (!ObjDesc) |
421 | { |
422 | return_ACPI_STATUS (AE_NO_MEMORY); |
423 | } |
424 | |
425 | /* Initialize the processor object from the operands */ |
426 | |
427 | ObjDesc->Processor.ProcId = (UINT8) Operand[1]->Integer.Value; |
428 | ObjDesc->Processor.Length = (UINT8) Operand[3]->Integer.Value; |
429 | ObjDesc->Processor.Address = (ACPI_IO_ADDRESS) Operand[2]->Integer.Value; |
430 | |
431 | /* Install the processor object in the parent Node */ |
432 | |
433 | Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0], |
434 | ObjDesc, ACPI_TYPE_PROCESSOR); |
435 | |
436 | /* Remove local reference to the object */ |
437 | |
438 | AcpiUtRemoveReference (ObjDesc); |
439 | return_ACPI_STATUS (Status); |
440 | } |
441 | |
442 | |
443 | /******************************************************************************* |
444 | * |
445 | * FUNCTION: AcpiExCreatePowerResource |
446 | * |
447 | * PARAMETERS: WalkState - Current state |
448 | * |
449 | * RETURN: Status |
450 | * |
451 | * DESCRIPTION: Create a new PowerResource object and populate the fields |
452 | * |
453 | * PowerResource (Name[0], SystemLevel[1], ResourceOrder[2]) |
454 | * |
455 | ******************************************************************************/ |
456 | |
457 | ACPI_STATUS |
458 | AcpiExCreatePowerResource ( |
459 | ACPI_WALK_STATE *WalkState) |
460 | { |
461 | ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; |
462 | ACPI_STATUS Status; |
463 | ACPI_OPERAND_OBJECT *ObjDesc; |
464 | |
465 | |
466 | ACPI_FUNCTION_TRACE_PTR (ExCreatePowerResource, WalkState); |
467 | |
468 | |
469 | /* Create the power resource object */ |
470 | |
471 | ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_POWER); |
472 | if (!ObjDesc) |
473 | { |
474 | return_ACPI_STATUS (AE_NO_MEMORY); |
475 | } |
476 | |
477 | /* Initialize the power object from the operands */ |
478 | |
479 | ObjDesc->PowerResource.SystemLevel = (UINT8) Operand[1]->Integer.Value; |
480 | ObjDesc->PowerResource.ResourceOrder = (UINT16) Operand[2]->Integer.Value; |
481 | |
482 | /* Install the power resource object in the parent Node */ |
483 | |
484 | Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0], |
485 | ObjDesc, ACPI_TYPE_POWER); |
486 | |
487 | /* Remove local reference to the object */ |
488 | |
489 | AcpiUtRemoveReference (ObjDesc); |
490 | return_ACPI_STATUS (Status); |
491 | } |
492 | #endif |
493 | |
494 | |
495 | /******************************************************************************* |
496 | * |
497 | * FUNCTION: AcpiExCreateMethod |
498 | * |
499 | * PARAMETERS: AmlStart - First byte of the method's AML |
500 | * AmlLength - AML byte count for this method |
501 | * WalkState - Current state |
502 | * |
503 | * RETURN: Status |
504 | * |
505 | * DESCRIPTION: Create a new method object |
506 | * |
507 | ******************************************************************************/ |
508 | |
509 | ACPI_STATUS |
510 | AcpiExCreateMethod ( |
511 | UINT8 *AmlStart, |
512 | UINT32 AmlLength, |
513 | ACPI_WALK_STATE *WalkState) |
514 | { |
515 | ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; |
516 | ACPI_OPERAND_OBJECT *ObjDesc; |
517 | ACPI_STATUS Status; |
518 | UINT8 MethodFlags; |
519 | |
520 | |
521 | ACPI_FUNCTION_TRACE_PTR (ExCreateMethod, WalkState); |
522 | |
523 | |
524 | /* Create a new method object */ |
525 | |
526 | ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); |
527 | if (!ObjDesc) |
528 | { |
529 | Status = AE_NO_MEMORY; |
530 | goto Exit; |
531 | } |
532 | |
533 | /* Save the method's AML pointer and length */ |
534 | |
535 | ObjDesc->Method.AmlStart = AmlStart; |
536 | ObjDesc->Method.AmlLength = AmlLength; |
537 | ObjDesc->Method.Node = Operand[0]; |
538 | |
539 | /* |
540 | * Disassemble the method flags. Split off the ArgCount, Serialized |
541 | * flag, and SyncLevel for efficiency. |
542 | */ |
543 | MethodFlags = (UINT8) Operand[1]->Integer.Value; |
544 | ObjDesc->Method.ParamCount = (UINT8) |
545 | (MethodFlags & AML_METHOD_ARG_COUNT); |
546 | |
547 | /* |
548 | * Get the SyncLevel. If method is serialized, a mutex will be |
549 | * created for this method when it is parsed. |
550 | */ |
551 | if (MethodFlags & AML_METHOD_SERIALIZED) |
552 | { |
553 | ObjDesc->Method.InfoFlags = ACPI_METHOD_SERIALIZED; |
554 | |
555 | /* |
556 | * ACPI 1.0: SyncLevel = 0 |
557 | * ACPI 2.0: SyncLevel = SyncLevel in method declaration |
558 | */ |
559 | ObjDesc->Method.SyncLevel = (UINT8) |
560 | ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4); |
561 | } |
562 | |
563 | /* Attach the new object to the method Node */ |
564 | |
565 | Status = AcpiNsAttachObject ((ACPI_NAMESPACE_NODE *) Operand[0], |
566 | ObjDesc, ACPI_TYPE_METHOD); |
567 | |
568 | /* Remove local reference to the object */ |
569 | |
570 | AcpiUtRemoveReference (ObjDesc); |
571 | |
572 | Exit: |
573 | /* Remove a reference to the operand */ |
574 | |
575 | AcpiUtRemoveReference (Operand[1]); |
576 | return_ACPI_STATUS (Status); |
577 | } |
578 | |