1 /*
2 * Copyright (c) 2023 Google Inc
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <sys/types.h>
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/flash/stm32_flash_api_extensions.h>
10 #include <zephyr/kernel.h>
11
12 #ifdef CONFIG_USERSPACE
13 #include <zephyr/syscall.h>
14 #include <zephyr/internal/syscall_handler.h>
15 #endif
16
17 #include <soc.h>
18 #include "flash_stm32.h"
19
20 #if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
flash_stm32_ex_op_sector_wp(const struct device * dev,const uintptr_t in,void * out)21 int flash_stm32_ex_op_sector_wp(const struct device *dev, const uintptr_t in,
22 void *out)
23 {
24 const struct flash_stm32_ex_op_sector_wp_in *request =
25 (const struct flash_stm32_ex_op_sector_wp_in *)in;
26 struct flash_stm32_ex_op_sector_wp_out *result =
27 (struct flash_stm32_ex_op_sector_wp_out *)out;
28 uint32_t change_mask;
29 int rc = 0, rc2 = 0;
30 #ifdef CONFIG_USERSPACE
31 bool syscall_trap = z_syscall_trap();
32 #endif
33
34 if (request != NULL) {
35 #ifdef CONFIG_USERSPACE
36 struct flash_stm32_ex_op_sector_wp_in in_copy;
37
38 if (syscall_trap) {
39 K_OOPS(k_usermode_from_copy(&in_copy, request,
40 sizeof(in_copy)));
41 request = &in_copy;
42 }
43 #endif
44 change_mask = request->enable_mask;
45
46 if (!IS_ENABLED(
47 CONFIG_FLASH_STM32_WRITE_PROTECT_DISABLE_PREVENTION)) {
48 change_mask |= request->disable_mask;
49 }
50
51 rc = flash_stm32_option_bytes_lock(dev, false);
52 if (rc == 0) {
53 rc = flash_stm32_update_wp_sectors(
54 dev, change_mask, request->enable_mask);
55 }
56
57 rc2 = flash_stm32_option_bytes_lock(dev, true);
58 if (!rc) {
59 rc = rc2;
60 }
61 }
62
63 if (result != NULL) {
64 #ifdef CONFIG_USERSPACE
65 struct flash_stm32_ex_op_sector_wp_out out_copy;
66
67 if (syscall_trap) {
68 result = &out_copy;
69 }
70 #endif
71 rc2 = flash_stm32_get_wp_sectors(dev, &result->protected_mask);
72 if (!rc) {
73 rc = rc2;
74 }
75
76 #ifdef CONFIG_USERSPACE
77 if (syscall_trap) {
78 K_OOPS(k_usermode_to_copy(out, result, sizeof(out_copy)));
79 }
80 #endif
81 }
82
83 return rc;
84 }
85 #endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */
86
87 #if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
flash_stm32_ex_op_rdp(const struct device * dev,const uintptr_t in,void * out)88 int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in,
89 void *out)
90 {
91 const struct flash_stm32_ex_op_rdp *request =
92 (const struct flash_stm32_ex_op_rdp *)in;
93 struct flash_stm32_ex_op_rdp *result =
94 (struct flash_stm32_ex_op_rdp *)out;
95
96 #ifdef CONFIG_USERSPACE
97 struct flash_stm32_ex_op_rdp copy;
98 bool syscall_trap = z_syscall_trap();
99 #endif
100 int rc = 0, rc2 = 0;
101
102 if (request != NULL) {
103 #ifdef CONFIG_USERSPACE
104 if (syscall_trap) {
105 K_OOPS(k_usermode_from_copy(©, request, sizeof(copy)));
106 request = ©
107 }
108 #endif
109 rc = flash_stm32_option_bytes_lock(dev, false);
110 if (rc == 0) {
111 rc = flash_stm32_update_rdp(dev, request->enable,
112 request->permanent);
113 }
114
115 rc2 = flash_stm32_option_bytes_lock(dev, true);
116 if (!rc) {
117 rc = rc2;
118 }
119 }
120
121 if (result != NULL) {
122 #ifdef CONFIG_USERSPACE
123 if (syscall_trap) {
124 result = ©
125 }
126 #endif
127 rc2 = flash_stm32_get_rdp(dev, &result->enable,
128 &result->permanent);
129 if (!rc) {
130 rc = rc2;
131 }
132
133 #ifdef CONFIG_USERSPACE
134 if (syscall_trap) {
135 K_OOPS(k_usermode_to_copy(out, result, sizeof(copy)));
136 }
137 #endif
138 }
139
140 return rc;
141 }
142 #endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */
143