1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2024 Google LLC
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6 
7 #include <bloblist.h>
8 #include <bootstage.h>
9 #include <command.h>
10 #include <display_options.h>
11 #include <lmb.h>
12 #include <malloc.h>
13 #include <mapmem.h>
14 #include <asm/global_data.h>
15 
16 DECLARE_GLOBAL_DATA_PTR;
17 
arch_dump_mem_attrs(void)18 void __weak arch_dump_mem_attrs(void)
19 {
20 }
21 
print_region(const char * name,ulong base,ulong size,ulong * uptop)22 static void print_region(const char *name, ulong base, ulong size, ulong *uptop)
23 {
24 	ulong end = base + size;
25 
26 	printf("%-12s %8lx %8lx %8lx", name, base, size, end);
27 	if (*uptop)
28 		printf(" %8lx", *uptop - end);
29 	putc('\n');
30 	*uptop = base;
31 }
32 
show_lmb(const struct lmb * lmb,ulong * uptop)33 static void show_lmb(const struct lmb *lmb, ulong *uptop)
34 {
35 	int i;
36 
37 	for (i = lmb->used_mem.count - 1; i >= 0; i--) {
38 		const struct lmb_region *rgn = alist_get(&lmb->used_mem, i,
39 							 struct lmb_region);
40 
41 		/*
42 		 * Assume that the top lmb region is the U-Boot region, so just
43 		 * take account of the memory not already reported
44 		 */
45 		if (lmb->used_mem.count - 1)
46 			print_region("lmb", rgn->base, *uptop - rgn->base,
47 				     uptop);
48 		else
49 			print_region("lmb", rgn->base, rgn->size, uptop);
50 		*uptop = rgn->base;
51 	}
52 }
53 
do_meminfo(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])54 static int do_meminfo(struct cmd_tbl *cmdtp, int flag, int argc,
55 		      char *const argv[])
56 {
57 	ulong upto, stk_bot;
58 
59 	puts("DRAM:  ");
60 	print_size(gd->ram_size, "\n");
61 
62 	if (!IS_ENABLED(CONFIG_CMD_MEMINFO_MAP))
63 		return 0;
64 
65 	arch_dump_mem_attrs();
66 
67 	printf("\n%-12s %8s %8s %8s %8s\n", "Region", "Base", "Size", "End",
68 	       "Gap");
69 	printf("------------------------------------------------\n");
70 	upto = 0;
71 	if (IS_ENABLED(CONFIG_VIDEO))
72 		print_region("video", gd_video_bottom(),
73 			     gd_video_size(), &upto);
74 	if (IS_ENABLED(CONFIG_TRACE))
75 		print_region("trace", map_to_sysmem(gd_trace_buff()),
76 			     gd_trace_size(), &upto);
77 	print_region("code", gd->relocaddr, gd->mon_len, &upto);
78 	print_region("malloc", map_to_sysmem((void *)mem_malloc_start),
79 		     mem_malloc_end - mem_malloc_start, &upto);
80 	print_region("board_info", map_to_sysmem(gd->bd),
81 		     sizeof(struct bd_info), &upto);
82 	print_region("global_data", map_to_sysmem((void *)gd),
83 		     sizeof(struct global_data), &upto);
84 	print_region("devicetree", map_to_sysmem(gd->fdt_blob),
85 		     fdt_totalsize(gd->fdt_blob), &upto);
86 	if (IS_ENABLED(CONFIG_BOOTSTAGE))
87 		print_region("bootstage", map_to_sysmem(gd_bootstage()),
88 			     bootstage_get_size(false), &upto);
89 	if (IS_ENABLED(CONFIG_BLOBLIST))
90 		print_region("bloblist", map_to_sysmem(gd_bloblist()),
91 			     bloblist_get_total_size(), &upto);
92 	stk_bot = gd->start_addr_sp - CONFIG_STACK_SIZE;
93 	print_region("stack", stk_bot, CONFIG_STACK_SIZE, &upto);
94 	if (IS_ENABLED(CONFIG_LMB))
95 		show_lmb(lmb_get(), &upto);
96 	print_region("free", gd->ram_base, upto - gd->ram_base, &upto);
97 
98 	return 0;
99 }
100 
101 U_BOOT_CMD(
102 	meminfo,	1,	1,	do_meminfo,
103 	"display memory information",
104 	""
105 );
106