blob: 1e2d801ffa59d33848182d84606e85433c715380 [file] [log] [blame]
/*
* Copyright (c) 2023 Google Inc
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <sys/types.h>
#include <zephyr/device.h>
#include <zephyr/drivers/flash/stm32_flash_api_extensions.h>
#include <zephyr/kernel.h>
#ifdef CONFIG_USERSPACE
#include <zephyr/syscall.h>
#include <zephyr/syscall_handler.h>
#endif
#include <soc.h>
#include "flash_stm32.h"
#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
int flash_stm32_ex_op_sector_wp(const struct device *dev, const uintptr_t in,
void *out)
{
const struct flash_stm32_ex_op_sector_wp_in *request =
(const struct flash_stm32_ex_op_sector_wp_in *)in;
struct flash_stm32_ex_op_sector_wp_out *result =
(struct flash_stm32_ex_op_sector_wp_out *)out;
uint32_t change_mask;
int rc = 0, rc2 = 0;
#ifdef CONFIG_USERSPACE
bool syscall_trap = z_syscall_trap();
#endif
if (request != NULL) {
#ifdef CONFIG_USERSPACE
struct flash_stm32_ex_op_sector_wp_in in_copy;
if (syscall_trap) {
Z_OOPS(z_user_from_copy(&in_copy, request,
sizeof(in_copy)));
request = &in_copy;
}
#endif
change_mask = request->enable_mask;
if (!IS_ENABLED(
CONFIG_FLASH_STM32_WRITE_PROTECT_DISABLE_PREVENTION)) {
change_mask |= request->disable_mask;
}
rc = flash_stm32_option_bytes_lock(dev, false);
if (rc == 0) {
rc = flash_stm32_update_wp_sectors(
dev, change_mask, request->enable_mask);
}
rc2 = flash_stm32_option_bytes_lock(dev, true);
if (!rc) {
rc = rc2;
}
}
if (result != NULL) {
#ifdef CONFIG_USERSPACE
struct flash_stm32_ex_op_sector_wp_out out_copy;
if (syscall_trap) {
result = &out_copy;
}
#endif
rc2 = flash_stm32_get_wp_sectors(dev, &result->protected_mask);
if (!rc) {
rc = rc2;
}
#ifdef CONFIG_USERSPACE
if (syscall_trap) {
Z_OOPS(z_user_to_copy(out, result, sizeof(out_copy)));
}
#endif
}
return rc;
}
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in,
void *out)
{
const struct flash_stm32_ex_op_rdp *request =
(const struct flash_stm32_ex_op_rdp *)in;
struct flash_stm32_ex_op_rdp *result =
(struct flash_stm32_ex_op_rdp *)out;
#ifdef CONFIG_USERSPACE
struct flash_stm32_ex_op_rdp copy;
bool syscall_trap = z_syscall_trap();
#endif
int rc = 0, rc2 = 0;
if (request != NULL) {
#ifdef CONFIG_USERSPACE
if (syscall_trap) {
Z_OOPS(z_user_from_copy(&copy, request, sizeof(copy)));
request = &copy;
}
#endif
rc = flash_stm32_option_bytes_lock(dev, false);
if (rc == 0) {
rc = flash_stm32_update_rdp(dev, request->enable,
request->permanent);
}
rc2 = flash_stm32_option_bytes_lock(dev, true);
if (!rc) {
rc = rc2;
}
}
if (result != NULL) {
#ifdef CONFIG_USERSPACE
if (syscall_trap) {
result = &copy;
}
#endif
rc2 = flash_stm32_get_rdp(dev, &result->enable,
&result->permanent);
if (!rc) {
rc = rc2;
}
#ifdef CONFIG_USERSPACE
if (syscall_trap) {
Z_OOPS(z_user_to_copy(out, result, sizeof(copy)));
}
#endif
}
return rc;
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */