1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#define EXPORT_ACPI_INTERFACES
46
47#include <acpi/acpi.h>
48#include "accommon.h"
49#include "acnamesp.h"
50#include "acparser.h"
51#include "amlcode.h"
52
53#define _COMPONENT ACPI_NAMESPACE
54ACPI_MODULE_NAME("nsxfname")
55
56
57static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
58 struct acpi_pnp_device_id *source,
59 char *string_area);
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79acpi_status
80acpi_get_handle(acpi_handle parent,
81 acpi_string pathname, acpi_handle * ret_handle)
82{
83 acpi_status status;
84 struct acpi_namespace_node *node = NULL;
85 struct acpi_namespace_node *prefix_node = NULL;
86
87 ACPI_FUNCTION_ENTRY();
88
89
90
91 if (!ret_handle || !pathname) {
92 return (AE_BAD_PARAMETER);
93 }
94
95
96
97 if (parent) {
98 prefix_node = acpi_ns_validate_handle(parent);
99 if (!prefix_node) {
100 return (AE_BAD_PARAMETER);
101 }
102 }
103
104
105
106
107
108
109
110
111 if (ACPI_IS_ROOT_PREFIX(pathname[0])) {
112
113
114
115
116
117 if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) {
118 *ret_handle =
119 ACPI_CAST_PTR(acpi_handle, acpi_gbl_root_node);
120 return (AE_OK);
121 }
122 } else if (!prefix_node) {
123
124
125
126 return (AE_BAD_PARAMETER);
127 }
128
129
130
131 status =
132 acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node);
133 if (ACPI_SUCCESS(status)) {
134 *ret_handle = ACPI_CAST_PTR(acpi_handle, node);
135 }
136
137 return (status);
138}
139
140ACPI_EXPORT_SYMBOL(acpi_get_handle)
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157acpi_status
158acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
159{
160 acpi_status status;
161 struct acpi_namespace_node *node;
162 char *node_name;
163
164
165
166 if (name_type > ACPI_NAME_TYPE_MAX) {
167 return (AE_BAD_PARAMETER);
168 }
169
170 status = acpi_ut_validate_buffer(buffer);
171 if (ACPI_FAILURE(status)) {
172 return (status);
173 }
174
175 if (name_type == ACPI_FULL_PATHNAME) {
176
177
178
179 status = acpi_ns_handle_to_pathname(handle, buffer);
180 return (status);
181 }
182
183
184
185
186
187 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
188 if (ACPI_FAILURE(status)) {
189 return (status);
190 }
191
192 node = acpi_ns_validate_handle(handle);
193 if (!node) {
194 status = AE_BAD_PARAMETER;
195 goto unlock_and_exit;
196 }
197
198
199
200 status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH);
201 if (ACPI_FAILURE(status)) {
202 goto unlock_and_exit;
203 }
204
205
206
207 node_name = acpi_ut_get_node_name(node);
208 ACPI_MOVE_NAME(buffer->pointer, node_name);
209 ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
210 status = AE_OK;
211
212unlock_and_exit:
213
214 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
215 return (status);
216}
217
218ACPI_EXPORT_SYMBOL(acpi_get_name)
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
234 struct acpi_pnp_device_id *source,
235 char *string_area)
236{
237
238
239
240 dest->string = string_area;
241 dest->length = source->length;
242
243
244
245 ACPI_MEMCPY(string_area, source->string, source->length);
246 return (string_area + source->length);
247}
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269acpi_status
270acpi_get_object_info(acpi_handle handle,
271 struct acpi_device_info **return_buffer)
272{
273 struct acpi_namespace_node *node;
274 struct acpi_device_info *info;
275 struct acpi_pnp_device_id_list *cid_list = NULL;
276 struct acpi_pnp_device_id *hid = NULL;
277 struct acpi_pnp_device_id *uid = NULL;
278 struct acpi_pnp_device_id *sub = NULL;
279 char *next_id_string;
280 acpi_object_type type;
281 acpi_name name;
282 u8 param_count = 0;
283 u8 valid = 0;
284 u32 info_size;
285 u32 i;
286 acpi_status status;
287
288
289
290 if (!handle || !return_buffer) {
291 return (AE_BAD_PARAMETER);
292 }
293
294 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
295 if (ACPI_FAILURE(status)) {
296 return (status);
297 }
298
299 node = acpi_ns_validate_handle(handle);
300 if (!node) {
301 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
302 return (AE_BAD_PARAMETER);
303 }
304
305
306
307 info_size = sizeof(struct acpi_device_info);
308 type = node->type;
309 name = node->name.integer;
310
311 if (node->type == ACPI_TYPE_METHOD) {
312 param_count = node->object->method.param_count;
313 }
314
315 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
316 if (ACPI_FAILURE(status)) {
317 return (status);
318 }
319
320 if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
321
322
323
324
325
326
327
328
329
330
331
332 status = acpi_ut_execute_HID(node, &hid);
333 if (ACPI_SUCCESS(status)) {
334 info_size += hid->length;
335 valid |= ACPI_VALID_HID;
336 }
337
338
339
340 status = acpi_ut_execute_UID(node, &uid);
341 if (ACPI_SUCCESS(status)) {
342 info_size += uid->length;
343 valid |= ACPI_VALID_UID;
344 }
345
346
347
348 status = acpi_ut_execute_SUB(node, &sub);
349 if (ACPI_SUCCESS(status)) {
350 info_size += sub->length;
351 valid |= ACPI_VALID_SUB;
352 }
353
354
355
356 status = acpi_ut_execute_CID(node, &cid_list);
357 if (ACPI_SUCCESS(status)) {
358
359
360
361 info_size +=
362 (cid_list->list_size -
363 sizeof(struct acpi_pnp_device_id_list));
364 valid |= ACPI_VALID_CID;
365 }
366 }
367
368
369
370
371
372 info = ACPI_ALLOCATE_ZEROED(info_size);
373 if (!info) {
374 status = AE_NO_MEMORY;
375 goto cleanup;
376 }
377
378
379
380 if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397 status = acpi_ut_execute_STA(node, &info->current_status);
398 if (ACPI_SUCCESS(status)) {
399 valid |= ACPI_VALID_STA;
400 }
401
402
403
404 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
405 &info->address);
406 if (ACPI_SUCCESS(status)) {
407 valid |= ACPI_VALID_ADR;
408 }
409
410
411
412 status = acpi_ut_execute_power_methods(node,
413 acpi_gbl_lowest_dstate_names,
414 ACPI_NUM_sx_w_METHODS,
415 info->lowest_dstates);
416 if (ACPI_SUCCESS(status)) {
417 valid |= ACPI_VALID_SXWS;
418 }
419
420
421
422 status = acpi_ut_execute_power_methods(node,
423 acpi_gbl_highest_dstate_names,
424 ACPI_NUM_sx_d_METHODS,
425 info->highest_dstates);
426 if (ACPI_SUCCESS(status)) {
427 valid |= ACPI_VALID_SXDS;
428 }
429 }
430
431
432
433
434
435 next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids);
436 if (cid_list) {
437
438
439
440 next_id_string +=
441 ((acpi_size) cid_list->count *
442 sizeof(struct acpi_pnp_device_id));
443 }
444
445
446
447
448
449
450
451
452 if (hid) {
453 next_id_string = acpi_ns_copy_device_id(&info->hardware_id,
454 hid, next_id_string);
455
456 if (acpi_ut_is_pci_root_bridge(hid->string)) {
457 info->flags |= ACPI_PCI_ROOT_BRIDGE;
458 }
459 }
460
461 if (uid) {
462 next_id_string = acpi_ns_copy_device_id(&info->unique_id,
463 uid, next_id_string);
464 }
465
466 if (sub) {
467 next_id_string = acpi_ns_copy_device_id(&info->subsystem_id,
468 sub, next_id_string);
469 }
470
471 if (cid_list) {
472 info->compatible_id_list.count = cid_list->count;
473 info->compatible_id_list.list_size = cid_list->list_size;
474
475
476
477 for (i = 0; i < cid_list->count; i++) {
478 next_id_string =
479 acpi_ns_copy_device_id(&info->compatible_id_list.
480 ids[i], &cid_list->ids[i],
481 next_id_string);
482
483 if (acpi_ut_is_pci_root_bridge(cid_list->ids[i].string)) {
484 info->flags |= ACPI_PCI_ROOT_BRIDGE;
485 }
486 }
487 }
488
489
490
491 info->info_size = info_size;
492 info->type = type;
493 info->name = name;
494 info->param_count = param_count;
495 info->valid = valid;
496
497 *return_buffer = info;
498 status = AE_OK;
499
500cleanup:
501 if (hid) {
502 ACPI_FREE(hid);
503 }
504 if (uid) {
505 ACPI_FREE(uid);
506 }
507 if (sub) {
508 ACPI_FREE(sub);
509 }
510 if (cid_list) {
511 ACPI_FREE(cid_list);
512 }
513 return (status);
514}
515
516ACPI_EXPORT_SYMBOL(acpi_get_object_info)
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532acpi_status acpi_install_method(u8 *buffer)
533{
534 struct acpi_table_header *table =
535 ACPI_CAST_PTR(struct acpi_table_header, buffer);
536 u8 *aml_buffer;
537 u8 *aml_start;
538 char *path;
539 struct acpi_namespace_node *node;
540 union acpi_operand_object *method_obj;
541 struct acpi_parse_state parser_state;
542 u32 aml_length;
543 u16 opcode;
544 u8 method_flags;
545 acpi_status status;
546
547
548
549 if (!buffer) {
550 return (AE_BAD_PARAMETER);
551 }
552
553
554
555 if (!ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) &&
556 !ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) {
557 return (AE_BAD_HEADER);
558 }
559
560
561
562 parser_state.aml = buffer + sizeof(struct acpi_table_header);
563 opcode = acpi_ps_peek_opcode(&parser_state);
564 if (opcode != AML_METHOD_OP) {
565 return (AE_BAD_PARAMETER);
566 }
567
568
569
570 parser_state.aml += acpi_ps_get_opcode_size(opcode);
571 parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state);
572 path = acpi_ps_get_next_namestring(&parser_state);
573 method_flags = *parser_state.aml++;
574 aml_start = parser_state.aml;
575 aml_length = ACPI_PTR_DIFF(parser_state.pkg_end, aml_start);
576
577
578
579
580
581 aml_buffer = ACPI_ALLOCATE(aml_length);
582 if (!aml_buffer) {
583 return (AE_NO_MEMORY);
584 }
585
586 method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
587 if (!method_obj) {
588 ACPI_FREE(aml_buffer);
589 return (AE_NO_MEMORY);
590 }
591
592
593
594 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
595 if (ACPI_FAILURE(status)) {
596 goto error_exit;
597 }
598
599
600
601 status =
602 acpi_ns_lookup(NULL, path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
603 ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND,
604 NULL, &node);
605
606 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
607
608 if (ACPI_FAILURE(status)) {
609 if (status != AE_ALREADY_EXISTS) {
610 goto error_exit;
611 }
612
613
614
615 if (node->type != ACPI_TYPE_METHOD) {
616 status = AE_TYPE;
617 goto error_exit;
618 }
619 }
620
621
622
623 ACPI_MEMCPY(aml_buffer, aml_start, aml_length);
624
625
626
627 method_obj->method.aml_start = aml_buffer;
628 method_obj->method.aml_length = aml_length;
629
630 method_obj->method.param_count = (u8)
631 (method_flags & AML_METHOD_ARG_COUNT);
632
633 if (method_flags & AML_METHOD_SERIALIZED) {
634 method_obj->method.info_flags = ACPI_METHOD_SERIALIZED;
635
636 method_obj->method.sync_level = (u8)
637 ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
638 }
639
640
641
642
643
644 status = acpi_ns_attach_object(node, method_obj, ACPI_TYPE_METHOD);
645
646
647
648
649
650 node->flags |= ANOBJ_ALLOCATED_BUFFER;
651
652
653
654 acpi_ut_remove_reference(method_obj);
655 return (status);
656
657error_exit:
658
659 ACPI_FREE(aml_buffer);
660 ACPI_FREE(method_obj);
661 return (status);
662}
663ACPI_EXPORT_SYMBOL(acpi_install_method)
664