cmd: Update the meminfo command to show the memory map

U-Boot has a fairly rigid memory map which is normally not visible
unless debugging is enabled in board_f.c

Update the 'meminfo' command to show it. This command does not cover
arch-specific pieces but gives a good overview of where things are.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2024-10-21 10:19:30 +02:00 committed by Tom Rini
parent 8306c3b035
commit f18c048e6e
6 changed files with 231 additions and 3 deletions

View file

@ -889,6 +889,17 @@ config CMD_MEMINFO
help help
Display memory information. Display memory information.
config CMD_MEMINFO_MAP
bool "- with memory map"
depends on CMD_MEMINFO
default y if SANDBOX
help
Shows a memory map, in addition to just the DRAM size. This allows
seeing where U-Boot's memory area is, at the top of DRAM, as well as
detail about each piece of it.
See doc/usage/cmd/meminfo.rst for more information.
config CMD_MEMORY config CMD_MEMORY
bool "md, mm, nm, mw, cp, cmp, base, loop" bool "md, mm, nm, mw, cp, cmp, base, loop"
default y default y

View file

@ -4,18 +4,67 @@
* Written by Simon Glass <sjg@chromium.org> * Written by Simon Glass <sjg@chromium.org>
*/ */
#include <bloblist.h>
#include <bootstage.h>
#include <command.h> #include <command.h>
#include <display_options.h> #include <display_options.h>
#include <malloc.h>
#include <mapmem.h>
#include <asm/global_data.h> #include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
static int do_meminfo(struct cmd_tbl *cmdtp, int flag, int argc, static void print_region(const char *name, ulong base, ulong size, ulong *uptop)
char *const argv[])
{ {
ulong end = base + size;
printf("%-12s %8lx %8lx %8lx", name, base, size, end);
if (*uptop)
printf(" %8lx", *uptop - end);
putc('\n');
*uptop = base;
}
static int do_meminfo(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
ulong upto, stk_bot;
puts("DRAM: "); puts("DRAM: ");
print_size(gd->ram_size, "\n"); print_size(gd->ram_size, "\n");
if (!IS_ENABLED(CONFIG_CMD_MEMINFO_MAP))
return 0;
printf("\n%-12s %8s %8s %8s %8s\n", "Region", "Base", "Size", "End",
"Gap");
printf("------------------------------------------------\n");
upto = 0;
if (IS_ENABLED(CONFIG_VIDEO))
print_region("video", gd_video_bottom(),
gd_video_size(), &upto);
if (IS_ENABLED(CONFIG_TRACE))
print_region("trace", map_to_sysmem(gd_trace_buff()),
gd_trace_size(), &upto);
print_region("code", gd->relocaddr, gd->mon_len, &upto);
print_region("malloc", map_to_sysmem((void *)mem_malloc_start),
mem_malloc_end - mem_malloc_start, &upto);
print_region("board_info", map_to_sysmem(gd->bd),
sizeof(struct bd_info), &upto);
print_region("global_data", map_to_sysmem((void *)gd),
sizeof(struct global_data), &upto);
print_region("devicetree", map_to_sysmem(gd->fdt_blob),
fdt_totalsize(gd->fdt_blob), &upto);
if (IS_ENABLED(CONFIG_BOOTSTAGE))
print_region("bootstage", map_to_sysmem(gd_bootstage()),
bootstage_get_size(false), &upto);
if (IS_ENABLED(CONFIG_BLOBLIST))
print_region("bloblist", map_to_sysmem(gd_bloblist()),
bloblist_get_total_size(), &upto);
stk_bot = gd->start_addr_sp - CONFIG_STACK_SIZE;
print_region("stack", stk_bot, CONFIG_STACK_SIZE, &upto);
print_region("free", gd->ram_base, stk_bot, &upto);
return 0; return 0;
} }

128
doc/usage/cmd/meminfo.rst Normal file
View file

@ -0,0 +1,128 @@
.. SPDX-License-Identifier: GPL-2.0+:
.. index::
single: meminfo (command)
meminfo command
===============
Synopsis
--------
::
meminfo
Description
-----------
The meminfo command shows the amount of memory. If ``CONFIG_CMD_MEMINFO_MAP`` is
enabled, then it also shows the layout of memory used by U-Boot and the region
which is free for use by images.
The layout of memory is set up before relocation, within the init sequence in
``board_init_f()``, specifically the various ``reserve_...()`` functions. This
'reservation' of memory starts from the top of RAM and proceeds downwards,
ending with the stack. This results in the maximum possible amount of memory
being left free for image-loading.
The meminfo command writes the DRAM size, then the rest of its outputs in 5
columns:
Region
Name of the region
Base
Base address of the region, i.e. where it starts in memory
Size
Size of the region, which may be a little smaller than the actual size
reserved, e.g. due to alignment
End
End of the region. The last byte of the region is one lower than the address
shown here
Gap
Gap between the end of this region and the base of the one above
Regions shown are:
video
Memory reserved for video framebuffers. This reservation happens in the
bind() methods of all video drivers which are present before relocation,
so the size depends on that maximum amount of memory which all such drivers
want to reserve. This may be significantly greater than the amount actually
needed, if the display is ultimately set to a smaller resolution or colour
depth than the maximum supported.
code
U-Boot's code and Block-Starting Symbol (BSS) region. Before relocation,
U-Boot copies its code to a high region and sets up a BSS immediately after
that. The size of this region is generally therefore ``__bss_end`` -
``__image_copy_start``
malloc
Contains the malloc() heap. The size of this is set by
``CONFIG_SYS_MALLOC_LEN``.
board_info
Contains the ``bd_info`` structure, with some information about the current
board.
global_data
Contains the global-data structure, pointed to by ``gd``. This includes
various pointers, values and flags which control U-Boot.
devicetree
Contains the flatted devicetree blob (FDT) being used by U-Boot to configure
itself and its devices.
bootstage
Contains the bootstage records, which keep track of boot time as U-Boot
executes. The size of this is determined by
``CONFIG_BOOTSTAGE_RECORD_COUNT``, with each record taking approximately
32 bytes.
bloblist
Contains the bloblist, which is a list of tables and other data created by
U-Boot while executed. The size of this is determined by
``CONFIG_BLOBLIST_SIZE``.
stack
Contains U-Boot's stack, growing downwards from the top. The nominal size of
this region is set by ``CONFIG_STACK_SIZE`` but there is no actual limit
enforced, so the stack can grow behind that. Images should be loaded lower
in memory to avoid any conflict.
free
Free memory, which is available for loading images. The base address of
this is ``gd->ram_base`` which is generally set by ``CFG_SYS_SDRAM_BASE``.
Example
-------
This example shows output with both ``CONFIG_CMD_MEMINFO`` and
``CONFIG_CMD_MEMINFO_MAP`` enabled::
=> meminfo
DRAM: 256 MiB
Region Base Size End Gap
------------------------------------------------
video f000000 1000000 10000000
code ec3a000 3c5d28 efffd28 2d8
malloc 8c38000 6002000 ec3a000 0
board_info 8c37f90 68 8c37ff8 8
global_data 8c37d80 208 8c37f88 8
devicetree 8c33000 4d7d 8c37d7d 3
bootstage 8c32c20 3c8 8c32fe8 18
bloblist 8c32000 400 8c32400 820
stack 7c31ff0 1000000 8c31ff0 10
free 0 7c31ff0 7c31ff0 0
Return value
------------
The return value $? is always 0 (true).

View file

@ -84,6 +84,7 @@ Shell commands
cmd/loads cmd/loads
cmd/loadx cmd/loadx
cmd/loady cmd/loady
cmd/meminfo
cmd/mbr cmd/mbr
cmd/md cmd/md
cmd/mmc cmd/mmc

View file

@ -19,8 +19,9 @@ obj-$(CONFIG_CMD_FDT) += fdt.o
obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o
obj-$(CONFIG_CMD_HISTORY) += history.o obj-$(CONFIG_CMD_HISTORY) += history.o
obj-$(CONFIG_CMD_LOADM) += loadm.o obj-$(CONFIG_CMD_LOADM) += loadm.o
obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o obj-$(CONFIG_CMD_MEMINFO) += meminfo.o
obj-$(CONFIG_CMD_MEMORY) += mem_copy.o obj-$(CONFIG_CMD_MEMORY) += mem_copy.o
obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
ifdef CONFIG_CMD_PCI ifdef CONFIG_CMD_PCI
obj-$(CONFIG_CMD_PCI_MPS) += pci_mps.o obj-$(CONFIG_CMD_PCI_MPS) += pci_mps.o
endif endif

38
test/cmd/meminfo.c Normal file
View file

@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Test for 'meminfo' command
*
* Copyright 2024 Google LLC
* Written by Simon Glass <sjg@chromium.org>
*/
#include <dm/test.h>
#include <test/cmd.h>
#include <test/ut.h>
/* Test 'meminfo' command */
static int cmd_test_meminfo(struct unit_test_state *uts)
{
ut_assertok(run_command("meminfo", 0));
ut_assert_nextline("DRAM: 256 MiB");
ut_assert_nextline_empty();
ut_assert_nextline("Region Base Size End Gap");
ut_assert_nextlinen("-");
/* For now we don't worry about checking the values */
ut_assert_nextlinen("video");
ut_assert_nextlinen("code");
ut_assert_nextlinen("malloc");
ut_assert_nextlinen("board_info");
ut_assert_nextlinen("global_data");
ut_assert_nextlinen("devicetree");
ut_assert_nextlinen("bootstage");
ut_assert_nextlinen("bloblist");
ut_assert_nextlinen("stack");
ut_assert_nextlinen("free");
ut_assert_console_end();
return 0;
}
CMD_TEST(cmd_test_meminfo, UTF_CONSOLE);