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(&copy, request, sizeof(copy)));
106 			request = &copy;
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 = &copy;
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