diff --git a/drivers/edac/shell.c b/drivers/edac/shell.c index 6536d8a32c8..fc42fb0b8cb 100644 --- a/drivers/edac/shell.c +++ b/drivers/edac/shell.c @@ -457,107 +457,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_info_cmds, SHELL_SUBCMD_SET_END /* Array terminated */ ); -/* Memory operation commands */ - -static int memory_read(const struct shell *sh, mem_addr_t addr, uint8_t width) -{ - uint64_t value; - int err = 0; - - switch (width) { - case 8: - value = sys_read8(addr); - break; - case 16: - value = sys_read16(addr); - break; - case 32: - value = sys_read32(addr); - break; - default: - shell_fprintf(sh, SHELL_NORMAL, "Incorrect data width\n"); - err = -EINVAL; - break; - } - - if (err == 0) { - shell_fprintf(sh, SHELL_NORMAL, "Read value 0x%lx\n", value); - } - - return err; -} - -static int memory_write(const struct shell *sh, mem_addr_t addr, - uint8_t width, uint64_t value) -{ - int err = 0; - - switch (width) { - case 8: - sys_write8(value, addr); - break; - case 16: - sys_write16(value, addr); - break; - case 32: - sys_write32(value, addr); - break; - default: - shell_fprintf(sh, SHELL_NORMAL, "Incorrect data width\n"); - err = -EINVAL; - break; - } - - return err; -} - -/* The syntax of the command is similar to busybox's devmem */ -static int cmd_mem(const struct shell *shell, size_t argc, char **argv) -{ - uint64_t value = 0; - mem_addr_t phys_addr, addr; - uint8_t width; - - if (argc < 2 || argc > 4) { - return -EINVAL; - } - - phys_addr = strtol(argv[1], NULL, 16); - device_map((mm_reg_t *)&addr, phys_addr, 0x100, K_MEM_CACHE_NONE); - - shell_fprintf(shell, SHELL_NORMAL, "Mapped 0x%lx to 0x%lx\n", - phys_addr, addr); - - if (argc < 3) { - width = 32; - } else { - width = strtol(argv[2], NULL, 10); - } - - shell_fprintf(shell, SHELL_NORMAL, "Using data width %d\n", width); - - if (argc <= 3) { - return memory_read(shell, addr, width); - } - - /* If there are more then 3 arguments, that means we are going to write - * this value at the address provided - */ - - value = strtol(argv[3], NULL, 16); - - shell_fprintf(shell, SHELL_NORMAL, "Writing value 0x%lx\n", value); - - return memory_write(shell, addr, width, value); -} - SHELL_STATIC_SUBCMD_SET_CREATE(sub_edac_cmds, SHELL_CMD(info, &sub_info_cmds, "Show EDAC information\n" "edac info ", cmd_edac_info), - SHELL_CMD(mem, NULL, - "Read / Write physical memory\n" - "edac mem address [width [value]]", cmd_mem), #if defined(CONFIG_EDAC_ERROR_INJECT) /* This does not work with SHELL_COND_CMD */ SHELL_CMD(inject, &sub_inject_cmds, diff --git a/subsys/shell/modules/CMakeLists.txt b/subsys/shell/modules/CMakeLists.txt index c9df7d9470f..d002604c6ae 100644 --- a/subsys/shell/modules/CMakeLists.txt +++ b/subsys/shell/modules/CMakeLists.txt @@ -12,3 +12,7 @@ zephyr_sources_ifdef( CONFIG_DATE_SHELL date_service.c ) +zephyr_sources_ifdef( + CONFIG_DEVMEM_SHELL + devmem_service.c + ) diff --git a/subsys/shell/modules/Kconfig b/subsys/shell/modules/Kconfig index c42d1e8bcf6..d21ff37f1a6 100644 --- a/subsys/shell/modules/Kconfig +++ b/subsys/shell/modules/Kconfig @@ -38,3 +38,9 @@ config DATE_SHELL default y if !SHELL_MINIMAL help This shell provides access to date and time based on Unix time. + +config DEVMEM_SHELL + bool "Enable devmem shell" + default y if !SHELL_MINIMAL + help + This shell command provides read/write access to physical memory. diff --git a/subsys/shell/modules/devmem_service.c b/subsys/shell/modules/devmem_service.c new file mode 100644 index 00000000000..ccb4cfc6555 --- /dev/null +++ b/subsys/shell/modules/devmem_service.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +static int memory_read(const struct shell *sh, mem_addr_t addr, uint8_t width) +{ + uint64_t value; + int err = 0; + + switch (width) { + case 8: + value = sys_read8(addr); + break; + case 16: + value = sys_read16(addr); + break; + case 32: + value = sys_read32(addr); + break; + default: + shell_fprintf(sh, SHELL_NORMAL, "Incorrect data width\n"); + err = -EINVAL; + break; + } + + if (err == 0) { + shell_fprintf(sh, SHELL_NORMAL, "Read value 0x%lx\n", value); + } + + return err; +} + +static int memory_write(const struct shell *sh, mem_addr_t addr, + uint8_t width, uint64_t value) +{ + int err = 0; + + switch (width) { + case 8: + sys_write8(value, addr); + break; + case 16: + sys_write16(value, addr); + break; + case 32: + sys_write32(value, addr); + break; + default: + shell_fprintf(sh, SHELL_NORMAL, "Incorrect data width\n"); + err = -EINVAL; + break; + } + + return err; +} + +/* The syntax of the command is similar to busybox's devmem */ +static int cmd_devmem(const struct shell *sh, size_t argc, char **argv) +{ + mem_addr_t phys_addr, addr; + uint32_t value = 0; + uint8_t width; + + if (argc < 2 || argc > 4) { + return -EINVAL; + } + + phys_addr = strtol(argv[1], NULL, 16); + +#if defined(CONFIG_MMU) || defined(CONFIG_PCIE) + device_map((mm_reg_t *)&addr, phys_addr, 0x100, K_MEM_CACHE_NONE); + + shell_print(sh, "Mapped 0x%lx to 0x%lx\n", phys_addr, addr); +#else + addr = phys_addr; +#endif /* defined(CONFIG_MMU) || defined(CONFIG_PCIE) */ + + if (argc < 3) { + width = 32; + } else { + width = strtol(argv[2], NULL, 10); + } + + shell_fprintf(sh, SHELL_NORMAL, "Using data width %d\n", width); + + if (argc <= 3) { + return memory_read(sh, addr, width); + } + + /* If there are more then 3 arguments, that means we are going to write + * this value at the address provided + */ + + value = strtol(argv[3], NULL, 16); + + shell_fprintf(sh, SHELL_NORMAL, "Writing value 0x%lx\n", value); + + return memory_write(sh, addr, width, value); +} + +SHELL_CMD_REGISTER(devmem, NULL, "Read/write physical memory\"" + "devmem address [width [value]]", cmd_devmem);