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