1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: nsdump - table dumping routines for debug
5  *
6  * Copyright (C) 2000 - 2023, Intel Corp.
7  *
8  *****************************************************************************/
9 
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acnamesp.h"
13 #include <acpi/acoutput.h>
14 
15 #define _COMPONENT          ACPI_NAMESPACE
16 ACPI_MODULE_NAME("nsdump")
17 
18 /* Local prototypes */
19 #ifdef ACPI_OBSOLETE_FUNCTIONS
20 void acpi_ns_dump_root_devices(void);
21 
22 static acpi_status
23 acpi_ns_dump_one_device(acpi_handle obj_handle,
24 			u32 level, void *context, void **return_value);
25 #endif
26 
27 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
28 
29 static acpi_status
30 acpi_ns_dump_one_object_path(acpi_handle obj_handle,
31 			     u32 level, void *context, void **return_value);
32 
33 static acpi_status
34 acpi_ns_get_max_depth(acpi_handle obj_handle,
35 		      u32 level, void *context, void **return_value);
36 
37 /*******************************************************************************
38  *
39  * FUNCTION:    acpi_ns_print_pathname
40  *
41  * PARAMETERS:  num_segments        - Number of ACPI name segments
42  *              pathname            - The compressed (internal) path
43  *
44  * RETURN:      None
45  *
46  * DESCRIPTION: Print an object's full namespace pathname
47  *
48  ******************************************************************************/
49 
acpi_ns_print_pathname(u32 num_segments,const char * pathname)50 void acpi_ns_print_pathname(u32 num_segments, const char *pathname)
51 {
52 	u32 i;
53 
54 	ACPI_FUNCTION_NAME(ns_print_pathname);
55 
56 	/* Check if debug output enabled */
57 
58 	if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_NAMES, ACPI_NAMESPACE)) {
59 		return;
60 	}
61 
62 	/* Print the entire name */
63 
64 	ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "["));
65 
66 	while (num_segments) {
67 		for (i = 0; i < 4; i++) {
68 			isprint((int)pathname[i]) ?
69 			    acpi_os_printf("%c", pathname[i]) :
70 			    acpi_os_printf("?");
71 		}
72 
73 		pathname += ACPI_NAMESEG_SIZE;
74 		num_segments--;
75 		if (num_segments) {
76 			acpi_os_printf(".");
77 		}
78 	}
79 
80 	acpi_os_printf("]\n");
81 }
82 
83 #ifdef ACPI_OBSOLETE_FUNCTIONS
84 /* Not used at this time, perhaps later */
85 
86 /*******************************************************************************
87  *
88  * FUNCTION:    acpi_ns_dump_pathname
89  *
90  * PARAMETERS:  handle              - Object
91  *              msg                 - Prefix message
92  *              level               - Desired debug level
93  *              component           - Caller's component ID
94  *
95  * RETURN:      None
96  *
97  * DESCRIPTION: Print an object's full namespace pathname
98  *              Manages allocation/freeing of a pathname buffer
99  *
100  ******************************************************************************/
101 
102 void
acpi_ns_dump_pathname(acpi_handle handle,const char * msg,u32 level,u32 component)103 acpi_ns_dump_pathname(acpi_handle handle,
104 		      const char *msg, u32 level, u32 component)
105 {
106 
107 	ACPI_FUNCTION_TRACE(ns_dump_pathname);
108 
109 	/* Do this only if the requested debug level and component are enabled */
110 
111 	if (!ACPI_IS_DEBUG_ENABLED(level, component)) {
112 		return_VOID;
113 	}
114 
115 	/* Convert handle to a full pathname and print it (with supplied message) */
116 
117 	acpi_ns_print_node_pathname(handle, msg);
118 	acpi_os_printf("\n");
119 	return_VOID;
120 }
121 #endif
122 
123 /*******************************************************************************
124  *
125  * FUNCTION:    acpi_ns_dump_one_object
126  *
127  * PARAMETERS:  obj_handle          - Node to be dumped
128  *              level               - Nesting level of the handle
129  *              context             - Passed into walk_namespace
130  *              return_value        - Not used
131  *
132  * RETURN:      Status
133  *
134  * DESCRIPTION: Dump a single Node
135  *              This procedure is a user_function called by acpi_ns_walk_namespace.
136  *
137  ******************************************************************************/
138 
139 acpi_status
acpi_ns_dump_one_object(acpi_handle obj_handle,u32 level,void * context,void ** return_value)140 acpi_ns_dump_one_object(acpi_handle obj_handle,
141 			u32 level, void *context, void **return_value)
142 {
143 	struct acpi_walk_info *info = (struct acpi_walk_info *)context;
144 	struct acpi_namespace_node *this_node;
145 	union acpi_operand_object *obj_desc = NULL;
146 	acpi_object_type obj_type;
147 	acpi_object_type type;
148 	u32 bytes_to_dump;
149 	u32 dbg_level;
150 	u32 i;
151 
152 	ACPI_FUNCTION_NAME(ns_dump_one_object);
153 
154 	/* Is output enabled? */
155 
156 	if (!(acpi_dbg_level & info->debug_level)) {
157 		return (AE_OK);
158 	}
159 
160 	if (!obj_handle) {
161 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Null object handle\n"));
162 		return (AE_OK);
163 	}
164 
165 	this_node = acpi_ns_validate_handle(obj_handle);
166 	if (!this_node) {
167 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid object handle %p\n",
168 				  obj_handle));
169 		return (AE_OK);
170 	}
171 
172 	type = this_node->type;
173 	info->count++;
174 
175 	/* Check if the owner matches */
176 
177 	if ((info->owner_id != ACPI_OWNER_ID_MAX) &&
178 	    (info->owner_id != this_node->owner_id)) {
179 		return (AE_OK);
180 	}
181 
182 	if (!(info->display_type & ACPI_DISPLAY_SHORT)) {
183 
184 		/* Indent the object according to the level */
185 
186 		acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " ");
187 
188 		/* Check the node type and name */
189 
190 		if (type > ACPI_TYPE_LOCAL_MAX) {
191 			ACPI_WARNING((AE_INFO,
192 				      "Invalid ACPI Object Type 0x%08X", type));
193 		}
194 
195 		acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
196 	}
197 
198 	/* Now we can print out the pertinent information */
199 
200 	acpi_os_printf(" %-12s %p %3.3X ",
201 		       acpi_ut_get_type_name(type), this_node,
202 		       this_node->owner_id);
203 
204 	dbg_level = acpi_dbg_level;
205 	acpi_dbg_level = 0;
206 	obj_desc = acpi_ns_get_attached_object(this_node);
207 	acpi_dbg_level = dbg_level;
208 
209 	/* Temp nodes are those nodes created by a control method */
210 
211 	if (this_node->flags & ANOBJ_TEMPORARY) {
212 		acpi_os_printf("(T) ");
213 	}
214 
215 	switch (info->display_type & ACPI_DISPLAY_MASK) {
216 	case ACPI_DISPLAY_SUMMARY:
217 
218 		if (!obj_desc) {
219 
220 			/* No attached object. Some types should always have an object */
221 
222 			switch (type) {
223 			case ACPI_TYPE_INTEGER:
224 			case ACPI_TYPE_PACKAGE:
225 			case ACPI_TYPE_BUFFER:
226 			case ACPI_TYPE_STRING:
227 			case ACPI_TYPE_METHOD:
228 
229 				acpi_os_printf("<No attached object>");
230 				break;
231 
232 			default:
233 
234 				break;
235 			}
236 
237 			acpi_os_printf("\n");
238 			return (AE_OK);
239 		}
240 
241 		switch (type) {
242 		case ACPI_TYPE_PROCESSOR:
243 
244 			acpi_os_printf("ID %02X Len %02X Addr %8.8X%8.8X\n",
245 				       obj_desc->processor.proc_id,
246 				       obj_desc->processor.length,
247 				       ACPI_FORMAT_UINT64(obj_desc->processor.
248 							  address));
249 			break;
250 
251 		case ACPI_TYPE_DEVICE:
252 
253 			acpi_os_printf("Notify Object: %p\n", obj_desc);
254 			break;
255 
256 		case ACPI_TYPE_METHOD:
257 
258 			acpi_os_printf("Args %X Len %.4X Aml %p\n",
259 				       (u32) obj_desc->method.param_count,
260 				       obj_desc->method.aml_length,
261 				       obj_desc->method.aml_start);
262 			break;
263 
264 		case ACPI_TYPE_INTEGER:
265 
266 			acpi_os_printf("= %8.8X%8.8X\n",
267 				       ACPI_FORMAT_UINT64(obj_desc->integer.
268 							  value));
269 			break;
270 
271 		case ACPI_TYPE_PACKAGE:
272 
273 			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
274 				acpi_os_printf("Elements %.2X\n",
275 					       obj_desc->package.count);
276 			} else {
277 				acpi_os_printf("[Length not yet evaluated]\n");
278 			}
279 			break;
280 
281 		case ACPI_TYPE_BUFFER:
282 
283 			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
284 				acpi_os_printf("Len %.2X",
285 					       obj_desc->buffer.length);
286 
287 				/* Dump some of the buffer */
288 
289 				if (obj_desc->buffer.length > 0) {
290 					acpi_os_printf(" =");
291 					for (i = 0;
292 					     (i < obj_desc->buffer.length
293 					      && i < 12); i++) {
294 						acpi_os_printf(" %2.2X",
295 							       obj_desc->buffer.
296 							       pointer[i]);
297 					}
298 				}
299 				acpi_os_printf("\n");
300 			} else {
301 				acpi_os_printf("[Length not yet evaluated]\n");
302 			}
303 			break;
304 
305 		case ACPI_TYPE_STRING:
306 
307 			acpi_os_printf("Len %.2X ", obj_desc->string.length);
308 			acpi_ut_print_string(obj_desc->string.pointer, 80);
309 			acpi_os_printf("\n");
310 			break;
311 
312 		case ACPI_TYPE_REGION:
313 
314 			acpi_os_printf("[%s]",
315 				       acpi_ut_get_region_name(obj_desc->region.
316 							       space_id));
317 			if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
318 				acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n",
319 					       ACPI_FORMAT_UINT64(obj_desc->
320 								  region.
321 								  address),
322 					       obj_desc->region.length);
323 			} else {
324 				acpi_os_printf
325 				    (" [Address/Length not yet evaluated]\n");
326 			}
327 			break;
328 
329 		case ACPI_TYPE_LOCAL_REFERENCE:
330 
331 			acpi_os_printf("[%s]\n",
332 				       acpi_ut_get_reference_name(obj_desc));
333 			break;
334 
335 		case ACPI_TYPE_BUFFER_FIELD:
336 
337 			if (obj_desc->buffer_field.buffer_obj &&
338 			    obj_desc->buffer_field.buffer_obj->buffer.node) {
339 				acpi_os_printf("Buf [%4.4s]",
340 					       acpi_ut_get_node_name(obj_desc->
341 								     buffer_field.
342 								     buffer_obj->
343 								     buffer.
344 								     node));
345 			}
346 			break;
347 
348 		case ACPI_TYPE_LOCAL_REGION_FIELD:
349 
350 			acpi_os_printf("Rgn [%4.4s]",
351 				       acpi_ut_get_node_name(obj_desc->
352 							     common_field.
353 							     region_obj->region.
354 							     node));
355 			break;
356 
357 		case ACPI_TYPE_LOCAL_BANK_FIELD:
358 
359 			acpi_os_printf("Rgn [%4.4s] Bnk [%4.4s]",
360 				       acpi_ut_get_node_name(obj_desc->
361 							     common_field.
362 							     region_obj->region.
363 							     node),
364 				       acpi_ut_get_node_name(obj_desc->
365 							     bank_field.
366 							     bank_obj->
367 							     common_field.
368 							     node));
369 			break;
370 
371 		case ACPI_TYPE_LOCAL_INDEX_FIELD:
372 
373 			acpi_os_printf("Idx [%4.4s] Dat [%4.4s]",
374 				       acpi_ut_get_node_name(obj_desc->
375 							     index_field.
376 							     index_obj->
377 							     common_field.node),
378 				       acpi_ut_get_node_name(obj_desc->
379 							     index_field.
380 							     data_obj->
381 							     common_field.
382 							     node));
383 			break;
384 
385 		case ACPI_TYPE_LOCAL_ALIAS:
386 		case ACPI_TYPE_LOCAL_METHOD_ALIAS:
387 
388 			acpi_os_printf("Target %4.4s (%p)\n",
389 				       acpi_ut_get_node_name(obj_desc),
390 				       obj_desc);
391 			break;
392 
393 		default:
394 
395 			acpi_os_printf("Object %p\n", obj_desc);
396 			break;
397 		}
398 
399 		/* Common field handling */
400 
401 		switch (type) {
402 		case ACPI_TYPE_BUFFER_FIELD:
403 		case ACPI_TYPE_LOCAL_REGION_FIELD:
404 		case ACPI_TYPE_LOCAL_BANK_FIELD:
405 		case ACPI_TYPE_LOCAL_INDEX_FIELD:
406 
407 			acpi_os_printf(" Off %.3X Len %.2X Acc %.2X\n",
408 				       (obj_desc->common_field.
409 					base_byte_offset * 8)
410 				       +
411 				       obj_desc->common_field.
412 				       start_field_bit_offset,
413 				       obj_desc->common_field.bit_length,
414 				       obj_desc->common_field.
415 				       access_byte_width);
416 			break;
417 
418 		default:
419 
420 			break;
421 		}
422 		break;
423 
424 	case ACPI_DISPLAY_OBJECTS:
425 
426 		acpi_os_printf("O:%p", obj_desc);
427 		if (!obj_desc) {
428 
429 			/* No attached object, we are done */
430 
431 			acpi_os_printf("\n");
432 			return (AE_OK);
433 		}
434 
435 		acpi_os_printf("(R%u)", obj_desc->common.reference_count);
436 
437 		switch (type) {
438 		case ACPI_TYPE_METHOD:
439 
440 			/* Name is a Method and its AML offset/length are set */
441 
442 			acpi_os_printf(" M:%p-%X\n", obj_desc->method.aml_start,
443 				       obj_desc->method.aml_length);
444 			break;
445 
446 		case ACPI_TYPE_INTEGER:
447 
448 			acpi_os_printf(" I:%8.8X8.8%X\n",
449 				       ACPI_FORMAT_UINT64(obj_desc->integer.
450 							  value));
451 			break;
452 
453 		case ACPI_TYPE_STRING:
454 
455 			acpi_os_printf(" S:%p-%X\n", obj_desc->string.pointer,
456 				       obj_desc->string.length);
457 			break;
458 
459 		case ACPI_TYPE_BUFFER:
460 
461 			acpi_os_printf(" B:%p-%X\n", obj_desc->buffer.pointer,
462 				       obj_desc->buffer.length);
463 			break;
464 
465 		default:
466 
467 			acpi_os_printf("\n");
468 			break;
469 		}
470 		break;
471 
472 	default:
473 		acpi_os_printf("\n");
474 		break;
475 	}
476 
477 	/* If debug turned off, done */
478 
479 	if (!(acpi_dbg_level & ACPI_LV_VALUES)) {
480 		return (AE_OK);
481 	}
482 
483 	/* If there is an attached object, display it */
484 
485 	dbg_level = acpi_dbg_level;
486 	acpi_dbg_level = 0;
487 	obj_desc = acpi_ns_get_attached_object(this_node);
488 	acpi_dbg_level = dbg_level;
489 
490 	/* Dump attached objects */
491 
492 	while (obj_desc) {
493 		obj_type = ACPI_TYPE_INVALID;
494 		acpi_os_printf("Attached Object %p: ", obj_desc);
495 
496 		/* Decode the type of attached object and dump the contents */
497 
498 		switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
499 		case ACPI_DESC_TYPE_NAMED:
500 
501 			acpi_os_printf("(Ptr to Node)\n");
502 			bytes_to_dump = sizeof(struct acpi_namespace_node);
503 			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
504 			break;
505 
506 		case ACPI_DESC_TYPE_OPERAND:
507 
508 			obj_type = obj_desc->common.type;
509 
510 			if (obj_type > ACPI_TYPE_LOCAL_MAX) {
511 				acpi_os_printf
512 				    ("(Pointer to ACPI Object type %.2X [UNKNOWN])\n",
513 				     obj_type);
514 
515 				bytes_to_dump = 32;
516 			} else {
517 				acpi_os_printf
518 				    ("(Pointer to ACPI Object type %.2X [%s])\n",
519 				     obj_type, acpi_ut_get_type_name(obj_type));
520 
521 				bytes_to_dump =
522 				    sizeof(union acpi_operand_object);
523 			}
524 
525 			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
526 			break;
527 
528 		default:
529 
530 			break;
531 		}
532 
533 		/* If value is NOT an internal object, we are done */
534 
535 		if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) !=
536 		    ACPI_DESC_TYPE_OPERAND) {
537 			goto cleanup;
538 		}
539 
540 		/* Valid object, get the pointer to next level, if any */
541 
542 		switch (obj_type) {
543 		case ACPI_TYPE_BUFFER:
544 		case ACPI_TYPE_STRING:
545 			/*
546 			 * NOTE: takes advantage of common fields between string/buffer
547 			 */
548 			bytes_to_dump = obj_desc->string.length;
549 			obj_desc = (void *)obj_desc->string.pointer;
550 
551 			acpi_os_printf("(Buffer/String pointer %p length %X)\n",
552 				       obj_desc, bytes_to_dump);
553 			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
554 			goto cleanup;
555 
556 		case ACPI_TYPE_BUFFER_FIELD:
557 
558 			obj_desc =
559 			    (union acpi_operand_object *)obj_desc->buffer_field.
560 			    buffer_obj;
561 			break;
562 
563 		case ACPI_TYPE_PACKAGE:
564 
565 			obj_desc = (void *)obj_desc->package.elements;
566 			break;
567 
568 		case ACPI_TYPE_METHOD:
569 
570 			obj_desc = (void *)obj_desc->method.aml_start;
571 			break;
572 
573 		case ACPI_TYPE_LOCAL_REGION_FIELD:
574 
575 			obj_desc = (void *)obj_desc->field.region_obj;
576 			break;
577 
578 		case ACPI_TYPE_LOCAL_BANK_FIELD:
579 
580 			obj_desc = (void *)obj_desc->bank_field.region_obj;
581 			break;
582 
583 		case ACPI_TYPE_LOCAL_INDEX_FIELD:
584 
585 			obj_desc = (void *)obj_desc->index_field.index_obj;
586 			break;
587 
588 		default:
589 
590 			goto cleanup;
591 		}
592 	}
593 
594 cleanup:
595 	acpi_os_printf("\n");
596 	return (AE_OK);
597 }
598 
599 /*******************************************************************************
600  *
601  * FUNCTION:    acpi_ns_dump_objects
602  *
603  * PARAMETERS:  type                - Object type to be dumped
604  *              display_type        - 0 or ACPI_DISPLAY_SUMMARY
605  *              max_depth           - Maximum depth of dump. Use ACPI_UINT32_MAX
606  *                                    for an effectively unlimited depth.
607  *              owner_id            - Dump only objects owned by this ID. Use
608  *                                    ACPI_UINT32_MAX to match all owners.
609  *              start_handle        - Where in namespace to start/end search
610  *
611  * RETURN:      None
612  *
613  * DESCRIPTION: Dump typed objects within the loaded namespace. Uses
614  *              acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object.
615  *
616  ******************************************************************************/
617 
618 void
acpi_ns_dump_objects(acpi_object_type type,u8 display_type,u32 max_depth,acpi_owner_id owner_id,acpi_handle start_handle)619 acpi_ns_dump_objects(acpi_object_type type,
620 		     u8 display_type,
621 		     u32 max_depth,
622 		     acpi_owner_id owner_id, acpi_handle start_handle)
623 {
624 	struct acpi_walk_info info;
625 	acpi_status status;
626 
627 	ACPI_FUNCTION_ENTRY();
628 
629 	/*
630 	 * Just lock the entire namespace for the duration of the dump.
631 	 * We don't want any changes to the namespace during this time,
632 	 * especially the temporary nodes since we are going to display
633 	 * them also.
634 	 */
635 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
636 	if (ACPI_FAILURE(status)) {
637 		acpi_os_printf("Could not acquire namespace mutex\n");
638 		return;
639 	}
640 
641 	info.count = 0;
642 	info.debug_level = ACPI_LV_TABLES;
643 	info.owner_id = owner_id;
644 	info.display_type = display_type;
645 
646 	(void)acpi_ns_walk_namespace(type, start_handle, max_depth,
647 				     ACPI_NS_WALK_NO_UNLOCK |
648 				     ACPI_NS_WALK_TEMP_NODES,
649 				     acpi_ns_dump_one_object, NULL,
650 				     (void *)&info, NULL);
651 
652 	acpi_os_printf("\nNamespace node count: %u\n\n", info.count);
653 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
654 }
655 
656 /*******************************************************************************
657  *
658  * FUNCTION:    acpi_ns_dump_one_object_path, acpi_ns_get_max_depth
659  *
660  * PARAMETERS:  obj_handle          - Node to be dumped
661  *              level               - Nesting level of the handle
662  *              context             - Passed into walk_namespace
663  *              return_value        - Not used
664  *
665  * RETURN:      Status
666  *
667  * DESCRIPTION: Dump the full pathname to a namespace object. acp_ns_get_max_depth
668  *              computes the maximum nesting depth in the namespace tree, in
669  *              order to simplify formatting in acpi_ns_dump_one_object_path.
670  *              These procedures are user_functions called by acpi_ns_walk_namespace.
671  *
672  ******************************************************************************/
673 
674 static acpi_status
acpi_ns_dump_one_object_path(acpi_handle obj_handle,u32 level,void * context,void ** return_value)675 acpi_ns_dump_one_object_path(acpi_handle obj_handle,
676 			     u32 level, void *context, void **return_value)
677 {
678 	u32 max_level = *((u32 *)context);
679 	char *pathname;
680 	struct acpi_namespace_node *node;
681 	int path_indent;
682 
683 	if (!obj_handle) {
684 		return (AE_OK);
685 	}
686 
687 	node = acpi_ns_validate_handle(obj_handle);
688 	if (!node) {
689 
690 		/* Ignore bad node during namespace walk */
691 
692 		return (AE_OK);
693 	}
694 
695 	pathname = acpi_ns_get_normalized_pathname(node, TRUE);
696 
697 	path_indent = 1;
698 	if (level <= max_level) {
699 		path_indent = max_level - level + 1;
700 	}
701 
702 	acpi_os_printf("%2d%*s%-12s%*s",
703 		       level, level, " ", acpi_ut_get_type_name(node->type),
704 		       path_indent, " ");
705 
706 	acpi_os_printf("%s\n", &pathname[1]);
707 	ACPI_FREE(pathname);
708 	return (AE_OK);
709 }
710 
711 static acpi_status
acpi_ns_get_max_depth(acpi_handle obj_handle,u32 level,void * context,void ** return_value)712 acpi_ns_get_max_depth(acpi_handle obj_handle,
713 		      u32 level, void *context, void **return_value)
714 {
715 	u32 *max_level = (u32 *)context;
716 
717 	if (level > *max_level) {
718 		*max_level = level;
719 	}
720 	return (AE_OK);
721 }
722 
723 /*******************************************************************************
724  *
725  * FUNCTION:    acpi_ns_dump_object_paths
726  *
727  * PARAMETERS:  type                - Object type to be dumped
728  *              display_type        - 0 or ACPI_DISPLAY_SUMMARY
729  *              max_depth           - Maximum depth of dump. Use ACPI_UINT32_MAX
730  *                                    for an effectively unlimited depth.
731  *              owner_id            - Dump only objects owned by this ID. Use
732  *                                    ACPI_UINT32_MAX to match all owners.
733  *              start_handle        - Where in namespace to start/end search
734  *
735  * RETURN:      None
736  *
737  * DESCRIPTION: Dump full object pathnames within the loaded namespace. Uses
738  *              acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object_path.
739  *
740  ******************************************************************************/
741 
742 void
acpi_ns_dump_object_paths(acpi_object_type type,u8 display_type,u32 max_depth,acpi_owner_id owner_id,acpi_handle start_handle)743 acpi_ns_dump_object_paths(acpi_object_type type,
744 			  u8 display_type,
745 			  u32 max_depth,
746 			  acpi_owner_id owner_id, acpi_handle start_handle)
747 {
748 	acpi_status status;
749 	u32 max_level = 0;
750 
751 	ACPI_FUNCTION_ENTRY();
752 
753 	/*
754 	 * Just lock the entire namespace for the duration of the dump.
755 	 * We don't want any changes to the namespace during this time,
756 	 * especially the temporary nodes since we are going to display
757 	 * them also.
758 	 */
759 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
760 	if (ACPI_FAILURE(status)) {
761 		acpi_os_printf("Could not acquire namespace mutex\n");
762 		return;
763 	}
764 
765 	/* Get the max depth of the namespace tree, for formatting later */
766 
767 	(void)acpi_ns_walk_namespace(type, start_handle, max_depth,
768 				     ACPI_NS_WALK_NO_UNLOCK |
769 				     ACPI_NS_WALK_TEMP_NODES,
770 				     acpi_ns_get_max_depth, NULL,
771 				     (void *)&max_level, NULL);
772 
773 	/* Now dump the entire namespace */
774 
775 	(void)acpi_ns_walk_namespace(type, start_handle, max_depth,
776 				     ACPI_NS_WALK_NO_UNLOCK |
777 				     ACPI_NS_WALK_TEMP_NODES,
778 				     acpi_ns_dump_one_object_path, NULL,
779 				     (void *)&max_level, NULL);
780 
781 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
782 }
783 
784 /*******************************************************************************
785  *
786  * FUNCTION:    acpi_ns_dump_entry
787  *
788  * PARAMETERS:  handle              - Node to be dumped
789  *              debug_level         - Output level
790  *
791  * RETURN:      None
792  *
793  * DESCRIPTION: Dump a single Node
794  *
795  ******************************************************************************/
796 
acpi_ns_dump_entry(acpi_handle handle,u32 debug_level)797 void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level)
798 {
799 	struct acpi_walk_info info;
800 
801 	ACPI_FUNCTION_ENTRY();
802 
803 	info.debug_level = debug_level;
804 	info.owner_id = ACPI_OWNER_ID_MAX;
805 	info.display_type = ACPI_DISPLAY_SUMMARY;
806 
807 	(void)acpi_ns_dump_one_object(handle, 1, &info, NULL);
808 }
809 
810 #ifdef ACPI_ASL_COMPILER
811 /*******************************************************************************
812  *
813  * FUNCTION:    acpi_ns_dump_tables
814  *
815  * PARAMETERS:  search_base         - Root of subtree to be dumped, or
816  *                                    NS_ALL to dump the entire namespace
817  *              max_depth           - Maximum depth of dump. Use INT_MAX
818  *                                    for an effectively unlimited depth.
819  *
820  * RETURN:      None
821  *
822  * DESCRIPTION: Dump the name space, or a portion of it.
823  *
824  ******************************************************************************/
825 
acpi_ns_dump_tables(acpi_handle search_base,u32 max_depth)826 void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth)
827 {
828 	acpi_handle search_handle = search_base;
829 
830 	ACPI_FUNCTION_TRACE(ns_dump_tables);
831 
832 	if (!acpi_gbl_root_node) {
833 		/*
834 		 * If the name space has not been initialized,
835 		 * there is nothing to dump.
836 		 */
837 		ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
838 				  "namespace not initialized!\n"));
839 		return_VOID;
840 	}
841 
842 	if (ACPI_NS_ALL == search_base) {
843 
844 		/* Entire namespace */
845 
846 		search_handle = acpi_gbl_root_node;
847 		ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "\\\n"));
848 	}
849 
850 	acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, max_depth,
851 			     ACPI_OWNER_ID_MAX, search_handle);
852 	return_VOID;
853 }
854 #endif
855 #endif
856