2 * Exynos FMP cipher driver
4 * Copyright (C) 2016 Samsung Electronics Co., Ltd.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
13 #include <linux/of_platform.h>
14 #include <linux/crypto.h>
15 #include <linux/buffer_head.h>
16 #include <linux/genhd.h>
17 #include <linux/delay.h>
19 #include <linux/blk_types.h>
20 #include <crypto/fmp.h>
24 #define MAX_SCAN_PART (50)
25 #define MAX_RETRY_COUNT (0x100000)
27 static dev_t
find_devt_for_test(struct exynos_fmp
*fmp
,
28 struct fmp_test_data
*data
)
33 uint64_t size_list
[MAX_SCAN_PART
];
34 dev_t devt_list
[MAX_SCAN_PART
];
35 dev_t devt_scan
, devt
;
36 struct block_device
*bdev
;
37 struct device
*dev
= fmp
->dev
;
38 fmode_t fmode
= FMODE_WRITE
| FMODE_READ
;
40 memset(size_list
, 0, sizeof(size_list
));
41 memset(devt_list
, 0, sizeof(devt_list
));
43 for (i
= 1; i
< MAX_SCAN_PART
; i
++) {
44 devt_scan
= blk_lookup_devt(data
->block_type
, i
);
45 bdev
= blkdev_get_by_dev(devt_scan
, fmode
, NULL
);
50 (uint64_t) i_size_read(bdev
->bd_inode
);
51 devt_list
[idx
++] = devt_scan
;
52 blkdev_put(bdev
, fmode
);
60 for (i
= 0; i
< idx
; i
++) {
65 if (size
< size_list
[i
])
69 bdev
= blkdev_get_by_dev(devt
, fmode
, NULL
);
70 dev_dbg(dev
, "Found partno %d for FMP test\n",
71 bdev
->bd_part
->partno
);
72 blkdev_put(bdev
, fmode
);
74 } while (count
< MAX_RETRY_COUNT
);
75 dev_err(dev
, "Block device isn't initialized yet for FMP test\n");
79 static int get_fmp_host_type(struct device
*dev
,
80 struct fmp_test_data
*data
)
83 struct device_node
*node
= dev
->of_node
;
87 of_property_read_string_index(node
, "exynos,block-type", 0, &type
);
89 pr_err("%s: Could not get block type\n", __func__
);
92 strlcpy(data
->block_type
, type
, FMP_BLOCK_TYPE_NAME_LEN
);
96 static int get_fmp_test_block_offset(struct device
*dev
,
97 struct fmp_test_data
*data
)
100 struct device_node
*node
= dev
->of_node
;
103 ret
= of_property_read_u32(node
, "exynos,fips-block_offset", &offset
);
105 pr_err("%s: Could not get fips test block offset\n", __func__
);
109 data
->test_block_offset
= offset
;
114 /* test block device init for fmp test */
115 struct fmp_test_data
*fmp_test_init(struct exynos_fmp
*fmp
)
118 struct fmp_test_data
*data
;
121 struct super_block
*sb
;
122 unsigned long blocksize
;
123 unsigned char blocksize_bits
;
124 fmode_t fmode
= FMODE_WRITE
| FMODE_READ
;
127 pr_err("%s: Invalid exynos fmp struct\n", __func__
);
130 data
= kmalloc(sizeof(struct fmp_test_data
), GFP_KERNEL
);
135 ret
= get_fmp_host_type(dev
, data
);
137 dev_err(dev
, "%s: Fail to get host type. ret(%d)", __func__
,
141 data
->devt
= find_devt_for_test(fmp
, data
);
143 dev_err(dev
, "%s: Fail to find devt for self test\n", __func__
);
146 data
->bdev
= blkdev_get_by_dev(data
->devt
, fmode
, NULL
);
147 if (IS_ERR(data
->bdev
)) {
148 dev_err(dev
, "%s: Fail to open block device\n", __func__
);
151 ret
= get_fmp_test_block_offset(dev
, data
);
153 dev_err(dev
, "%s: Fail to get fips offset. ret(%d)\n",
157 inode
= data
->bdev
->bd_inode
;
159 blocksize
= sb
->s_blocksize
;
160 blocksize_bits
= sb
->s_blocksize_bits
;
162 (i_size_read(inode
) -
163 (blocksize
* data
->test_block_offset
)) >> blocksize_bits
;
171 int fmp_cipher_run(struct exynos_fmp
*fmp
, struct fmp_test_data
*fdata
,
172 uint8_t *data
, uint32_t len
, bool bypass
, uint32_t write
,
173 void *priv
, struct fmp_crypto_info
*ci
)
177 static struct buffer_head
*bh
;
181 if (!fmp
|| !fdata
|| !ci
) {
182 pr_err("%s: Invalid fmp struct: %p, %p, %p\n",
183 __func__
, fmp
, fdata
, ci
);
188 bh
= __getblk(fdata
->bdev
, fdata
->sector
, FMP_BLK_SIZE
);
190 dev_err(dev
, "%s: Fail to get block from bdev\n", __func__
);
194 /* set algo_mode for test */
195 org_algo_mode
= ci
->algo_mode
;
197 ci
->algo_mode
= EXYNOS_FMP_BYPASS_MODE
;
198 ci
->algo_mode
|= EXYNOS_FMP_ALGO_MODE_TEST
;
201 /* priv is diskc for crypto test. */
203 /* ci is fmp_test_data->ci */
204 fmp
->test_data
= fdata
;
207 ci
->enc_mode
= EXYNOS_FMP_FILE_ENC
;
210 /* ci is crypto_tfm_ctx(tfm) */
211 bh
->b_private
= priv
;
213 op_flags
= REQ_CRYPT
;
215 if (write
== WRITE_MODE
) {
216 memcpy(bh
->b_data
, data
, len
);
217 set_buffer_dirty(bh
);
218 ret
= __sync_dirty_buffer(bh
, op_flags
| REQ_SYNC
);
220 dev_err(dev
, "%s: IO error syncing for write mode\n",
225 memset(bh
->b_data
, 0, FMP_BLK_SIZE
);
228 bh
->b_end_io
= end_buffer_read_sync
;
229 submit_bh(REQ_OP_READ
, REQ_SYNC
| REQ_PRIO
| op_flags
, bh
);
231 if (unlikely(!buffer_uptodate(bh
))) {
235 memcpy(data
, bh
->b_data
, len
);
239 ci
->algo_mode
= org_algo_mode
;
244 int fmp_test_crypt(struct exynos_fmp
*fmp
, struct fmp_test_data
*fdata
,
245 uint8_t *src
, uint8_t *dst
, uint32_t len
, uint32_t enc
,
246 void *priv
, struct fmp_crypto_info
*ci
)
251 pr_err("%s: Invalid exynos fmp struct\n", __func__
);
255 if (enc
== ENCRYPT
) {
256 ret
= fmp_cipher_run(fmp
, fdata
, src
, len
, 0,
257 WRITE_MODE
, priv
, ci
);
259 pr_err("Fail to run fmp cipher ret(%d)\n",
263 ret
= fmp_cipher_run(fmp
, fdata
, dst
, len
, 1,
264 READ_MODE
, priv
, ci
);
266 pr_err("Fail to run fmp cipher ret(%d)\n",
270 } else if (enc
== DECRYPT
) {
271 ret
= fmp_cipher_run(fmp
, fdata
, src
, len
, 1,
272 WRITE_MODE
, priv
, ci
);
274 pr_err("Fail to run fmp cipher ret(%d)\n",
278 ret
= fmp_cipher_run(fmp
, fdata
, dst
, len
, 0,
279 READ_MODE
, priv
, ci
);
281 pr_err("Fail to run fmp cipher ret(%d)\n",
286 pr_err("%s: Invalid enc %d mode\n", __func__
, enc
);
295 /* test block device release for fmp test */
296 void fmp_test_exit(struct fmp_test_data
*fdata
)
298 fmode_t fmode
= FMODE_WRITE
| FMODE_READ
;
301 pr_err("%s: Invalid exynos fmp struct\n", __func__
);
305 blkdev_put(fdata
->bdev
, fmode
);