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