Linux-libre 4.4.228-gnu
[librecmc/linux-libre.git] / drivers / acpi / acpica / dbcmds.c
1 /*******************************************************************************
2  *
3  * Module Name: dbcmds - Miscellaneous debug commands and output routines
4  *
5  ******************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include <acpi/acpi.h>
45 #include "accommon.h"
46 #include "acevents.h"
47 #include "acdebug.h"
48 #include "acnamesp.h"
49 #include "acresrc.h"
50 #include "actables.h"
51
52 #define _COMPONENT          ACPI_CA_DEBUGGER
53 ACPI_MODULE_NAME("dbcmds")
54
55 /* Local prototypes */
56 static void
57 acpi_dm_compare_aml_resources(u8 *aml1_buffer,
58                               acpi_rsdesc_size aml1_buffer_length,
59                               u8 *aml2_buffer,
60                               acpi_rsdesc_size aml2_buffer_length);
61
62 static acpi_status
63 acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name);
64
65 static acpi_status
66 acpi_db_resource_callback(struct acpi_resource *resource, void *context);
67
68 static acpi_status
69 acpi_db_device_resources(acpi_handle obj_handle,
70                          u32 nesting_level, void *context, void **return_value);
71
72 static void acpi_db_do_one_sleep_state(u8 sleep_state);
73
74 static char *acpi_db_trace_method_name = NULL;
75
76 /*******************************************************************************
77  *
78  * FUNCTION:    acpi_db_convert_to_node
79  *
80  * PARAMETERS:  in_string           - String to convert
81  *
82  * RETURN:      Pointer to a NS node
83  *
84  * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or
85  *              alphanumeric strings.
86  *
87  ******************************************************************************/
88
89 struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string)
90 {
91         struct acpi_namespace_node *node;
92         acpi_size address;
93
94         if ((*in_string >= 0x30) && (*in_string <= 0x39)) {
95
96                 /* Numeric argument, convert */
97
98                 address = strtoul(in_string, NULL, 16);
99                 node = ACPI_TO_POINTER(address);
100                 if (!acpi_os_readable(node, sizeof(struct acpi_namespace_node))) {
101                         acpi_os_printf("Address %p is invalid", node);
102                         return (NULL);
103                 }
104
105                 /* Make sure pointer is valid NS node */
106
107                 if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
108                         acpi_os_printf
109                             ("Address %p is not a valid namespace node [%s]\n",
110                              node, acpi_ut_get_descriptor_name(node));
111                         return (NULL);
112                 }
113         } else {
114                 /*
115                  * Alpha argument: The parameter is a name string that must be
116                  * resolved to a Namespace object.
117                  */
118                 node = acpi_db_local_ns_lookup(in_string);
119                 if (!node) {
120                         acpi_os_printf
121                             ("Could not find [%s] in namespace, defaulting to root node\n",
122                              in_string);
123                         node = acpi_gbl_root_node;
124                 }
125         }
126
127         return (node);
128 }
129
130 /*******************************************************************************
131  *
132  * FUNCTION:    acpi_db_sleep
133  *
134  * PARAMETERS:  object_arg          - Desired sleep state (0-5). NULL means
135  *                                    invoke all possible sleep states.
136  *
137  * RETURN:      Status
138  *
139  * DESCRIPTION: Simulate sleep/wake sequences
140  *
141  ******************************************************************************/
142
143 acpi_status acpi_db_sleep(char *object_arg)
144 {
145         u8 sleep_state;
146         u32 i;
147
148         ACPI_FUNCTION_TRACE(acpi_db_sleep);
149
150         /* Null input (no arguments) means to invoke all sleep states */
151
152         if (!object_arg) {
153                 acpi_os_printf("Invoking all possible sleep states, 0-%d\n",
154                                ACPI_S_STATES_MAX);
155
156                 for (i = 0; i <= ACPI_S_STATES_MAX; i++) {
157                         acpi_db_do_one_sleep_state((u8)i);
158                 }
159
160                 return_ACPI_STATUS(AE_OK);
161         }
162
163         /* Convert argument to binary and invoke the sleep state */
164
165         sleep_state = (u8)strtoul(object_arg, NULL, 0);
166         acpi_db_do_one_sleep_state(sleep_state);
167         return_ACPI_STATUS(AE_OK);
168 }
169
170 /*******************************************************************************
171  *
172  * FUNCTION:    acpi_db_do_one_sleep_state
173  *
174  * PARAMETERS:  sleep_state         - Desired sleep state (0-5)
175  *
176  * RETURN:      None
177  *
178  * DESCRIPTION: Simulate a sleep/wake sequence
179  *
180  ******************************************************************************/
181
182 static void acpi_db_do_one_sleep_state(u8 sleep_state)
183 {
184         acpi_status status;
185         u8 sleep_type_a;
186         u8 sleep_type_b;
187
188         /* Validate parameter */
189
190         if (sleep_state > ACPI_S_STATES_MAX) {
191                 acpi_os_printf("Sleep state %d out of range (%d max)\n",
192                                sleep_state, ACPI_S_STATES_MAX);
193                 return;
194         }
195
196         acpi_os_printf("\n---- Invoking sleep state S%d (%s):\n",
197                        sleep_state, acpi_gbl_sleep_state_names[sleep_state]);
198
199         /* Get the values for the sleep type registers (for display only) */
200
201         status =
202             acpi_get_sleep_type_data(sleep_state, &sleep_type_a, &sleep_type_b);
203         if (ACPI_FAILURE(status)) {
204                 acpi_os_printf("Could not evaluate [%s] method, %s\n",
205                                acpi_gbl_sleep_state_names[sleep_state],
206                                acpi_format_exception(status));
207                 return;
208         }
209
210         acpi_os_printf
211             ("Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n",
212              sleep_state, sleep_type_a, sleep_type_b);
213
214         /* Invoke the various sleep/wake interfaces */
215
216         acpi_os_printf("**** Sleep: Prepare to sleep (S%d) ****\n",
217                        sleep_state);
218         status = acpi_enter_sleep_state_prep(sleep_state);
219         if (ACPI_FAILURE(status)) {
220                 goto error_exit;
221         }
222
223         acpi_os_printf("**** Sleep: Going to sleep (S%d) ****\n", sleep_state);
224         status = acpi_enter_sleep_state(sleep_state);
225         if (ACPI_FAILURE(status)) {
226                 goto error_exit;
227         }
228
229         acpi_os_printf("**** Wake: Prepare to return from sleep (S%d) ****\n",
230                        sleep_state);
231         status = acpi_leave_sleep_state_prep(sleep_state);
232         if (ACPI_FAILURE(status)) {
233                 goto error_exit;
234         }
235
236         acpi_os_printf("**** Wake: Return from sleep (S%d) ****\n",
237                        sleep_state);
238         status = acpi_leave_sleep_state(sleep_state);
239         if (ACPI_FAILURE(status)) {
240                 goto error_exit;
241         }
242
243         return;
244
245 error_exit:
246         ACPI_EXCEPTION((AE_INFO, status, "During invocation of sleep state S%d",
247                         sleep_state));
248 }
249
250 /*******************************************************************************
251  *
252  * FUNCTION:    acpi_db_display_locks
253  *
254  * PARAMETERS:  None
255  *
256  * RETURN:      None
257  *
258  * DESCRIPTION: Display information about internal mutexes.
259  *
260  ******************************************************************************/
261
262 void acpi_db_display_locks(void)
263 {
264         u32 i;
265
266         for (i = 0; i < ACPI_MAX_MUTEX; i++) {
267                 acpi_os_printf("%26s : %s\n", acpi_ut_get_mutex_name(i),
268                                acpi_gbl_mutex_info[i].thread_id ==
269                                ACPI_MUTEX_NOT_ACQUIRED ? "Locked" : "Unlocked");
270         }
271 }
272
273 /*******************************************************************************
274  *
275  * FUNCTION:    acpi_db_display_table_info
276  *
277  * PARAMETERS:  table_arg           - Name of table to be displayed
278  *
279  * RETURN:      None
280  *
281  * DESCRIPTION: Display information about loaded tables. Current
282  *              implementation displays all loaded tables.
283  *
284  ******************************************************************************/
285
286 void acpi_db_display_table_info(char *table_arg)
287 {
288         u32 i;
289         struct acpi_table_desc *table_desc;
290         acpi_status status;
291
292         /* Header */
293
294         acpi_os_printf("Idx ID  Status Type                    "
295                        "TableHeader (Sig, Address, Length, Misc)\n");
296
297         /* Walk the entire root table list */
298
299         for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
300                 table_desc = &acpi_gbl_root_table_list.tables[i];
301
302                 /* Index and Table ID */
303
304                 acpi_os_printf("%3u %.2u ", i, table_desc->owner_id);
305
306                 /* Decode the table flags */
307
308                 if (!(table_desc->flags & ACPI_TABLE_IS_LOADED)) {
309                         acpi_os_printf("NotLoaded ");
310                 } else {
311                         acpi_os_printf(" Loaded ");
312                 }
313
314                 switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
315                 case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
316
317                         acpi_os_printf("External/virtual ");
318                         break;
319
320                 case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
321
322                         acpi_os_printf("Internal/physical ");
323                         break;
324
325                 case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
326
327                         acpi_os_printf("Internal/virtual ");
328                         break;
329
330                 default:
331
332                         acpi_os_printf("INVALID TYPE    ");
333                         break;
334                 }
335
336                 /* Make sure that the table is mapped */
337
338                 status = acpi_tb_validate_table(table_desc);
339                 if (ACPI_FAILURE(status)) {
340                         return;
341                 }
342
343                 /* Dump the table header */
344
345                 if (table_desc->pointer) {
346                         acpi_tb_print_table_header(table_desc->address,
347                                                    table_desc->pointer);
348                 } else {
349                         /* If the pointer is null, the table has been unloaded */
350
351                         ACPI_INFO((AE_INFO, "%4.4s - Table has been unloaded",
352                                    table_desc->signature.ascii));
353                 }
354         }
355 }
356
357 /*******************************************************************************
358  *
359  * FUNCTION:    acpi_db_unload_acpi_table
360  *
361  * PARAMETERS:  object_name         - Namespace pathname for an object that
362  *                                    is owned by the table to be unloaded
363  *
364  * RETURN:      None
365  *
366  * DESCRIPTION: Unload an ACPI table, via any namespace node that is owned
367  *              by the table.
368  *
369  ******************************************************************************/
370
371 void acpi_db_unload_acpi_table(char *object_name)
372 {
373         struct acpi_namespace_node *node;
374         acpi_status status;
375
376         /* Translate name to an Named object */
377
378         node = acpi_db_convert_to_node(object_name);
379         if (!node) {
380                 return;
381         }
382
383         status = acpi_unload_parent_table(ACPI_CAST_PTR(acpi_handle, node));
384         if (ACPI_SUCCESS(status)) {
385                 acpi_os_printf("Parent of [%s] (%p) unloaded and uninstalled\n",
386                                object_name, node);
387         } else {
388                 acpi_os_printf("%s, while unloading parent table of [%s]\n",
389                                acpi_format_exception(status), object_name);
390         }
391 }
392
393 /*******************************************************************************
394  *
395  * FUNCTION:    acpi_db_send_notify
396  *
397  * PARAMETERS:  name                - Name of ACPI object where to send notify
398  *              value               - Value of the notify to send.
399  *
400  * RETURN:      None
401  *
402  * DESCRIPTION: Send an ACPI notification. The value specified is sent to the
403  *              named object as an ACPI notify.
404  *
405  ******************************************************************************/
406
407 void acpi_db_send_notify(char *name, u32 value)
408 {
409         struct acpi_namespace_node *node;
410         acpi_status status;
411
412         /* Translate name to an Named object */
413
414         node = acpi_db_convert_to_node(name);
415         if (!node) {
416                 return;
417         }
418
419         /* Dispatch the notify if legal */
420
421         if (acpi_ev_is_notify_object(node)) {
422                 status = acpi_ev_queue_notify_request(node, value);
423                 if (ACPI_FAILURE(status)) {
424                         acpi_os_printf("Could not queue notify\n");
425                 }
426         } else {
427                 acpi_os_printf("Named object [%4.4s] Type %s, "
428                                "must be Device/Thermal/Processor type\n",
429                                acpi_ut_get_node_name(node),
430                                acpi_ut_get_type_name(node->type));
431         }
432 }
433
434 /*******************************************************************************
435  *
436  * FUNCTION:    acpi_db_display_interfaces
437  *
438  * PARAMETERS:  action_arg          - Null, "install", or "remove"
439  *              interface_name_arg  - Name for install/remove options
440  *
441  * RETURN:      None
442  *
443  * DESCRIPTION: Display or modify the global _OSI interface list
444  *
445  ******************************************************************************/
446
447 void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg)
448 {
449         struct acpi_interface_info *next_interface;
450         char *sub_string;
451         acpi_status status;
452
453         /* If no arguments, just display current interface list */
454
455         if (!action_arg) {
456                 (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex,
457                                             ACPI_WAIT_FOREVER);
458
459                 next_interface = acpi_gbl_supported_interfaces;
460                 while (next_interface) {
461                         if (!(next_interface->flags & ACPI_OSI_INVALID)) {
462                                 acpi_os_printf("%s\n", next_interface->name);
463                         }
464
465                         next_interface = next_interface->next;
466                 }
467
468                 acpi_os_release_mutex(acpi_gbl_osi_mutex);
469                 return;
470         }
471
472         /* If action_arg exists, so must interface_name_arg */
473
474         if (!interface_name_arg) {
475                 acpi_os_printf("Missing Interface Name argument\n");
476                 return;
477         }
478
479         /* Uppercase the action for match below */
480
481         acpi_ut_strupr(action_arg);
482
483         /* install - install an interface */
484
485         sub_string = strstr("INSTALL", action_arg);
486         if (sub_string) {
487                 status = acpi_install_interface(interface_name_arg);
488                 if (ACPI_FAILURE(status)) {
489                         acpi_os_printf("%s, while installing \"%s\"\n",
490                                        acpi_format_exception(status),
491                                        interface_name_arg);
492                 }
493                 return;
494         }
495
496         /* remove - remove an interface */
497
498         sub_string = strstr("REMOVE", action_arg);
499         if (sub_string) {
500                 status = acpi_remove_interface(interface_name_arg);
501                 if (ACPI_FAILURE(status)) {
502                         acpi_os_printf("%s, while removing \"%s\"\n",
503                                        acpi_format_exception(status),
504                                        interface_name_arg);
505                 }
506                 return;
507         }
508
509         /* Invalid action_arg */
510
511         acpi_os_printf("Invalid action argument: %s\n", action_arg);
512         return;
513 }
514
515 /*******************************************************************************
516  *
517  * FUNCTION:    acpi_db_display_template
518  *
519  * PARAMETERS:  buffer_arg          - Buffer name or address
520  *
521  * RETURN:      None
522  *
523  * DESCRIPTION: Dump a buffer that contains a resource template
524  *
525  ******************************************************************************/
526
527 void acpi_db_display_template(char *buffer_arg)
528 {
529         struct acpi_namespace_node *node;
530         acpi_status status;
531         struct acpi_buffer return_buffer;
532
533         /* Translate buffer_arg to an Named object */
534
535         node = acpi_db_convert_to_node(buffer_arg);
536         if (!node || (node == acpi_gbl_root_node)) {
537                 acpi_os_printf("Invalid argument: %s\n", buffer_arg);
538                 return;
539         }
540
541         /* We must have a buffer object */
542
543         if (node->type != ACPI_TYPE_BUFFER) {
544                 acpi_os_printf
545                     ("Not a Buffer object, cannot be a template: %s\n",
546                      buffer_arg);
547                 return;
548         }
549
550         return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
551         return_buffer.pointer = acpi_gbl_db_buffer;
552
553         /* Attempt to convert the raw buffer to a resource list */
554
555         status = acpi_rs_create_resource_list(node->object, &return_buffer);
556
557         acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
558         acpi_dbg_level |= ACPI_LV_RESOURCES;
559
560         if (ACPI_FAILURE(status)) {
561                 acpi_os_printf
562                     ("Could not convert Buffer to a resource list: %s, %s\n",
563                      buffer_arg, acpi_format_exception(status));
564                 goto dump_buffer;
565         }
566
567         /* Now we can dump the resource list */
568
569         acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource,
570                                                  return_buffer.pointer));
571
572 dump_buffer:
573         acpi_os_printf("\nRaw data buffer:\n");
574         acpi_ut_debug_dump_buffer((u8 *)node->object->buffer.pointer,
575                                   node->object->buffer.length,
576                                   DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
577
578         acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
579         return;
580 }
581
582 /*******************************************************************************
583  *
584  * FUNCTION:    acpi_dm_compare_aml_resources
585  *
586  * PARAMETERS:  aml1_buffer         - Contains first resource list
587  *              aml1_buffer_length  - Length of first resource list
588  *              aml2_buffer         - Contains second resource list
589  *              aml2_buffer_length  - Length of second resource list
590  *
591  * RETURN:      None
592  *
593  * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in
594  *              order to isolate a miscompare to an individual resource)
595  *
596  ******************************************************************************/
597
598 static void
599 acpi_dm_compare_aml_resources(u8 *aml1_buffer,
600                               acpi_rsdesc_size aml1_buffer_length,
601                               u8 *aml2_buffer,
602                               acpi_rsdesc_size aml2_buffer_length)
603 {
604         u8 *aml1;
605         u8 *aml2;
606         u8 *aml1_end;
607         u8 *aml2_end;
608         acpi_rsdesc_size aml1_length;
609         acpi_rsdesc_size aml2_length;
610         acpi_rsdesc_size offset = 0;
611         u8 resource_type;
612         u32 count = 0;
613         u32 i;
614
615         /* Compare overall buffer sizes (may be different due to size rounding) */
616
617         if (aml1_buffer_length != aml2_buffer_length) {
618                 acpi_os_printf("**** Buffer length mismatch in converted "
619                                "AML: Original %X, New %X ****\n",
620                                aml1_buffer_length, aml2_buffer_length);
621         }
622
623         aml1 = aml1_buffer;
624         aml2 = aml2_buffer;
625         aml1_end = aml1_buffer + aml1_buffer_length;
626         aml2_end = aml2_buffer + aml2_buffer_length;
627
628         /* Walk the descriptor lists, comparing each descriptor */
629
630         while ((aml1 < aml1_end) && (aml2 < aml2_end)) {
631
632                 /* Get the lengths of each descriptor */
633
634                 aml1_length = acpi_ut_get_descriptor_length(aml1);
635                 aml2_length = acpi_ut_get_descriptor_length(aml2);
636                 resource_type = acpi_ut_get_resource_type(aml1);
637
638                 /* Check for descriptor length match */
639
640                 if (aml1_length != aml2_length) {
641                         acpi_os_printf
642                             ("**** Length mismatch in descriptor [%.2X] type %2.2X, "
643                              "Offset %8.8X Len1 %X, Len2 %X ****\n", count,
644                              resource_type, offset, aml1_length, aml2_length);
645                 }
646
647                 /* Check for descriptor byte match */
648
649                 else if (memcmp(aml1, aml2, aml1_length)) {
650                         acpi_os_printf
651                             ("**** Data mismatch in descriptor [%.2X] type %2.2X, "
652                              "Offset %8.8X ****\n", count, resource_type,
653                              offset);
654
655                         for (i = 0; i < aml1_length; i++) {
656                                 if (aml1[i] != aml2[i]) {
657                                         acpi_os_printf
658                                             ("Mismatch at byte offset %.2X: is %2.2X, "
659                                              "should be %2.2X\n", i, aml2[i],
660                                              aml1[i]);
661                                 }
662                         }
663                 }
664
665                 /* Exit on end_tag descriptor */
666
667                 if (resource_type == ACPI_RESOURCE_NAME_END_TAG) {
668                         return;
669                 }
670
671                 /* Point to next descriptor in each buffer */
672
673                 count++;
674                 offset += aml1_length;
675                 aml1 += aml1_length;
676                 aml2 += aml2_length;
677         }
678 }
679
680 /*******************************************************************************
681  *
682  * FUNCTION:    acpi_dm_test_resource_conversion
683  *
684  * PARAMETERS:  node                - Parent device node
685  *              name                - resource method name (_CRS)
686  *
687  * RETURN:      Status
688  *
689  * DESCRIPTION: Compare the original AML with a conversion of the AML to
690  *              internal resource list, then back to AML.
691  *
692  ******************************************************************************/
693
694 static acpi_status
695 acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name)
696 {
697         acpi_status status;
698         struct acpi_buffer return_buffer;
699         struct acpi_buffer resource_buffer;
700         struct acpi_buffer new_aml;
701         union acpi_object *original_aml;
702
703         acpi_os_printf("Resource Conversion Comparison:\n");
704
705         new_aml.length = ACPI_ALLOCATE_LOCAL_BUFFER;
706         return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
707         resource_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
708
709         /* Get the original _CRS AML resource template */
710
711         status = acpi_evaluate_object(node, name, NULL, &return_buffer);
712         if (ACPI_FAILURE(status)) {
713                 acpi_os_printf("Could not obtain %s: %s\n",
714                                name, acpi_format_exception(status));
715                 return (status);
716         }
717
718         /* Get the AML resource template, converted to internal resource structs */
719
720         status = acpi_get_current_resources(node, &resource_buffer);
721         if (ACPI_FAILURE(status)) {
722                 acpi_os_printf("AcpiGetCurrentResources failed: %s\n",
723                                acpi_format_exception(status));
724                 goto exit1;
725         }
726
727         /* Convert internal resource list to external AML resource template */
728
729         status = acpi_rs_create_aml_resources(&resource_buffer, &new_aml);
730         if (ACPI_FAILURE(status)) {
731                 acpi_os_printf("AcpiRsCreateAmlResources failed: %s\n",
732                                acpi_format_exception(status));
733                 goto exit2;
734         }
735
736         /* Compare original AML to the newly created AML resource list */
737
738         original_aml = return_buffer.pointer;
739
740         acpi_dm_compare_aml_resources(original_aml->buffer.pointer,
741                                       (acpi_rsdesc_size) original_aml->buffer.
742                                       length, new_aml.pointer,
743                                       (acpi_rsdesc_size) new_aml.length);
744
745         /* Cleanup and exit */
746
747         ACPI_FREE(new_aml.pointer);
748 exit2:
749         ACPI_FREE(resource_buffer.pointer);
750 exit1:
751         ACPI_FREE(return_buffer.pointer);
752         return (status);
753 }
754
755 /*******************************************************************************
756  *
757  * FUNCTION:    acpi_db_resource_callback
758  *
759  * PARAMETERS:  acpi_walk_resource_callback
760  *
761  * RETURN:      Status
762  *
763  * DESCRIPTION: Simple callback to exercise acpi_walk_resources and
764  *              acpi_walk_resource_buffer.
765  *
766  ******************************************************************************/
767
768 static acpi_status
769 acpi_db_resource_callback(struct acpi_resource *resource, void *context)
770 {
771
772         return (AE_OK);
773 }
774
775 /*******************************************************************************
776  *
777  * FUNCTION:    acpi_db_device_resources
778  *
779  * PARAMETERS:  acpi_walk_callback
780  *
781  * RETURN:      Status
782  *
783  * DESCRIPTION: Display the _PRT/_CRS/_PRS resources for a device object.
784  *
785  ******************************************************************************/
786
787 static acpi_status
788 acpi_db_device_resources(acpi_handle obj_handle,
789                          u32 nesting_level, void *context, void **return_value)
790 {
791         struct acpi_namespace_node *node;
792         struct acpi_namespace_node *prt_node = NULL;
793         struct acpi_namespace_node *crs_node = NULL;
794         struct acpi_namespace_node *prs_node = NULL;
795         struct acpi_namespace_node *aei_node = NULL;
796         char *parent_path;
797         struct acpi_buffer return_buffer;
798         acpi_status status;
799
800         node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
801         parent_path = acpi_ns_get_external_pathname(node);
802         if (!parent_path) {
803                 return (AE_NO_MEMORY);
804         }
805
806         /* Get handles to the resource methods for this device */
807
808         (void)acpi_get_handle(node, METHOD_NAME__PRT,
809                               ACPI_CAST_PTR(acpi_handle, &prt_node));
810         (void)acpi_get_handle(node, METHOD_NAME__CRS,
811                               ACPI_CAST_PTR(acpi_handle, &crs_node));
812         (void)acpi_get_handle(node, METHOD_NAME__PRS,
813                               ACPI_CAST_PTR(acpi_handle, &prs_node));
814         (void)acpi_get_handle(node, METHOD_NAME__AEI,
815                               ACPI_CAST_PTR(acpi_handle, &aei_node));
816
817         if (!prt_node && !crs_node && !prs_node && !aei_node) {
818                 goto cleanup;   /* Nothing to do */
819         }
820
821         acpi_os_printf("\nDevice: %s\n", parent_path);
822
823         /* Prepare for a return object of arbitrary size */
824
825         return_buffer.pointer = acpi_gbl_db_buffer;
826         return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
827
828         /* _PRT */
829
830         if (prt_node) {
831                 acpi_os_printf("Evaluating _PRT\n");
832
833                 status =
834                     acpi_evaluate_object(prt_node, NULL, NULL, &return_buffer);
835                 if (ACPI_FAILURE(status)) {
836                         acpi_os_printf("Could not evaluate _PRT: %s\n",
837                                        acpi_format_exception(status));
838                         goto get_crs;
839                 }
840
841                 return_buffer.pointer = acpi_gbl_db_buffer;
842                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
843
844                 status = acpi_get_irq_routing_table(node, &return_buffer);
845                 if (ACPI_FAILURE(status)) {
846                         acpi_os_printf("GetIrqRoutingTable failed: %s\n",
847                                        acpi_format_exception(status));
848                         goto get_crs;
849                 }
850
851                 acpi_rs_dump_irq_list(ACPI_CAST_PTR(u8, acpi_gbl_db_buffer));
852         }
853
854         /* _CRS */
855
856 get_crs:
857         if (crs_node) {
858                 acpi_os_printf("Evaluating _CRS\n");
859
860                 return_buffer.pointer = acpi_gbl_db_buffer;
861                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
862
863                 status =
864                     acpi_evaluate_object(crs_node, NULL, NULL, &return_buffer);
865                 if (ACPI_FAILURE(status)) {
866                         acpi_os_printf("Could not evaluate _CRS: %s\n",
867                                        acpi_format_exception(status));
868                         goto get_prs;
869                 }
870
871                 /* This code exercises the acpi_walk_resources interface */
872
873                 status = acpi_walk_resources(node, METHOD_NAME__CRS,
874                                              acpi_db_resource_callback, NULL);
875                 if (ACPI_FAILURE(status)) {
876                         acpi_os_printf("AcpiWalkResources failed: %s\n",
877                                        acpi_format_exception(status));
878                         goto get_prs;
879                 }
880
881                 /* Get the _CRS resource list (test ALLOCATE buffer) */
882
883                 return_buffer.pointer = NULL;
884                 return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
885
886                 status = acpi_get_current_resources(node, &return_buffer);
887                 if (ACPI_FAILURE(status)) {
888                         acpi_os_printf("AcpiGetCurrentResources failed: %s\n",
889                                        acpi_format_exception(status));
890                         goto get_prs;
891                 }
892
893                 /* This code exercises the acpi_walk_resource_buffer interface */
894
895                 status = acpi_walk_resource_buffer(&return_buffer,
896                                                    acpi_db_resource_callback,
897                                                    NULL);
898                 if (ACPI_FAILURE(status)) {
899                         acpi_os_printf("AcpiWalkResourceBuffer failed: %s\n",
900                                        acpi_format_exception(status));
901                         goto end_crs;
902                 }
903
904                 /* Dump the _CRS resource list */
905
906                 acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource,
907                                                          return_buffer.
908                                                          pointer));
909
910                 /*
911                  * Perform comparison of original AML to newly created AML. This
912                  * tests both the AML->Resource conversion and the Resource->AML
913                  * conversion.
914                  */
915                 (void)acpi_dm_test_resource_conversion(node, METHOD_NAME__CRS);
916
917                 /* Execute _SRS with the resource list */
918
919                 acpi_os_printf("Evaluating _SRS\n");
920
921                 status = acpi_set_current_resources(node, &return_buffer);
922                 if (ACPI_FAILURE(status)) {
923                         acpi_os_printf("AcpiSetCurrentResources failed: %s\n",
924                                        acpi_format_exception(status));
925                         goto end_crs;
926                 }
927
928 end_crs:
929                 ACPI_FREE(return_buffer.pointer);
930         }
931
932         /* _PRS */
933
934 get_prs:
935         if (prs_node) {
936                 acpi_os_printf("Evaluating _PRS\n");
937
938                 return_buffer.pointer = acpi_gbl_db_buffer;
939                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
940
941                 status =
942                     acpi_evaluate_object(prs_node, NULL, NULL, &return_buffer);
943                 if (ACPI_FAILURE(status)) {
944                         acpi_os_printf("Could not evaluate _PRS: %s\n",
945                                        acpi_format_exception(status));
946                         goto get_aei;
947                 }
948
949                 return_buffer.pointer = acpi_gbl_db_buffer;
950                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
951
952                 status = acpi_get_possible_resources(node, &return_buffer);
953                 if (ACPI_FAILURE(status)) {
954                         acpi_os_printf("AcpiGetPossibleResources failed: %s\n",
955                                        acpi_format_exception(status));
956                         goto get_aei;
957                 }
958
959                 acpi_rs_dump_resource_list(ACPI_CAST_PTR
960                                            (struct acpi_resource,
961                                             acpi_gbl_db_buffer));
962         }
963
964         /* _AEI */
965
966 get_aei:
967         if (aei_node) {
968                 acpi_os_printf("Evaluating _AEI\n");
969
970                 return_buffer.pointer = acpi_gbl_db_buffer;
971                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
972
973                 status =
974                     acpi_evaluate_object(aei_node, NULL, NULL, &return_buffer);
975                 if (ACPI_FAILURE(status)) {
976                         acpi_os_printf("Could not evaluate _AEI: %s\n",
977                                        acpi_format_exception(status));
978                         goto cleanup;
979                 }
980
981                 return_buffer.pointer = acpi_gbl_db_buffer;
982                 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
983
984                 status = acpi_get_event_resources(node, &return_buffer);
985                 if (ACPI_FAILURE(status)) {
986                         acpi_os_printf("AcpiGetEventResources failed: %s\n",
987                                        acpi_format_exception(status));
988                         goto cleanup;
989                 }
990
991                 acpi_rs_dump_resource_list(ACPI_CAST_PTR
992                                            (struct acpi_resource,
993                                             acpi_gbl_db_buffer));
994         }
995
996 cleanup:
997         ACPI_FREE(parent_path);
998         return (AE_OK);
999 }
1000
1001 /*******************************************************************************
1002  *
1003  * FUNCTION:    acpi_db_display_resources
1004  *
1005  * PARAMETERS:  object_arg          - String object name or object pointer.
1006  *                                    NULL or "*" means "display resources for
1007  *                                    all devices"
1008  *
1009  * RETURN:      None
1010  *
1011  * DESCRIPTION: Display the resource objects associated with a device.
1012  *
1013  ******************************************************************************/
1014
1015 void acpi_db_display_resources(char *object_arg)
1016 {
1017         struct acpi_namespace_node *node;
1018
1019         acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
1020         acpi_dbg_level |= ACPI_LV_RESOURCES;
1021
1022         /* Asterisk means "display resources for all devices" */
1023
1024         if (!object_arg || (!strcmp(object_arg, "*"))) {
1025                 (void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1026                                           ACPI_UINT32_MAX,
1027                                           acpi_db_device_resources, NULL, NULL,
1028                                           NULL);
1029         } else {
1030                 /* Convert string to object pointer */
1031
1032                 node = acpi_db_convert_to_node(object_arg);
1033                 if (node) {
1034                         if (node->type != ACPI_TYPE_DEVICE) {
1035                                 acpi_os_printf
1036                                     ("%4.4s: Name is not a device object (%s)\n",
1037                                      node->name.ascii,
1038                                      acpi_ut_get_type_name(node->type));
1039                         } else {
1040                                 (void)acpi_db_device_resources(node, 0, NULL,
1041                                                                NULL);
1042                         }
1043                 }
1044         }
1045
1046         acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
1047 }
1048
1049 #if (!ACPI_REDUCED_HARDWARE)
1050 /*******************************************************************************
1051  *
1052  * FUNCTION:    acpi_db_generate_gpe
1053  *
1054  * PARAMETERS:  gpe_arg             - Raw GPE number, ascii string
1055  *              block_arg           - GPE block number, ascii string
1056  *                                    0 or 1 for FADT GPE blocks
1057  *
1058  * RETURN:      None
1059  *
1060  * DESCRIPTION: Simulate firing of a GPE
1061  *
1062  ******************************************************************************/
1063
1064 void acpi_db_generate_gpe(char *gpe_arg, char *block_arg)
1065 {
1066         u32 block_number = 0;
1067         u32 gpe_number;
1068         struct acpi_gpe_event_info *gpe_event_info;
1069
1070         gpe_number = strtoul(gpe_arg, NULL, 0);
1071
1072         /*
1073          * If no block arg, or block arg == 0 or 1, use the FADT-defined
1074          * GPE blocks.
1075          */
1076         if (block_arg) {
1077                 block_number = strtoul(block_arg, NULL, 0);
1078                 if (block_number == 1) {
1079                         block_number = 0;
1080                 }
1081         }
1082
1083         gpe_event_info =
1084             acpi_ev_get_gpe_event_info(ACPI_TO_POINTER(block_number),
1085                                        gpe_number);
1086         if (!gpe_event_info) {
1087                 acpi_os_printf("Invalid GPE\n");
1088                 return;
1089         }
1090
1091         (void)acpi_ev_gpe_dispatch(NULL, gpe_event_info, gpe_number);
1092 }
1093
1094 /*******************************************************************************
1095  *
1096  * FUNCTION:    acpi_db_generate_sci
1097  *
1098  * PARAMETERS:  None
1099  *
1100  * RETURN:      None
1101  *
1102  * DESCRIPTION: Simulate an SCI -- just call the SCI dispatch.
1103  *
1104  ******************************************************************************/
1105
1106 void acpi_db_generate_sci(void)
1107 {
1108         acpi_ev_sci_dispatch();
1109 }
1110
1111 #endif                          /* !ACPI_REDUCED_HARDWARE */
1112
1113 /*******************************************************************************
1114  *
1115  * FUNCTION:    acpi_db_trace
1116  *
1117  * PARAMETERS:  enable_arg          - ENABLE/AML to enable tracer
1118  *                                    DISABLE to disable tracer
1119  *              method_arg          - Method to trace
1120  *              once_arg            - Whether trace once
1121  *
1122  * RETURN:      None
1123  *
1124  * DESCRIPTION: Control method tracing facility
1125  *
1126  ******************************************************************************/
1127
1128 void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg)
1129 {
1130         u32 debug_level = 0;
1131         u32 debug_layer = 0;
1132         u32 flags = 0;
1133
1134         if (enable_arg) {
1135                 acpi_ut_strupr(enable_arg);
1136         }
1137
1138         if (once_arg) {
1139                 acpi_ut_strupr(once_arg);
1140         }
1141
1142         if (method_arg) {
1143                 if (acpi_db_trace_method_name) {
1144                         ACPI_FREE(acpi_db_trace_method_name);
1145                         acpi_db_trace_method_name = NULL;
1146                 }
1147
1148                 acpi_db_trace_method_name =
1149                     ACPI_ALLOCATE(strlen(method_arg) + 1);
1150                 if (!acpi_db_trace_method_name) {
1151                         acpi_os_printf("Failed to allocate method name (%s)\n",
1152                                        method_arg);
1153                         return;
1154                 }
1155
1156                 strcpy(acpi_db_trace_method_name, method_arg);
1157         }
1158
1159         if (!strcmp(enable_arg, "ENABLE") ||
1160             !strcmp(enable_arg, "METHOD") || !strcmp(enable_arg, "OPCODE")) {
1161                 if (!strcmp(enable_arg, "ENABLE")) {
1162
1163                         /* Inherit current console settings */
1164
1165                         debug_level = acpi_gbl_db_console_debug_level;
1166                         debug_layer = acpi_dbg_layer;
1167                 } else {
1168                         /* Restrict console output to trace points only */
1169
1170                         debug_level = ACPI_LV_TRACE_POINT;
1171                         debug_layer = ACPI_EXECUTER;
1172                 }
1173
1174                 flags = ACPI_TRACE_ENABLED;
1175
1176                 if (!strcmp(enable_arg, "OPCODE")) {
1177                         flags |= ACPI_TRACE_OPCODE;
1178                 }
1179
1180                 if (once_arg && !strcmp(once_arg, "ONCE")) {
1181                         flags |= ACPI_TRACE_ONESHOT;
1182                 }
1183         }
1184
1185         (void)acpi_debug_trace(acpi_db_trace_method_name,
1186                                debug_level, debug_layer, flags);
1187 }