diff options
author | Tomas Vanek <vanekt@fbl.cz> | 2023-05-13 06:39:48 +0200 |
---|---|---|
committer | Tomas Vanek <vanekt@fbl.cz> | 2023-05-24 05:27:02 +0000 |
commit | 5c46a5de49f5dd14227b9444a5815eaaadd7ceb4 (patch) | |
tree | e4f71f2e6dbe9e9ae72c44c8f7deba929f251b97 /src/jtag/drivers | |
parent | b41b368255d53d9561851900eeeba38b12720a82 (diff) | |
download | riscv-openocd-5c46a5de49f5dd14227b9444a5815eaaadd7ceb4.zip riscv-openocd-5c46a5de49f5dd14227b9444a5815eaaadd7ceb4.tar.gz riscv-openocd-5c46a5de49f5dd14227b9444a5815eaaadd7ceb4.tar.bz2 |
jtag/drivers/bcm2835gpio: add peripheral_mem_dev config command
The bcm2835gpio driver preferred /dev/gpiomem for access to
memory mapped GPIO control and used /dev/mem as a fallback
only if it couldn't open /dev/gpiomem.
/dev/mem usually requires elevated rights or specific capabilities
of the opening process, so the fallback failed anyway.
Although /dev/gpiomem is the strongly preferred option with respect
to security, there could be also use cases which require /dev/mem
even if /dev/gpiomem is available (e.g. changing the GPIO pad
settings is necessary or testing/debugging OpenOCD).
It was difficult to handle such cases because they required
to block globally the system device /dev/gpiomem
(remove, rename or chmod).
Drop the fallback feature and select the memory device
by 'bcm2835gpio peripheral_mem_dev' configuration command.
Use /dev/gpiomem as a default.
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Change-Id: I60e427bda795d7a13d55d61443590dd31d694832
Reviewed-on: https://review.openocd.org/c/openocd/+/7350
Tested-by: jenkins
Reviewed-by: Jonathan Bell <jonathan@raspberrypi.com>
Diffstat (limited to 'src/jtag/drivers')
-rw-r--r-- | src/jtag/drivers/bcm2835gpio.c | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index c723860..39e4af3 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -19,6 +19,7 @@ #include <sys/mman.h> +static char *bcm2835_peri_mem_dev; static off_t bcm2835_peri_base = 0x20000000; #define BCM2835_GPIO_BASE (bcm2835_peri_base + 0x200000) /* GPIO controller */ @@ -57,6 +58,14 @@ static struct initial_gpio_state { } initial_gpio_state[ADAPTER_GPIO_IDX_NUM]; static uint32_t initial_drive_strength_etc; +static inline const char *bcm2835_get_mem_dev(void) +{ + if (bcm2835_peri_mem_dev) + return bcm2835_peri_mem_dev; + + return "/dev/gpiomem"; +} + static inline void bcm2835_gpio_synchronize(void) { /* Ensure that previous writes to GPIO registers are flushed out of @@ -300,6 +309,18 @@ COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs) return ERROR_OK; } +COMMAND_HANDLER(bcm2835gpio_handle_peripheral_mem_dev) +{ + if (CMD_ARGC == 1) { + free(bcm2835_peri_mem_dev); + bcm2835_peri_mem_dev = strdup(CMD_ARGV[0]); + } + + command_print(CMD, "BCM2835 GPIO: peripheral_mem_dev = %s", + bcm2835_get_mem_dev()); + return ERROR_OK; +} + COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base) { uint64_t tmp_base; @@ -323,6 +344,13 @@ static const struct command_registration bcm2835gpio_subcommand_handlers[] = { .usage = "[SPEED_COEFF SPEED_OFFSET]", }, { + .name = "peripheral_mem_dev", + .handler = &bcm2835gpio_handle_peripheral_mem_dev, + .mode = COMMAND_CONFIG, + .help = "device to map memory mapped GPIOs from.", + .usage = "[device]", + }, + { .name = "peripheral_base", .handler = &bcm2835gpio_handle_peripheral_base, .mode = COMMAND_CONFIG, @@ -413,16 +441,16 @@ static int bcm2835gpio_init(void) return ERROR_JTAG_INIT_FAILED; } - bool pad_mapping_possible = false; + bool is_gpiomem = strcmp(bcm2835_get_mem_dev(), "/dev/gpiomem") == 0; + bool pad_mapping_possible = !is_gpiomem; - dev_mem_fd = open("/dev/gpiomem", O_RDWR | O_SYNC); - if (dev_mem_fd < 0) { - LOG_DEBUG("Cannot open /dev/gpiomem, fallback to /dev/mem"); - dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); - pad_mapping_possible = true; - } + dev_mem_fd = open(bcm2835_get_mem_dev(), O_RDWR | O_SYNC); if (dev_mem_fd < 0) { - LOG_ERROR("open: %s", strerror(errno)); + LOG_ERROR("open %s: %s", bcm2835_get_mem_dev(), strerror(errno)); + /* TODO: add /dev/mem specific doc and refer to it + * if (!is_gpiomem && (errno == EACCES || errno == EPERM)) + * LOG_INFO("Consult the user's guide chapter 4.? how to set permissions and capabilities"); + */ return ERROR_JTAG_INIT_FAILED; } @@ -532,6 +560,7 @@ static int bcm2835gpio_quit(void) pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5A000000 | initial_drive_strength_etc; } bcm2835gpio_munmap(); + free(bcm2835_peri_mem_dev); return ERROR_OK; } |