0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <acpi/acpi.h>
0012 #include "accommon.h"
0013 #include "acnamesp.h"
0014 #include "amlcode.h"
0015
0016 #define _COMPONENT ACPI_NAMESPACE
0017 ACPI_MODULE_NAME("nsutils")
0018
0019
0020 #ifdef ACPI_OBSOLETE_FUNCTIONS
0021 acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
0022 #endif
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 void
0037 acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
0038 const char *message)
0039 {
0040 struct acpi_buffer buffer;
0041 acpi_status status;
0042
0043 if (!node) {
0044 acpi_os_printf("[NULL NAME]");
0045 return;
0046 }
0047
0048
0049
0050 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
0051
0052 status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
0053 if (ACPI_SUCCESS(status)) {
0054 if (message) {
0055 acpi_os_printf("%s ", message);
0056 }
0057
0058 acpi_os_printf("%s", (char *)buffer.pointer);
0059 ACPI_FREE(buffer.pointer);
0060 }
0061 }
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
0076 {
0077 ACPI_FUNCTION_TRACE(ns_get_type);
0078
0079 if (!node) {
0080 ACPI_WARNING((AE_INFO, "Null Node parameter"));
0081 return_UINT8(ACPI_TYPE_ANY);
0082 }
0083
0084 return_UINT8(node->type);
0085 }
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100 u32 acpi_ns_local(acpi_object_type type)
0101 {
0102 ACPI_FUNCTION_TRACE(ns_local);
0103
0104 if (!acpi_ut_valid_object_type(type)) {
0105
0106
0107
0108 ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
0109 return_UINT32(ACPI_NS_NORMAL);
0110 }
0111
0112 return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
0113 }
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
0130 {
0131 const char *next_external_char;
0132 u32 i;
0133
0134 ACPI_FUNCTION_ENTRY();
0135
0136 next_external_char = info->external_name;
0137 info->num_carats = 0;
0138 info->num_segments = 0;
0139 info->fully_qualified = FALSE;
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 if (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
0150 info->fully_qualified = TRUE;
0151 next_external_char++;
0152
0153
0154
0155 while (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
0156 next_external_char++;
0157 }
0158 } else {
0159
0160
0161 while (ACPI_IS_PARENT_PREFIX(*next_external_char)) {
0162 info->num_carats++;
0163 next_external_char++;
0164 }
0165 }
0166
0167
0168
0169
0170
0171
0172 if (*next_external_char) {
0173 info->num_segments = 1;
0174 for (i = 0; next_external_char[i]; i++) {
0175 if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) {
0176 info->num_segments++;
0177 }
0178 }
0179 }
0180
0181 info->length = (ACPI_NAMESEG_SIZE * info->num_segments) +
0182 4 + info->num_carats;
0183
0184 info->next_external_char = next_external_char;
0185 }
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200 acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
0201 {
0202 u32 num_segments = info->num_segments;
0203 char *internal_name = info->internal_name;
0204 const char *external_name = info->next_external_char;
0205 char *result = NULL;
0206 u32 i;
0207
0208 ACPI_FUNCTION_TRACE(ns_build_internal_name);
0209
0210
0211
0212 if (info->fully_qualified) {
0213 internal_name[0] = AML_ROOT_PREFIX;
0214
0215 if (num_segments <= 1) {
0216 result = &internal_name[1];
0217 } else if (num_segments == 2) {
0218 internal_name[1] = AML_DUAL_NAME_PREFIX;
0219 result = &internal_name[2];
0220 } else {
0221 internal_name[1] = AML_MULTI_NAME_PREFIX;
0222 internal_name[2] = (char)num_segments;
0223 result = &internal_name[3];
0224 }
0225 } else {
0226
0227
0228
0229
0230 i = 0;
0231 if (info->num_carats) {
0232 for (i = 0; i < info->num_carats; i++) {
0233 internal_name[i] = AML_PARENT_PREFIX;
0234 }
0235 }
0236
0237 if (num_segments <= 1) {
0238 result = &internal_name[i];
0239 } else if (num_segments == 2) {
0240 internal_name[i] = AML_DUAL_NAME_PREFIX;
0241 result = &internal_name[(acpi_size)i + 1];
0242 } else {
0243 internal_name[i] = AML_MULTI_NAME_PREFIX;
0244 internal_name[(acpi_size)i + 1] = (char)num_segments;
0245 result = &internal_name[(acpi_size)i + 2];
0246 }
0247 }
0248
0249
0250
0251 for (; num_segments; num_segments--) {
0252 for (i = 0; i < ACPI_NAMESEG_SIZE; i++) {
0253 if (ACPI_IS_PATH_SEPARATOR(*external_name) ||
0254 (*external_name == 0)) {
0255
0256
0257
0258 result[i] = '_';
0259 } else {
0260
0261
0262 result[i] = (char)toupper((int)*external_name);
0263 external_name++;
0264 }
0265 }
0266
0267
0268
0269 if (!ACPI_IS_PATH_SEPARATOR(*external_name) &&
0270 (*external_name != 0)) {
0271 return_ACPI_STATUS(AE_BAD_PATHNAME);
0272 }
0273
0274
0275
0276 external_name++;
0277 result += ACPI_NAMESEG_SIZE;
0278 }
0279
0280
0281
0282 *result = 0;
0283
0284 if (info->fully_qualified) {
0285 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0286 "Returning [%p] (abs) \"\\%s\"\n",
0287 internal_name, internal_name));
0288 } else {
0289 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
0290 internal_name, internal_name));
0291 }
0292
0293 return_ACPI_STATUS(AE_OK);
0294 }
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311 acpi_status
0312 acpi_ns_internalize_name(const char *external_name, char **converted_name)
0313 {
0314 char *internal_name;
0315 struct acpi_namestring_info info;
0316 acpi_status status;
0317
0318 ACPI_FUNCTION_TRACE(ns_internalize_name);
0319
0320 if ((!external_name) || (*external_name == 0) || (!converted_name)) {
0321 return_ACPI_STATUS(AE_BAD_PARAMETER);
0322 }
0323
0324
0325
0326 info.external_name = external_name;
0327 acpi_ns_get_internal_name_length(&info);
0328
0329
0330
0331 internal_name = ACPI_ALLOCATE_ZEROED(info.length);
0332 if (!internal_name) {
0333 return_ACPI_STATUS(AE_NO_MEMORY);
0334 }
0335
0336
0337
0338 info.internal_name = internal_name;
0339 status = acpi_ns_build_internal_name(&info);
0340 if (ACPI_FAILURE(status)) {
0341 ACPI_FREE(internal_name);
0342 return_ACPI_STATUS(status);
0343 }
0344
0345 *converted_name = internal_name;
0346 return_ACPI_STATUS(AE_OK);
0347 }
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 acpi_status
0367 acpi_ns_externalize_name(u32 internal_name_length,
0368 const char *internal_name,
0369 u32 * converted_name_length, char **converted_name)
0370 {
0371 u32 names_index = 0;
0372 u32 num_segments = 0;
0373 u32 required_length;
0374 u32 prefix_length = 0;
0375 u32 i = 0;
0376 u32 j = 0;
0377
0378 ACPI_FUNCTION_TRACE(ns_externalize_name);
0379
0380 if (!internal_name_length || !internal_name || !converted_name) {
0381 return_ACPI_STATUS(AE_BAD_PARAMETER);
0382 }
0383
0384
0385
0386 switch (internal_name[0]) {
0387 case AML_ROOT_PREFIX:
0388
0389 prefix_length = 1;
0390 break;
0391
0392 case AML_PARENT_PREFIX:
0393
0394 for (i = 0; i < internal_name_length; i++) {
0395 if (ACPI_IS_PARENT_PREFIX(internal_name[i])) {
0396 prefix_length = i + 1;
0397 } else {
0398 break;
0399 }
0400 }
0401
0402 if (i == internal_name_length) {
0403 prefix_length = i;
0404 }
0405
0406 break;
0407
0408 default:
0409
0410 break;
0411 }
0412
0413
0414
0415
0416
0417 if (prefix_length < internal_name_length) {
0418 switch (internal_name[prefix_length]) {
0419 case AML_MULTI_NAME_PREFIX:
0420
0421
0422
0423 names_index = prefix_length + 2;
0424 num_segments = (u8)
0425 internal_name[(acpi_size)prefix_length + 1];
0426 break;
0427
0428 case AML_DUAL_NAME_PREFIX:
0429
0430
0431
0432 names_index = prefix_length + 1;
0433 num_segments = 2;
0434 break;
0435
0436 case 0:
0437
0438
0439
0440 names_index = 0;
0441 num_segments = 0;
0442 break;
0443
0444 default:
0445
0446
0447
0448 names_index = prefix_length;
0449 num_segments = 1;
0450 break;
0451 }
0452 }
0453
0454
0455
0456
0457
0458
0459 required_length = prefix_length + (4 * num_segments) +
0460 ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
0461
0462
0463
0464
0465
0466 if (required_length > internal_name_length) {
0467 ACPI_ERROR((AE_INFO, "Invalid internal name"));
0468 return_ACPI_STATUS(AE_BAD_PATHNAME);
0469 }
0470
0471
0472
0473 *converted_name = ACPI_ALLOCATE_ZEROED(required_length);
0474 if (!(*converted_name)) {
0475 return_ACPI_STATUS(AE_NO_MEMORY);
0476 }
0477
0478 j = 0;
0479
0480 for (i = 0; i < prefix_length; i++) {
0481 (*converted_name)[j++] = internal_name[i];
0482 }
0483
0484 if (num_segments > 0) {
0485 for (i = 0; i < num_segments; i++) {
0486 if (i > 0) {
0487 (*converted_name)[j++] = '.';
0488 }
0489
0490
0491
0492 ACPI_COPY_NAMESEG(&(*converted_name)[j],
0493 &internal_name[names_index]);
0494 acpi_ut_repair_name(&(*converted_name)[j]);
0495
0496 j += ACPI_NAMESEG_SIZE;
0497 names_index += ACPI_NAMESEG_SIZE;
0498 }
0499 }
0500
0501 if (converted_name_length) {
0502 *converted_name_length = (u32) required_length;
0503 }
0504
0505 return_ACPI_STATUS(AE_OK);
0506 }
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528 struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
0529 {
0530
0531 ACPI_FUNCTION_ENTRY();
0532
0533
0534
0535 if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
0536 return (acpi_gbl_root_node);
0537 }
0538
0539
0540
0541 if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
0542 return (NULL);
0543 }
0544
0545 return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
0546 }
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560 void acpi_ns_terminate(void)
0561 {
0562 acpi_status status;
0563
0564 ACPI_FUNCTION_TRACE(ns_terminate);
0565
0566
0567
0568
0569
0570 acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
0571
0572
0573
0574 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0575 if (ACPI_FAILURE(status)) {
0576 return_VOID;
0577 }
0578
0579 acpi_ns_delete_node(acpi_gbl_root_node);
0580 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0581
0582 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
0583 return_VOID;
0584 }
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597 u32 acpi_ns_opens_scope(acpi_object_type type)
0598 {
0599 ACPI_FUNCTION_ENTRY();
0600
0601 if (type > ACPI_TYPE_LOCAL_MAX) {
0602
0603
0604
0605 ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
0606 return (ACPI_NS_NORMAL);
0607 }
0608
0609 return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
0610 }
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634 acpi_status
0635 acpi_ns_get_node_unlocked(struct acpi_namespace_node *prefix_node,
0636 const char *pathname,
0637 u32 flags, struct acpi_namespace_node **return_node)
0638 {
0639 union acpi_generic_state scope_info;
0640 acpi_status status;
0641 char *internal_path;
0642
0643 ACPI_FUNCTION_TRACE_PTR(ns_get_node_unlocked,
0644 ACPI_CAST_PTR(char, pathname));
0645
0646
0647
0648 if (!pathname) {
0649 *return_node = prefix_node;
0650 if (!prefix_node) {
0651 *return_node = acpi_gbl_root_node;
0652 }
0653
0654 return_ACPI_STATUS(AE_OK);
0655 }
0656
0657
0658
0659 if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) {
0660 *return_node = acpi_gbl_root_node;
0661 return_ACPI_STATUS(AE_OK);
0662 }
0663
0664
0665
0666 status = acpi_ns_internalize_name(pathname, &internal_path);
0667 if (ACPI_FAILURE(status)) {
0668 return_ACPI_STATUS(status);
0669 }
0670
0671
0672
0673 scope_info.scope.node = prefix_node;
0674
0675
0676
0677 status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY,
0678 ACPI_IMODE_EXECUTE,
0679 (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL,
0680 return_node);
0681 if (ACPI_FAILURE(status)) {
0682 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n",
0683 pathname, acpi_format_exception(status)));
0684 }
0685
0686 ACPI_FREE(internal_path);
0687 return_ACPI_STATUS(status);
0688 }
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712 acpi_status
0713 acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
0714 const char *pathname,
0715 u32 flags, struct acpi_namespace_node **return_node)
0716 {
0717 acpi_status status;
0718
0719 ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
0720
0721 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0722 if (ACPI_FAILURE(status)) {
0723 return_ACPI_STATUS(status);
0724 }
0725
0726 status = acpi_ns_get_node_unlocked(prefix_node, pathname,
0727 flags, return_node);
0728
0729 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0730 return_ACPI_STATUS(status);
0731 }