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