Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6595 serge 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 
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
}