1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: excreate - Named object creation 5 * 6 * Copyright (C) 2000 - 2021, Intel Corp. 7 * 8 *****************************************************************************/ 9 10 #include <acpi/acpi.h> 11 #include "accommon.h" 12 #include "acinterp.h" 13 #include "amlcode.h" 14 #include "acnamesp.h" 15 16 #define _COMPONENT ACPI_EXECUTER 17 ACPI_MODULE_NAME("excreate") 18 /******************************************************************************* 19 * 20 * FUNCTION: acpi_ex_create_alias 21 * 22 * PARAMETERS: walk_state - Current state, contains operands 23 * 24 * RETURN: Status 25 * 26 * DESCRIPTION: Create a new named alias 27 * 28 ******************************************************************************/ 29 acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) 30 { 31 struct acpi_namespace_node *target_node; 32 struct acpi_namespace_node *alias_node; 33 acpi_status status = AE_OK; 34 35 ACPI_FUNCTION_TRACE(ex_create_alias); 36 37 /* Get the source/alias operands (both namespace nodes) */ 38 39 alias_node = (struct acpi_namespace_node *)walk_state->operands[0]; 40 target_node = (struct acpi_namespace_node *)walk_state->operands[1]; 41 42 if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) || 43 (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { 44 /* 45 * Dereference an existing alias so that we don't create a chain 46 * of aliases. With this code, we guarantee that an alias is 47 * always exactly one level of indirection away from the 48 * actual aliased name. 49 */ 50 target_node = 51 ACPI_CAST_PTR(struct acpi_namespace_node, 52 target_node->object); 53 } 54 55 /* Ensure that the target node is valid */ 56 57 if (!target_node) { 58 return_ACPI_STATUS(AE_NULL_OBJECT); 59 } 60 61 /* Construct the alias object (a namespace node) */ 62 63 switch (target_node->type) { 64 case ACPI_TYPE_METHOD: 65 /* 66 * Control method aliases need to be differentiated with 67 * a special type 68 */ 69 alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; 70 break; 71 72 default: 73 /* 74 * All other object types. 75 * 76 * The new alias has the type ALIAS and points to the original 77 * NS node, not the object itself. 78 */ 79 alias_node->type = ACPI_TYPE_LOCAL_ALIAS; 80 alias_node->object = 81 ACPI_CAST_PTR(union acpi_operand_object, target_node); 82 break; 83 } 84 85 /* Since both operands are Nodes, we don't need to delete them */ 86 87 alias_node->object = 88 ACPI_CAST_PTR(union acpi_operand_object, target_node); 89 return_ACPI_STATUS(status); 90 } 91 92 /******************************************************************************* 93 * 94 * FUNCTION: acpi_ex_create_event 95 * 96 * PARAMETERS: walk_state - Current state 97 * 98 * RETURN: Status 99 * 100 * DESCRIPTION: Create a new event object 101 * 102 ******************************************************************************/ 103 104 acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state) 105 { 106 acpi_status status; 107 union acpi_operand_object *obj_desc; 108 109 ACPI_FUNCTION_TRACE(ex_create_event); 110 111 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT); 112 if (!obj_desc) { 113 status = AE_NO_MEMORY; 114 goto cleanup; 115 } 116 117 /* 118 * Create the actual OS semaphore, with zero initial units -- meaning 119 * that the event is created in an unsignalled state 120 */ 121 status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, 122 &obj_desc->event.os_semaphore); 123 if (ACPI_FAILURE(status)) { 124 goto cleanup; 125 } 126 127 /* Attach object to the Node */ 128 129 status = acpi_ns_attach_object((struct acpi_namespace_node *) 130 walk_state->operands[0], obj_desc, 131 ACPI_TYPE_EVENT); 132 133 cleanup: 134 /* 135 * Remove local reference to the object (on error, will cause deletion 136 * of both object and semaphore if present.) 137 */ 138 acpi_ut_remove_reference(obj_desc); 139 return_ACPI_STATUS(status); 140 } 141 142 /******************************************************************************* 143 * 144 * FUNCTION: acpi_ex_create_mutex 145 * 146 * PARAMETERS: walk_state - Current state 147 * 148 * RETURN: Status 149 * 150 * DESCRIPTION: Create a new mutex object 151 * 152 * Mutex (Name[0], sync_level[1]) 153 * 154 ******************************************************************************/ 155 156 acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) 157 { 158 acpi_status status = AE_OK; 159 union acpi_operand_object *obj_desc; 160 161 ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS); 162 163 /* Create the new mutex object */ 164 165 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX); 166 if (!obj_desc) { 167 status = AE_NO_MEMORY; 168 goto cleanup; 169 } 170 171 /* Create the actual OS Mutex */ 172 173 status = acpi_os_create_mutex(&obj_desc->mutex.os_mutex); 174 if (ACPI_FAILURE(status)) { 175 goto cleanup; 176 } 177 178 /* Init object and attach to NS node */ 179 180 obj_desc->mutex.sync_level = (u8)walk_state->operands[1]->integer.value; 181 obj_desc->mutex.node = 182 (struct acpi_namespace_node *)walk_state->operands[0]; 183 184 status = 185 acpi_ns_attach_object(obj_desc->mutex.node, obj_desc, 186 ACPI_TYPE_MUTEX); 187 188 cleanup: 189 /* 190 * Remove local reference to the object (on error, will cause deletion 191 * of both object and semaphore if present.) 192 */ 193 acpi_ut_remove_reference(obj_desc); 194 return_ACPI_STATUS(status); 195 } 196 197 /******************************************************************************* 198 * 199 * FUNCTION: acpi_ex_create_region 200 * 201 * PARAMETERS: aml_start - Pointer to the region declaration AML 202 * aml_length - Max length of the declaration AML 203 * space_id - Address space ID for the region 204 * walk_state - Current state 205 * 206 * RETURN: Status 207 * 208 * DESCRIPTION: Create a new operation region object 209 * 210 ******************************************************************************/ 211 212 acpi_status 213 acpi_ex_create_region(u8 * aml_start, 214 u32 aml_length, 215 u8 space_id, struct acpi_walk_state *walk_state) 216 { 217 acpi_status status; 218 union acpi_operand_object *obj_desc; 219 struct acpi_namespace_node *node; 220 union acpi_operand_object *region_obj2; 221 222 ACPI_FUNCTION_TRACE(ex_create_region); 223 224 /* Get the Namespace Node */ 225 226 node = walk_state->op->common.node; 227 228 /* 229 * If the region object is already attached to this node, 230 * just return 231 */ 232 if (acpi_ns_get_attached_object(node)) { 233 return_ACPI_STATUS(AE_OK); 234 } 235 236 /* 237 * Space ID must be one of the predefined IDs, or in the user-defined 238 * range 239 */ 240 if (!acpi_is_valid_space_id(space_id)) { 241 /* 242 * Print an error message, but continue. We don't want to abort 243 * a table load for this exception. Instead, if the region is 244 * actually used at runtime, abort the executing method. 245 */ 246 ACPI_ERROR((AE_INFO, 247 "Invalid/unknown Address Space ID: 0x%2.2X", 248 space_id)); 249 } 250 251 ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n", 252 acpi_ut_get_region_name(space_id), space_id)); 253 254 /* Create the region descriptor */ 255 256 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); 257 if (!obj_desc) { 258 status = AE_NO_MEMORY; 259 goto cleanup; 260 } 261 262 /* 263 * Remember location in AML stream of address & length 264 * operands since they need to be evaluated at run time. 265 */ 266 region_obj2 = acpi_ns_get_secondary_object(obj_desc); 267 region_obj2->extra.aml_start = aml_start; 268 region_obj2->extra.aml_length = aml_length; 269 region_obj2->extra.method_REG = NULL; 270 if (walk_state->scope_info) { 271 region_obj2->extra.scope_node = 272 walk_state->scope_info->scope.node; 273 } else { 274 region_obj2->extra.scope_node = node; 275 } 276 277 /* Init the region from the operands */ 278 279 obj_desc->region.space_id = space_id; 280 obj_desc->region.address = 0; 281 obj_desc->region.length = 0; 282 obj_desc->region.node = node; 283 obj_desc->region.handler = NULL; 284 obj_desc->common.flags &= 285 ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_REG_CONNECTED | 286 AOPOBJ_OBJECT_INITIALIZED); 287 288 /* Install the new region object in the parent Node */ 289 290 status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION); 291 292 cleanup: 293 294 /* Remove local reference to the object */ 295 296 acpi_ut_remove_reference(obj_desc); 297 return_ACPI_STATUS(status); 298 } 299 300 /******************************************************************************* 301 * 302 * FUNCTION: acpi_ex_create_processor 303 * 304 * PARAMETERS: walk_state - Current state 305 * 306 * RETURN: Status 307 * 308 * DESCRIPTION: Create a new processor object and populate the fields 309 * 310 * Processor (Name[0], cpu_ID[1], pblock_addr[2], pblock_length[3]) 311 * 312 ******************************************************************************/ 313 314 acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state) 315 { 316 union acpi_operand_object **operand = &walk_state->operands[0]; 317 union acpi_operand_object *obj_desc; 318 acpi_status status; 319 320 ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state); 321 322 /* Create the processor object */ 323 324 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR); 325 if (!obj_desc) { 326 return_ACPI_STATUS(AE_NO_MEMORY); 327 } 328 329 /* Initialize the processor object from the operands */ 330 331 obj_desc->processor.proc_id = (u8) operand[1]->integer.value; 332 obj_desc->processor.length = (u8) operand[3]->integer.value; 333 obj_desc->processor.address = 334 (acpi_io_address)operand[2]->integer.value; 335 336 /* Install the processor object in the parent Node */ 337 338 status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], 339 obj_desc, ACPI_TYPE_PROCESSOR); 340 341 /* Remove local reference to the object */ 342 343 acpi_ut_remove_reference(obj_desc); 344 return_ACPI_STATUS(status); 345 } 346 347 /******************************************************************************* 348 * 349 * FUNCTION: acpi_ex_create_power_resource 350 * 351 * PARAMETERS: walk_state - Current state 352 * 353 * RETURN: Status 354 * 355 * DESCRIPTION: Create a new power_resource object and populate the fields 356 * 357 * power_resource (Name[0], system_level[1], resource_order[2]) 358 * 359 ******************************************************************************/ 360 361 acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state) 362 { 363 union acpi_operand_object **operand = &walk_state->operands[0]; 364 acpi_status status; 365 union acpi_operand_object *obj_desc; 366 367 ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state); 368 369 /* Create the power resource object */ 370 371 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER); 372 if (!obj_desc) { 373 return_ACPI_STATUS(AE_NO_MEMORY); 374 } 375 376 /* Initialize the power object from the operands */ 377 378 obj_desc->power_resource.system_level = (u8) operand[1]->integer.value; 379 obj_desc->power_resource.resource_order = 380 (u16) operand[2]->integer.value; 381 382 /* Install the power resource object in the parent Node */ 383 384 status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], 385 obj_desc, ACPI_TYPE_POWER); 386 387 /* Remove local reference to the object */ 388 389 acpi_ut_remove_reference(obj_desc); 390 return_ACPI_STATUS(status); 391 } 392 393 /******************************************************************************* 394 * 395 * FUNCTION: acpi_ex_create_method 396 * 397 * PARAMETERS: aml_start - First byte of the method's AML 398 * aml_length - AML byte count for this method 399 * walk_state - Current state 400 * 401 * RETURN: Status 402 * 403 * DESCRIPTION: Create a new method object 404 * 405 ******************************************************************************/ 406 407 acpi_status 408 acpi_ex_create_method(u8 * aml_start, 409 u32 aml_length, struct acpi_walk_state *walk_state) 410 { 411 union acpi_operand_object **operand = &walk_state->operands[0]; 412 union acpi_operand_object *obj_desc; 413 acpi_status status; 414 u8 method_flags; 415 416 ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state); 417 418 /* Create a new method object */ 419 420 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); 421 if (!obj_desc) { 422 status = AE_NO_MEMORY; 423 goto exit; 424 } 425 426 /* Save the method's AML pointer and length */ 427 428 obj_desc->method.aml_start = aml_start; 429 obj_desc->method.aml_length = aml_length; 430 obj_desc->method.node = operand[0]; 431 432 /* 433 * Disassemble the method flags. Split off the arg_count, Serialized 434 * flag, and sync_level for efficiency. 435 */ 436 method_flags = (u8)operand[1]->integer.value; 437 obj_desc->method.param_count = (u8) 438 (method_flags & AML_METHOD_ARG_COUNT); 439 440 /* 441 * Get the sync_level. If method is serialized, a mutex will be 442 * created for this method when it is parsed. 443 */ 444 if (method_flags & AML_METHOD_SERIALIZED) { 445 obj_desc->method.info_flags = ACPI_METHOD_SERIALIZED; 446 447 /* 448 * ACPI 1.0: sync_level = 0 449 * ACPI 2.0: sync_level = sync_level in method declaration 450 */ 451 obj_desc->method.sync_level = (u8) 452 ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4); 453 } 454 455 /* Attach the new object to the method Node */ 456 457 status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], 458 obj_desc, ACPI_TYPE_METHOD); 459 460 /* Remove local reference to the object */ 461 462 acpi_ut_remove_reference(obj_desc); 463 464 exit: 465 /* Remove a reference to the operand */ 466 467 acpi_ut_remove_reference(operand[1]); 468 return_ACPI_STATUS(status); 469 } 470