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 - 2023, 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.pointer = NULL; 283 obj_desc->region.node = node; 284 obj_desc->region.handler = NULL; 285 obj_desc->common.flags &= 286 ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_REG_CONNECTED | 287 AOPOBJ_OBJECT_INITIALIZED); 288 289 /* Install the new region object in the parent Node */ 290 291 status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION); 292 293 cleanup: 294 295 /* Remove local reference to the object */ 296 297 acpi_ut_remove_reference(obj_desc); 298 return_ACPI_STATUS(status); 299 } 300 301 /******************************************************************************* 302 * 303 * FUNCTION: acpi_ex_create_processor 304 * 305 * PARAMETERS: walk_state - Current state 306 * 307 * RETURN: Status 308 * 309 * DESCRIPTION: Create a new processor object and populate the fields 310 * 311 * Processor (Name[0], cpu_ID[1], pblock_addr[2], pblock_length[3]) 312 * 313 ******************************************************************************/ 314 315 acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state) 316 { 317 union acpi_operand_object **operand = &walk_state->operands[0]; 318 union acpi_operand_object *obj_desc; 319 acpi_status status; 320 321 ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state); 322 323 /* Create the processor object */ 324 325 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR); 326 if (!obj_desc) { 327 return_ACPI_STATUS(AE_NO_MEMORY); 328 } 329 330 /* Initialize the processor object from the operands */ 331 332 obj_desc->processor.proc_id = (u8) operand[1]->integer.value; 333 obj_desc->processor.length = (u8) operand[3]->integer.value; 334 obj_desc->processor.address = 335 (acpi_io_address)operand[2]->integer.value; 336 337 /* Install the processor object in the parent Node */ 338 339 status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], 340 obj_desc, ACPI_TYPE_PROCESSOR); 341 342 /* Remove local reference to the object */ 343 344 acpi_ut_remove_reference(obj_desc); 345 return_ACPI_STATUS(status); 346 } 347 348 /******************************************************************************* 349 * 350 * FUNCTION: acpi_ex_create_power_resource 351 * 352 * PARAMETERS: walk_state - Current state 353 * 354 * RETURN: Status 355 * 356 * DESCRIPTION: Create a new power_resource object and populate the fields 357 * 358 * power_resource (Name[0], system_level[1], resource_order[2]) 359 * 360 ******************************************************************************/ 361 362 acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state) 363 { 364 union acpi_operand_object **operand = &walk_state->operands[0]; 365 acpi_status status; 366 union acpi_operand_object *obj_desc; 367 368 ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state); 369 370 /* Create the power resource object */ 371 372 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER); 373 if (!obj_desc) { 374 return_ACPI_STATUS(AE_NO_MEMORY); 375 } 376 377 /* Initialize the power object from the operands */ 378 379 obj_desc->power_resource.system_level = (u8) operand[1]->integer.value; 380 obj_desc->power_resource.resource_order = 381 (u16) operand[2]->integer.value; 382 383 /* Install the power resource object in the parent Node */ 384 385 status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], 386 obj_desc, ACPI_TYPE_POWER); 387 388 /* Remove local reference to the object */ 389 390 acpi_ut_remove_reference(obj_desc); 391 return_ACPI_STATUS(status); 392 } 393 394 /******************************************************************************* 395 * 396 * FUNCTION: acpi_ex_create_method 397 * 398 * PARAMETERS: aml_start - First byte of the method's AML 399 * aml_length - AML byte count for this method 400 * walk_state - Current state 401 * 402 * RETURN: Status 403 * 404 * DESCRIPTION: Create a new method object 405 * 406 ******************************************************************************/ 407 408 acpi_status 409 acpi_ex_create_method(u8 * aml_start, 410 u32 aml_length, struct acpi_walk_state *walk_state) 411 { 412 union acpi_operand_object **operand = &walk_state->operands[0]; 413 union acpi_operand_object *obj_desc; 414 acpi_status status; 415 u8 method_flags; 416 417 ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state); 418 419 /* Create a new method object */ 420 421 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); 422 if (!obj_desc) { 423 status = AE_NO_MEMORY; 424 goto exit; 425 } 426 427 /* Save the method's AML pointer and length */ 428 429 obj_desc->method.aml_start = aml_start; 430 obj_desc->method.aml_length = aml_length; 431 obj_desc->method.node = operand[0]; 432 433 /* 434 * Disassemble the method flags. Split off the arg_count, Serialized 435 * flag, and sync_level for efficiency. 436 */ 437 method_flags = (u8)operand[1]->integer.value; 438 obj_desc->method.param_count = (u8) 439 (method_flags & AML_METHOD_ARG_COUNT); 440 441 /* 442 * Get the sync_level. If method is serialized, a mutex will be 443 * created for this method when it is parsed. 444 */ 445 if (method_flags & AML_METHOD_SERIALIZED) { 446 obj_desc->method.info_flags = ACPI_METHOD_SERIALIZED; 447 448 /* 449 * ACPI 1.0: sync_level = 0 450 * ACPI 2.0: sync_level = sync_level in method declaration 451 */ 452 obj_desc->method.sync_level = (u8) 453 ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4); 454 } 455 456 /* Attach the new object to the method Node */ 457 458 status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0], 459 obj_desc, ACPI_TYPE_METHOD); 460 461 /* Remove local reference to the object */ 462 463 acpi_ut_remove_reference(obj_desc); 464 465 exit: 466 /* Remove a reference to the operand */ 467 468 acpi_ut_remove_reference(operand[1]); 469 return_ACPI_STATUS(status); 470 } 471