11/*
22 * Copyright (c) 2020 Intel Corporation
33 * Copyright (c) 2021 Antmicro <www.antmicro.com>
4+ * Copyright (c) 2022 Meta
45 *
56 * SPDX-License-Identifier: Apache-2.0
67 */
910#include <zephyr/device.h>
1011#include <zephyr/shell/shell.h>
1112#include <zephyr/sys/byteorder.h>
13+ #ifdef CONFIG_ARCH_POSIX
14+ #include <unistd.h>
15+ #else
16+ #include <zephyr/posix/unistd.h>
17+ #endif
1218
1319static inline bool is_ascii (uint8_t data )
1420{
@@ -26,6 +32,122 @@ static bool littleendian;
2632#define CHAR_CAN 0x18
2733#define CHAR_DC1 0x11
2834
35+ #ifndef BITS_PER_BYTE
36+ #define BITS_PER_BYTE 8
37+ #endif
38+
39+ static int memory_dump (const struct shell * sh , mem_addr_t phys_addr , size_t size , uint8_t width )
40+ {
41+ uint32_t value ;
42+ size_t data_offset ;
43+ mm_reg_t addr ;
44+ const size_t vsize = width / BITS_PER_BYTE ;
45+ uint8_t data [SHELL_HEXDUMP_BYTES_IN_LINE ];
46+
47+ #if defined(CONFIG_MMU ) || defined(CONFIG_PCIE )
48+ device_map ((mm_reg_t * )& addr , phys_addr , size , K_MEM_CACHE_NONE );
49+
50+ shell_print (sh , "Mapped 0x%lx to 0x%lx\n" , phys_addr , addr );
51+ #else
52+ addr = phys_addr ;
53+ #endif /* defined(CONFIG_MMU) || defined(CONFIG_PCIE) */
54+
55+ for (; size > 0 ;
56+ addr += SHELL_HEXDUMP_BYTES_IN_LINE , size -= MIN (size , SHELL_HEXDUMP_BYTES_IN_LINE )) {
57+ for (data_offset = 0 ;
58+ size >= vsize && data_offset + vsize <= SHELL_HEXDUMP_BYTES_IN_LINE ;
59+ data_offset += vsize ) {
60+ switch (width ) {
61+ case 8 :
62+ value = sys_read8 (addr + data_offset );
63+ data [data_offset ] = value ;
64+ break ;
65+ case 16 :
66+ value = sys_read16 (addr + data_offset );
67+ if (IS_ENABLED (CONFIG_BIG_ENDIAN )) {
68+ value = __bswap_16 (value );
69+ }
70+
71+ data [data_offset ] = (uint8_t )value ;
72+ value >>= 8 ;
73+ data [data_offset + 1 ] = (uint8_t )value ;
74+ break ;
75+ case 32 :
76+ value = sys_read32 (addr + data_offset );
77+ if (IS_ENABLED (CONFIG_BIG_ENDIAN )) {
78+ value = __bswap_32 (value );
79+ }
80+
81+ data [data_offset ] = (uint8_t )value ;
82+ value >>= 8 ;
83+ data [data_offset + 1 ] = (uint8_t )value ;
84+ value >>= 8 ;
85+ data [data_offset + 2 ] = (uint8_t )value ;
86+ value >>= 8 ;
87+ data [data_offset + 3 ] = (uint8_t )value ;
88+ break ;
89+ default :
90+ shell_fprintf (sh , SHELL_NORMAL , "Incorrect data width\n" );
91+ return - EINVAL ;
92+ }
93+ }
94+
95+ shell_hexdump_line (sh , addr , data , MIN (size , SHELL_HEXDUMP_BYTES_IN_LINE ));
96+ }
97+
98+ return 0 ;
99+ }
100+
101+ static int cmd_dump (const struct shell * sh , size_t argc , char * * argv )
102+ {
103+ int rv ;
104+ size_t size = -1 ;
105+ size_t width = 32 ;
106+ mem_addr_t addr = -1 ;
107+
108+ optind = 1 ;
109+ while ((rv = getopt (argc , argv , "a:s:w:" )) != -1 ) {
110+ switch (rv ) {
111+ case 'a' :
112+ addr = (mem_addr_t )strtoul (optarg , NULL , 16 );
113+ if (addr == 0 && errno == EINVAL ) {
114+ shell_error (sh , "invalid addr '%s'" , optarg );
115+ return - EINVAL ;
116+ }
117+ break ;
118+ case 's' :
119+ size = (size_t )strtoul (optarg , NULL , 0 );
120+ if (size == 0 && errno == EINVAL ) {
121+ shell_error (sh , "invalid size '%s'" , optarg );
122+ return - EINVAL ;
123+ }
124+ break ;
125+ case 'w' :
126+ width = (size_t )strtoul (optarg , NULL , 0 );
127+ if (width == 0 && errno == EINVAL ) {
128+ shell_error (sh , "invalid width '%s'" , optarg );
129+ return - EINVAL ;
130+ }
131+ break ;
132+ case '?' :
133+ default :
134+ return - EINVAL ;
135+ }
136+ }
137+
138+ if (addr == -1 ) {
139+ shell_error (sh , "'-a <address>' is mandatory" );
140+ return - EINVAL ;
141+ }
142+
143+ if (size == -1 ) {
144+ shell_error (sh , "'-s <size>' is mandatory" );
145+ return - EINVAL ;
146+ }
147+
148+ return memory_dump (sh , addr , size , width );
149+ }
150+
29151static int set_bypass (const struct shell * sh , shell_bypass_cb_t bypass )
30152{
31153 static bool in_use ;
@@ -229,6 +351,10 @@ static int cmd_devmem(const struct shell *sh, size_t argc, char **argv)
229351}
230352
231353SHELL_STATIC_SUBCMD_SET_CREATE (sub_devmem ,
354+ SHELL_CMD_ARG (dump , NULL ,
355+ "Usage:\n"
356+ "devmem dump -a <address> -s <size> [-w <width>]\n" ,
357+ cmd_dump , 4 , 6 ),
232358 SHELL_CMD_ARG (load , NULL ,
233359 "Usage:\n"
234360 "devmem load [options] [address]\n"
0 commit comments