[PATCH v4 0/8] Allow showing the memory map

This little series adds a new 'memmap' command, intended to show the layout of memory within U-Boot and how much memory is available for loading images.
Changes in v4: - Drop am65x patch as it is not needed - Add patch to export the lmb data structure - Add new patch to show the lmb records
Changes in v3: - Add a new Kconfig for the extra functionality
Changes in v2: - Split into its own patch - Modify the existing 'meminfo' command instead
Simon Glass (8): common: Fix up malloc() comment in reserve_noncached() common: Tidy up how malloc() is inited global_data: Add some more accessors bootstage: Allow counting memory without strings cmd: Move meminfo command into its own file cmd: Update the meminfo command to show the memory map lmb: Export the lmb data structure meminfo: Show the lmb records
cmd/Kconfig | 12 +++ cmd/Makefile | 1 + cmd/mem.c | 19 ----- cmd/meminfo.c | 99 +++++++++++++++++++++++ common/board_f.c | 8 +- common/board_r.c | 3 +- common/bootstage.c | 16 ++-- common/dlmalloc.c | 8 +- common/spl/spl.c | 4 +- doc/usage/cmd/meminfo.rst | 128 ++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + include/asm-generic/global_data.h | 30 +++++++ include/bootstage.h | 5 +- include/malloc.h | 8 ++ lib/lmb.c | 2 +- test/cmd/Makefile | 3 +- test/cmd/meminfo.c | 42 ++++++++++ 17 files changed, 347 insertions(+), 42 deletions(-) create mode 100644 cmd/meminfo.c create mode 100644 doc/usage/cmd/meminfo.rst create mode 100644 test/cmd/meminfo.c

The function name has changed, so update it.
Signed-off-by: Simon Glass sjg@chromium.org Acked-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
(no changes since v1)
common/board_f.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/common/board_f.c b/common/board_f.c index f1bd70fdd6c..a87411ee350 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -501,9 +501,9 @@ static unsigned long reserve_stack_aligned(size_t size) static int reserve_noncached(void) { /* - * The value of gd->start_addr_sp must match the value of malloc_start - * calculated in board_r.c:initr_malloc(), which is passed to - * dlmalloc.c:mem_malloc_init() and then used by + * The value of gd->start_addr_sp must match the value of + * mem_malloc_start calculated in board_r.c:initr_malloc(), which is + * passed to dlmalloc.c:mem_malloc_init() and then used by * cache.c:noncached_init() * * These calculations must match the code in cache.c:noncached_init()

The call to malloc() is a bit strange. The naming of the arguments suggests that an address is passed, but in fact it is a pointer, at least in the board_init_r() function and SPL equivalent.
Update it to work as described. Add a function comment as well.
Note that this does adjustment does not extend into the malloc() implementation itself, apart from changing mem_malloc_init(), since there are lots of casts and pointers and integers are used interchangeably.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
(no changes since v1)
common/board_r.c | 3 +-- common/dlmalloc.c | 8 +++++--- common/spl/spl.c | 4 +--- include/malloc.h | 8 ++++++++ 4 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/common/board_r.c b/common/board_r.c index e5f33f40643..8a19817fa39 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -204,8 +204,7 @@ static int initr_malloc(void) */ start = gd->relocaddr - TOTAL_MALLOC_LEN; gd_set_malloc_start(start); - mem_malloc_init((ulong)map_sysmem(start, TOTAL_MALLOC_LEN), - TOTAL_MALLOC_LEN); + mem_malloc_init(start, TOTAL_MALLOC_LEN); return 0; }
diff --git a/common/dlmalloc.c b/common/dlmalloc.c index 1ac7ce3f43c..cc4d3a0a028 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -16,6 +16,8 @@ #include <asm/global_data.h>
#include <malloc.h> +#include <mapmem.h> +#include <string.h> #include <asm/io.h> #include <valgrind/memcheck.h>
@@ -598,9 +600,9 @@ void *sbrk(ptrdiff_t increment)
void mem_malloc_init(ulong start, ulong size) { - mem_malloc_start = start; - mem_malloc_end = start + size; - mem_malloc_brk = start; + mem_malloc_start = (ulong)map_sysmem(start, size); + mem_malloc_end = mem_malloc_start + size; + mem_malloc_brk = mem_malloc_start;
#ifdef CONFIG_SYS_MALLOC_DEFAULT_TO_INIT malloc_init(); diff --git a/common/spl/spl.c b/common/spl/spl.c index 94657d00591..1ceb63daf31 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -678,9 +678,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) spl_set_bd();
if (IS_ENABLED(CONFIG_SPL_SYS_MALLOC)) { - mem_malloc_init((ulong)map_sysmem(SPL_SYS_MALLOC_START, - SPL_SYS_MALLOC_SIZE), - SPL_SYS_MALLOC_SIZE); + mem_malloc_init(SPL_SYS_MALLOC_START, SPL_SYS_MALLOC_SIZE); gd->flags |= GD_FLG_FULL_MALLOC_INIT; } if (!(gd->flags & GD_FLG_SPL_INIT)) { diff --git a/include/malloc.h b/include/malloc.h index 07d3e90a855..9e0be482416 100644 --- a/include/malloc.h +++ b/include/malloc.h @@ -981,6 +981,14 @@ extern ulong mem_malloc_start; extern ulong mem_malloc_end; extern ulong mem_malloc_brk;
+/** + * mem_malloc_init() - Set up the malloc() pool + * + * Sets the region of memory to be used for all future calls to malloc(), etc. + * + * @start: Start address + * @size: Size in bytes + */ void mem_malloc_init(ulong start, ulong size);
#ifdef __cplusplus

Add accessors for bloblist, bootstage, trace and video to avoid needing more #ifdefs in the C code.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
include/asm-generic/global_data.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 644a0d77873..9dc0f4308cc 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -544,6 +544,36 @@ static_assert(sizeof(struct global_data) == GD_SIZE); #define gd_set_upl(val) #endif
+#if CONFIG_IS_ENABLED(BLOBLIST) +#define gd_bloblist() gd->bloblist +#else +#define gd_bloblist() NULL +#endif + +#if CONFIG_IS_ENABLED(BOOTSTAGE) +#define gd_bootstage() gd->bootstage +#else +#define gd_bootstage() NULL +#endif + +#if CONFIG_IS_ENABLED(TRACE) +#define gd_trace_buff() gd->trace_buff +#define gd_trace_size() CONFIG_TRACE_BUFFER_SIZE +#else +#define gd_trace_buff() NULL +#define gd_trace_size() 0 +#endif + +#if CONFIG_IS_ENABLED(VIDEO) +#define gd_video_top() gd->video_top +#define gd_video_bottom() gd->video_bottom +#define gd_video_size() (gd->video_top - gd->video_bottom) +#else +#define gd_video_top() 0 +#define gd_video_bottom() 0 +#define gd_video_size() 0 +#endif + /** * enum gd_flags - global data flags *

The bootstage array includes pointers to strings but not the strings themselves. The strings are added when stashing, but including them in the size calculation gives an inflated view of the amount of space used by the array.
Update this function so it can return the amount of memory used by the bootstage structures themselves, without the strings which they point to.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v1)
common/board_f.c | 2 +- common/bootstage.c | 16 +++++++++------- include/bootstage.h | 5 +++-- 3 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/common/board_f.c b/common/board_f.c index a87411ee350..98dc2591e1d 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -582,7 +582,7 @@ static int reserve_fdt(void) static int reserve_bootstage(void) { #ifdef CONFIG_BOOTSTAGE - int size = bootstage_get_size(); + int size = bootstage_get_size(true);
gd->start_addr_sp = reserve_stack_aligned(size); gd->boardf->new_bootstage = map_sysmem(gd->start_addr_sp, size); diff --git a/common/bootstage.c b/common/bootstage.c index dd6aed7c2fd..c7bb204501a 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -520,17 +520,19 @@ int _bootstage_unstash_default(void) } #endif
-int bootstage_get_size(void) +int bootstage_get_size(bool add_strings) { - struct bootstage_data *data = gd->bootstage; - struct bootstage_record *rec; int size; - int i;
size = sizeof(struct bootstage_data); - for (rec = data->record, i = 0; i < data->rec_count; - i++, rec++) - size += strlen(rec->name) + 1; + if (add_strings) { + struct bootstage_data *data = gd->bootstage; + struct bootstage_record *rec; + int i; + + for (rec = data->record, i = 0; i < data->rec_count; i++, rec++) + size += strlen(rec->name) + 1; + }
return size; } diff --git a/include/bootstage.h b/include/bootstage.h index 57792648c49..3300ca0248a 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -371,9 +371,10 @@ int bootstage_unstash(const void *base, int size); /** * bootstage_get_size() - Get the size of the bootstage data * + * @add_strings: true to add the size of attached strings (for stashing) * Return: size of boostage data in bytes */ -int bootstage_get_size(void); +int bootstage_get_size(bool add_strings);
/** * bootstage_init() - Prepare bootstage for use @@ -444,7 +445,7 @@ static inline int bootstage_unstash(const void *base, int size) return 0; /* Pretend to succeed */ }
-static inline int bootstage_get_size(void) +static inline int bootstage_get_size(bool add_strings) { return 0; }

In preparation for expanding this command, move it into a separate file. Rename the function to remove the extra underscore. Update the number of arguments to 1, since 3 is incorrect.
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v2)
Changes in v2: - Split into its own patch
cmd/Kconfig | 1 + cmd/Makefile | 1 + cmd/mem.c | 19 ------------------- cmd/meminfo.c | 26 ++++++++++++++++++++++++++ 4 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 cmd/meminfo.c
diff --git a/cmd/Kconfig b/cmd/Kconfig index a4ca61c37dd..05bd3e8a5e2 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -885,6 +885,7 @@ config MD5SUM_VERIFY
config CMD_MEMINFO bool "meminfo" + default y if SANDBOX help Display memory information.
diff --git a/cmd/Makefile b/cmd/Makefile index 3c5bd56e912..16e275eba63 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -110,6 +110,7 @@ obj-$(CONFIG_CMD_LOG) += log.o obj-$(CONFIG_CMD_LSBLK) += lsblk.o obj-$(CONFIG_CMD_MD5SUM) += md5sum.o obj-$(CONFIG_CMD_MEMORY) += mem.o +obj-$(CONFIG_CMD_MEMINFO) += meminfo.o obj-$(CONFIG_CMD_IO) += io.o obj-$(CONFIG_CMD_MII) += mii.o obj-$(CONFIG_CMD_MISC) += misc.o diff --git a/cmd/mem.c b/cmd/mem.c index 4d6fde28531..9e716776393 100644 --- a/cmd/mem.c +++ b/cmd/mem.c @@ -1379,17 +1379,6 @@ U_BOOT_CMD(
#endif
-#ifdef CONFIG_CMD_MEMINFO -static int do_mem_info(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - puts("DRAM: "); - print_size(gd->ram_size, "\n"); - - return 0; -} -#endif - U_BOOT_CMD( base, 2, 1, do_mem_base, "print or set address offset", @@ -1433,14 +1422,6 @@ U_BOOT_CMD( ); #endif /* CONFIG_CMD_MX_CYCLIC */
-#ifdef CONFIG_CMD_MEMINFO -U_BOOT_CMD( - meminfo, 3, 1, do_mem_info, - "display memory information", - "" -); -#endif - #ifdef CONFIG_CMD_RANDOM U_BOOT_CMD( random, 4, 0, do_random, diff --git a/cmd/meminfo.c b/cmd/meminfo.c new file mode 100644 index 00000000000..bb9bcec2e3f --- /dev/null +++ b/cmd/meminfo.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 Google LLC + * Written by Simon Glass sjg@chromium.org + */ + +#include <command.h> +#include <display_options.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +static int do_meminfo(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + puts("DRAM: "); + print_size(gd->ram_size, "\n"); + + return 0; +} + +U_BOOT_CMD( + meminfo, 1, 1, do_meminfo, + "display memory information", + "" +);

On Mon, 21 Oct 2024 at 11:19, Simon Glass sjg@chromium.org wrote:
In preparation for expanding this command, move it into a separate file. Rename the function to remove the extra underscore. Update the number of arguments to 1, since 3 is incorrect.
Signed-off-by: Simon Glass sjg@chromium.org
(no changes since v2)
Changes in v2:
- Split into its own patch
cmd/Kconfig | 1 + cmd/Makefile | 1 + cmd/mem.c | 19 ------------------- cmd/meminfo.c | 26 ++++++++++++++++++++++++++ 4 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 cmd/meminfo.c
diff --git a/cmd/Kconfig b/cmd/Kconfig index a4ca61c37dd..05bd3e8a5e2 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -885,6 +885,7 @@ config MD5SUM_VERIFY
config CMD_MEMINFO bool "meminfo"
default y if SANDBOX help Display memory information.
diff --git a/cmd/Makefile b/cmd/Makefile index 3c5bd56e912..16e275eba63 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -110,6 +110,7 @@ obj-$(CONFIG_CMD_LOG) += log.o obj-$(CONFIG_CMD_LSBLK) += lsblk.o obj-$(CONFIG_CMD_MD5SUM) += md5sum.o obj-$(CONFIG_CMD_MEMORY) += mem.o +obj-$(CONFIG_CMD_MEMINFO) += meminfo.o obj-$(CONFIG_CMD_IO) += io.o obj-$(CONFIG_CMD_MII) += mii.o obj-$(CONFIG_CMD_MISC) += misc.o diff --git a/cmd/mem.c b/cmd/mem.c index 4d6fde28531..9e716776393 100644 --- a/cmd/mem.c +++ b/cmd/mem.c @@ -1379,17 +1379,6 @@ U_BOOT_CMD(
#endif
-#ifdef CONFIG_CMD_MEMINFO -static int do_mem_info(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
-{
puts("DRAM: ");
print_size(gd->ram_size, "\n");
return 0;
-} -#endif
U_BOOT_CMD( base, 2, 1, do_mem_base, "print or set address offset", @@ -1433,14 +1422,6 @@ U_BOOT_CMD( ); #endif /* CONFIG_CMD_MX_CYCLIC */
-#ifdef CONFIG_CMD_MEMINFO -U_BOOT_CMD(
meminfo, 3, 1, do_mem_info,
"display memory information",
""
-); -#endif
#ifdef CONFIG_CMD_RANDOM U_BOOT_CMD( random, 4, 0, do_random, diff --git a/cmd/meminfo.c b/cmd/meminfo.c new file mode 100644 index 00000000000..bb9bcec2e3f --- /dev/null +++ b/cmd/meminfo.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright 2024 Google LLC
- Written by Simon Glass sjg@chromium.org
- */
+#include <command.h> +#include <display_options.h> +#include <asm/global_data.h>
+DECLARE_GLOBAL_DATA_PTR;
+static int do_meminfo(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
puts("DRAM: ");
print_size(gd->ram_size, "\n");
return 0;
+}
+U_BOOT_CMD(
meminfo, 1, 1, do_meminfo,
"display memory information",
""
+);
2.43.0
Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org

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 ---
Changes in v4: - Drop am65x patch as it is not needed
Changes in v3: - Add a new Kconfig for the extra functionality
Changes in v2: - Modify the existing 'meminfo' command instead
cmd/Kconfig | 11 ++++ cmd/meminfo.c | 51 ++++++++++++++- doc/usage/cmd/meminfo.rst | 128 ++++++++++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + test/cmd/Makefile | 3 +- test/cmd/meminfo.c | 38 +++++++++++ 6 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 doc/usage/cmd/meminfo.rst create mode 100644 test/cmd/meminfo.c
diff --git a/cmd/Kconfig b/cmd/Kconfig index 05bd3e8a5e2..2c5188daff2 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -889,6 +889,17 @@ config CMD_MEMINFO help 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 bool "md, mm, nm, mw, cp, cmp, base, loop" default y diff --git a/cmd/meminfo.c b/cmd/meminfo.c index bb9bcec2e3f..0e6d2f9cc2c 100644 --- a/cmd/meminfo.c +++ b/cmd/meminfo.c @@ -4,18 +4,67 @@ * Written by Simon Glass sjg@chromium.org */
+#include <bloblist.h> +#include <bootstage.h> #include <command.h> #include <display_options.h> +#include <malloc.h> +#include <mapmem.h> #include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR;
+static void print_region(const char *name, ulong base, ulong size, ulong *uptop) +{ + 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[]) + char *const argv[]) { + ulong upto, stk_bot; + puts("DRAM: "); 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; }
diff --git a/doc/usage/cmd/meminfo.rst b/doc/usage/cmd/meminfo.rst new file mode 100644 index 00000000000..6c94493cccc --- /dev/null +++ b/doc/usage/cmd/meminfo.rst @@ -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). diff --git a/doc/usage/index.rst b/doc/usage/index.rst index b84d8ee909f..db71711c393 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -84,6 +84,7 @@ Shell commands cmd/loads cmd/loadx cmd/loady + cmd/meminfo cmd/mbr cmd/md cmd/mmc diff --git a/test/cmd/Makefile b/test/cmd/Makefile index 40808350962..4b487c1d2cb 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -19,8 +19,9 @@ obj-$(CONFIG_CMD_FDT) += fdt.o obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o obj-$(CONFIG_CMD_HISTORY) += history.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_MEM_SEARCH) += mem_search.o ifdef CONFIG_CMD_PCI obj-$(CONFIG_CMD_PCI_MPS) += pci_mps.o endif diff --git a/test/cmd/meminfo.c b/test/cmd/meminfo.c new file mode 100644 index 00000000000..84981305bf0 --- /dev/null +++ b/test/cmd/meminfo.c @@ -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);

Provide a way to access this data structure so that the meminfo command can use it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: - Add patch to export the lmb data structure
lib/lmb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/lmb.c b/lib/lmb.c index 7e90f178763..eec99c185ee 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -887,12 +887,12 @@ int lmb_init(void) return 0; }
-#if CONFIG_IS_ENABLED(UNIT_TEST) struct lmb *lmb_get(void) { return &lmb; }
+#if CONFIG_IS_ENABLED(UNIT_TEST) int lmb_push(struct lmb *store) { int ret;

On Mon, 21 Oct 2024 at 11:19, Simon Glass sjg@chromium.org wrote:
Provide a way to access this data structure so that the meminfo command can use it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v4:
- Add patch to export the lmb data structure
lib/lmb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/lmb.c b/lib/lmb.c index 7e90f178763..eec99c185ee 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -887,12 +887,12 @@ int lmb_init(void) return 0; }
-#if CONFIG_IS_ENABLED(UNIT_TEST) struct lmb *lmb_get(void) { return &lmb; }
+#if CONFIG_IS_ENABLED(UNIT_TEST) int lmb_push(struct lmb *store) { int ret; -- 2.43.0
Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org

Add the lmb records onto the end of the memory map.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: - Add new patch to show the lmb records
cmd/meminfo.c | 26 +++++++++++++++++++++++++- test/cmd/meminfo.c | 6 +++++- 2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/cmd/meminfo.c b/cmd/meminfo.c index 0e6d2f9cc2c..5e83d61c2dd 100644 --- a/cmd/meminfo.c +++ b/cmd/meminfo.c @@ -8,6 +8,7 @@ #include <bootstage.h> #include <command.h> #include <display_options.h> +#include <lmb.h> #include <malloc.h> #include <mapmem.h> #include <asm/global_data.h> @@ -25,6 +26,27 @@ static void print_region(const char *name, ulong base, ulong size, ulong *uptop) *uptop = base; }
+static void show_lmb(const struct lmb *lmb, ulong *uptop) +{ + int i; + + for (i = lmb->used_mem.count - 1; i >= 0; i--) { + const struct lmb_region *rgn = alist_get(&lmb->used_mem, i, + struct lmb_region); + + /* + * Assume that the top lmb region is the U-Boot region, so just + * take account of the memory not already reported + */ + if (lmb->used_mem.count - 1) + print_region("lmb", rgn->base, *uptop - rgn->base, + uptop); + else + print_region("lmb", rgn->base, rgn->size, uptop); + *uptop = rgn->base; + } +} + static int do_meminfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -63,7 +85,9 @@ static int do_meminfo(struct cmd_tbl *cmdtp, int flag, int argc, 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); + if (IS_ENABLED(CONFIG_LMB)) + show_lmb(lmb_get(), &upto); + print_region("free", gd->ram_base, upto, &upto);
return 0; } diff --git a/test/cmd/meminfo.c b/test/cmd/meminfo.c index 84981305bf0..53b41e3b49e 100644 --- a/test/cmd/meminfo.c +++ b/test/cmd/meminfo.c @@ -30,7 +30,11 @@ static int cmd_test_meminfo(struct unit_test_state *uts) ut_assert_nextlinen("bootstage"); ut_assert_nextlinen("bloblist"); ut_assert_nextlinen("stack"); - ut_assert_nextlinen("free"); + + /* we expect at least one lmb line, but don't know how many */ + ut_assert_nextlinen("lmb"); + ut_assert_skip_to_linen("free"); + ut_assert_console_end();
return 0;

On Mon, 21 Oct 2024 10:19:24 +0200, Simon Glass wrote:
This little series adds a new 'memmap' command, intended to show the layout of memory within U-Boot and how much memory is available for loading images.
Changes in v4:
- Drop am65x patch as it is not needed
- Add patch to export the lmb data structure
- Add new patch to show the lmb records
[...]
Applied to u-boot/master, thanks!
participants (3)
-
Ilias Apalodimas
-
Simon Glass
-
Tom Rini