blob: 7f85a3f0da7b2e2f00e6576a91124db219966da1 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2023 ASR Micro Limited
4 *
5 */
6
7#include <linux/module.h>
8#include <linux/kernel.h>
9#include <linux/platform_device.h>
10#include <linux/of.h>
11#include <linux/clk.h>
12#include <linux/io.h>
13#include <linux/slab.h>
14#include <linux/miscdevice.h>
15#include <linux/sched.h>
16#include <linux/fs.h>
17#include <linux/uaccess.h>
18#ifdef CONFIG_TEE
19#include <linux/tee_drv.h>
20#endif
21
22#include <uapi/linux/geu_ioctl.h>
23
24#include "asr-fuse-optee.h"
25#include "asr-geu-optee.h"
26
27static struct teec_uuid pta_fuse_uuid = ASR_FUSE_ACCESS_UUID;
28
29static int asr_fuse_read_sim_lock(int *sim_lock)
30{
31 return asrgeu_optee_acquire_ta_buff(&pta_fuse_uuid, CMD_FUSE_READ_SIM_LOCK, sim_lock, 4, 0);
32}
33
34static int asr_fuse_burn_sim_lock(void)
35{
36 int sim_lock = 0;
37 asrgeu_optee_acquire_ta_buff(&pta_fuse_uuid, CMD_FUSE_BURN_SIM_LOCK, &sim_lock, 4, 0);
38
39 return sim_lock;
40}
41
42static int asr_fuse_get_trusted_boot_mode(int *tb_mode)
43{
44 return asrgeu_optee_acquire_ta_buff(&pta_fuse_uuid, CMD_FUSE_READ_TRUSTED_MODE, tb_mode, 4, 0);
45}
46
47static int asr_fuse_read_oem_key_hash(uint32_t *key_hash)
48{
49 return asrgeu_optee_acquire_ta_buff(&pta_fuse_uuid, CMD_FUSE_READ_OEM_KEY_HASH, key_hash, 32, 0);
50}
51
52static int asr_fuse_read_life_cycle(uint32_t *life_cycle)
53{
54 return asrgeu_optee_acquire_ta_buff(&pta_fuse_uuid, CMD_FUSE_READ_LIFE_CYCLE, life_cycle, 2, 0);
55}
56
57static int asr_fuse_read_oem_uid(uint32_t *uid)
58{
59 return asrgeu_optee_acquire_ta_buff(&pta_fuse_uuid, CMD_FUSE_READ_OEM_UUID, uid, 8, 0);
60}
61
62static DEFINE_MUTEX(sim_lock_mutex);
63static DEFINE_MUTEX(tb_mode_mutex);
64static ssize_t sim_lock_read(struct device *dev,
65 struct device_attribute *attr, char *buf)
66{
67 int len = 0;
68 unsigned int sim_lock;
69
70 mutex_lock(&sim_lock_mutex);
71
72 asr_fuse_read_sim_lock(&sim_lock);
73
74 len = sprintf(buf, "%x\n", sim_lock);
75
76 mutex_unlock(&sim_lock_mutex);
77
78 return (ssize_t)len;
79}
80
81static ssize_t sim_lock_write(struct device *dev,
82 struct device_attribute *attr, const char *buf, size_t size)
83{
84 int ret, enable, sim_lock;
85
86 ret = sscanf(buf, "%d", &enable);
87
88 if(ret != 1 || enable != 1) {
89 return size;
90 }
91
92 mutex_lock(&sim_lock_mutex);
93
94 sim_lock = asr_fuse_burn_sim_lock();
95
96 if (!sim_lock)
97 dev_info(dev, "burn sim lock fails\n");
98 else
99 dev_info(dev, "burn sim lock done\n");
100
101 mutex_unlock(&sim_lock_mutex);
102 return size;
103}
104
105static ssize_t tb_mode_read(struct device *dev,
106 struct device_attribute *attr, char *buf)
107{
108 int len = 0, i;
109 int tb_mode;
110 unsigned int fused_key_hash[8];
111
112 mutex_lock(&tb_mode_mutex);
113
114 asr_fuse_get_trusted_boot_mode(&tb_mode);
115
116 asr_fuse_read_oem_key_hash(fused_key_hash);
117
118 len = sprintf(buf, "Trusted boot mode: %d\n", tb_mode);
119
120 len += sprintf(buf+len, "OEM Key Hash(High --> Low):\n");
121
122 for (i = 7; i >= 0; i--)
123 len += sprintf(buf+len, "%08x ", fused_key_hash[i]);
124
125 len += sprintf(buf+len, "\n");
126
127 mutex_unlock(&tb_mode_mutex);
128
129 return (ssize_t)len;
130}
131
132static DEVICE_ATTR(simlock, S_IRUGO | S_IWUSR, sim_lock_read, sim_lock_write);
133static DEVICE_ATTR(tb_mode, S_IRUGO, tb_mode_read, NULL);
134
135static struct attribute *fuse_dev_attrs[] = {
136 &dev_attr_simlock.attr,
137 &dev_attr_tb_mode.attr,
138 NULL
139};
140
141ATTRIBUTE_GROUPS(fuse_dev);
142
143static int asr_fuse_iotcl_read_key_hash(void __user *key_hash, unsigned int len)
144{
145 unsigned int oem_key_hash[8];
146
147 if (!access_ok(key_hash, len))
148 return -EFAULT;
149
150 asr_fuse_read_oem_key_hash(oem_key_hash);
151
152 if (copy_to_user(key_hash, oem_key_hash, len)) {
153 return -EFAULT;
154 }
155
156 return 0;
157}
158
159static int asr_fuse_iotcl_read_life_cycle(void __user *life_cyle, unsigned int len)
160{
161 unsigned int asr_life_cyle[2];
162
163 if (!access_ok(life_cyle, 2 * sizeof(unsigned int)))
164 return -EFAULT;
165
166 asr_fuse_read_life_cycle(asr_life_cyle);
167
168 if (copy_to_user(life_cyle, asr_life_cyle, sizeof(unsigned int) * 2)) {
169 return -EFAULT;
170 }
171
172 return 0;
173}
174
175static int asr_fuse_iotcl_read_oem_uid(void __user *oem_uid_hi, void __user *oem_uid_lo)
176{
177 unsigned int oem_uid[2];
178
179 if (!access_ok(oem_uid_hi, sizeof(unsigned int)) ||
180 !access_ok(oem_uid_lo, sizeof(unsigned int)))
181 return -EFAULT;
182
183 asr_fuse_read_oem_uid(oem_uid);
184
185 if (copy_to_user(oem_uid_hi, &oem_uid[0], sizeof(unsigned int)))
186 return -EFAULT;
187
188 if (copy_to_user(oem_uid_lo, &oem_uid[1], sizeof(unsigned int)))
189 return -EFAULT;
190
191 return 0;
192}
193
194static int asr_fuse_iotcl_burn_simlock(void __user *sim_lock)
195{
196 int simlock = 0;
197
198 simlock = asr_fuse_burn_sim_lock();
199
200 if (simlock == 0) {
201 pr_err("asr fuse: burn sim lock fails\n");
202 return -EFAULT;
203 } else {
204 if(copy_to_user(sim_lock, (void *)(&simlock), 4)) {
205 pr_err("asr fuse: get sim lock error\n");
206 return -EFAULT;
207 }
208 }
209
210 return 0;
211}
212
213static int asr_fuse_iotcl_get_simlock(void __user *sim_lock)
214{
215 int simlock;
216
217 asr_fuse_read_sim_lock(&simlock);
218 if(copy_to_user(sim_lock, (void *)(&simlock), 4)) {
219 pr_err("asr fuse: get sim lock error\n");
220 return -EFAULT;
221 }
222
223 return 0;
224}
225
226static int asr_fuse_iotcl_get_trust_mode(void __user *tb_mode)
227{
228 int trusted_mode;
229
230 asr_fuse_get_trusted_boot_mode(&trusted_mode);
231 if(copy_to_user(tb_mode, (void *)(&trusted_mode), 4)) {
232 pr_err("asr fuse: get trusted boot error\n");
233 return -EFAULT;
234 }
235
236 return 0;
237}
238
239static long asr_fuse_ioctl(struct file *file, u_int cmd, u_long arg)
240{
241 int ret = 0;
242 struct geu_arg geu_arg;
243
244 if (copy_from_user(&geu_arg, (void __user *)arg, sizeof(geu_arg)))
245 return -EFAULT;
246
247 switch (cmd) {
248 case GEU_READ_OEMHASHKEY:
249 ret = asr_fuse_iotcl_read_key_hash((void __user *)geu_arg.arg0,
250 geu_arg.arg1);
251 break;
252 case GEU_READ_LIFECYCLE:
253 ret = asr_fuse_iotcl_read_life_cycle((void __user *)geu_arg.arg0,
254 geu_arg.arg1);
255 break;
256 case GEU_READ_OEM_UUID:
257 ret = asr_fuse_iotcl_read_oem_uid((void __user *)geu_arg.arg0,
258 (void __user *)geu_arg.arg1);
259 break;
260 case GEU_BURN_SIM_LOCK:
261 ret = asr_fuse_iotcl_burn_simlock((void __user *)arg);
262 break;
263 case GEU_GET_SIM_LOCK:
264 ret = asr_fuse_iotcl_get_simlock((void __user *)arg);
265 break;
266 case GEU_GET_TRUST_MODE:
267 ret = asr_fuse_iotcl_get_trust_mode((void __user *)arg);
268 break;
269 default:
270 pr_err("asr fuse: iotcl invald command %x\n", cmd);
271 ret = -EINVAL;
272 }
273
274 return ret;
275}
276
277static int asr_fuse_open(struct inode *inode, struct file *file)
278{
279 return 0;
280}
281
282static int asr_fuse_close(struct inode *inode, struct file *file)
283{
284 return 0;
285}
286
287static const struct file_operations asr_fuse_fops = {
288 .owner = THIS_MODULE,
289 .open = asr_fuse_open,
290 .release = asr_fuse_close,
291 .unlocked_ioctl = asr_fuse_ioctl,
292};
293
294int asr_geu_fuse_register(struct asr_geu_dev *geu_dd)
295{
296 int ret = 0;
297 struct asr_geu_fuse *fuse;
298 struct miscdevice *misc;
299 struct device *dev = geu_dd->dev;
300
301 fuse = devm_kzalloc(dev, sizeof(struct asr_geu_fuse), GFP_KERNEL);
302 if (!fuse)
303 return -ENOMEM;
304
305 geu_dd->asr_fuse = fuse;
306
307 misc = &fuse->fuse_misc;
308
309 /* register the device */
310 misc->name = "geu"; /* to be compatiable with old apps */
311 misc->minor = MISC_DYNAMIC_MINOR;
312 misc->fops = &asr_fuse_fops;
313 misc->this_device = NULL;
314 misc->groups = fuse_dev_groups;
315 ret = misc_register(misc);
316 if (ret < 0) {
317 dev_err(dev,
318 "unable to register device node /dev/geu\n");
319 devm_kfree(dev, fuse);
320 return ret;
321 }
322
323 return 0;
324}
325
326int asr_geu_fuse_unregister(struct asr_geu_dev *geu_dd)
327{
328 struct device *dev = geu_dd->dev;
329 struct asr_geu_fuse *fuse = geu_dd->asr_fuse;
330
331 misc_deregister(&fuse->fuse_misc);
332
333 devm_kfree(dev, fuse);
334
335 return 0;
336}
337
338MODULE_DESCRIPTION("ASR Fuse Read/Write driver with optee-os.");
339MODULE_LICENSE("GPL v2");
340MODULE_AUTHOR("Yu Zhang");