diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /crypto/scatterwalk.c | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'crypto/scatterwalk.c')
-rw-r--r-- | crypto/scatterwalk.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c new file mode 100644 index 000000000..16f6ba896 --- /dev/null +++ b/crypto/scatterwalk.c | |||
@@ -0,0 +1,93 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * Cryptographic API. | ||
4 | * | ||
5 | * Cipher operations. | ||
6 | * | ||
7 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> | ||
8 | * 2002 Adam J. Richter <adam@yggdrasil.com> | ||
9 | * 2004 Jean-Luc Cooke <jlcooke@certainkey.com> | ||
10 | */ | ||
11 | |||
12 | #include <crypto/scatterwalk.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/mm.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/scatterlist.h> | ||
17 | |||
18 | static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) | ||
19 | { | ||
20 | void *src = out ? buf : sgdata; | ||
21 | void *dst = out ? sgdata : buf; | ||
22 | |||
23 | memcpy(dst, src, nbytes); | ||
24 | } | ||
25 | |||
26 | void scatterwalk_copychunks(void *buf, struct scatter_walk *walk, | ||
27 | size_t nbytes, int out) | ||
28 | { | ||
29 | for (;;) { | ||
30 | unsigned int len_this_page = scatterwalk_pagelen(walk); | ||
31 | u8 *vaddr; | ||
32 | |||
33 | if (len_this_page > nbytes) | ||
34 | len_this_page = nbytes; | ||
35 | |||
36 | if (out != 2) { | ||
37 | vaddr = scatterwalk_map(walk); | ||
38 | memcpy_dir(buf, vaddr, len_this_page, out); | ||
39 | scatterwalk_unmap(vaddr); | ||
40 | } | ||
41 | |||
42 | scatterwalk_advance(walk, len_this_page); | ||
43 | |||
44 | if (nbytes == len_this_page) | ||
45 | break; | ||
46 | |||
47 | buf += len_this_page; | ||
48 | nbytes -= len_this_page; | ||
49 | |||
50 | scatterwalk_pagedone(walk, out & 1, 1); | ||
51 | } | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(scatterwalk_copychunks); | ||
54 | |||
55 | void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg, | ||
56 | unsigned int start, unsigned int nbytes, int out) | ||
57 | { | ||
58 | struct scatter_walk walk; | ||
59 | struct scatterlist tmp[2]; | ||
60 | |||
61 | if (!nbytes) | ||
62 | return; | ||
63 | |||
64 | sg = scatterwalk_ffwd(tmp, sg, start); | ||
65 | |||
66 | scatterwalk_start(&walk, sg); | ||
67 | scatterwalk_copychunks(buf, &walk, nbytes, out); | ||
68 | scatterwalk_done(&walk, out, 0); | ||
69 | } | ||
70 | EXPORT_SYMBOL_GPL(scatterwalk_map_and_copy); | ||
71 | |||
72 | struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2], | ||
73 | struct scatterlist *src, | ||
74 | unsigned int len) | ||
75 | { | ||
76 | for (;;) { | ||
77 | if (!len) | ||
78 | return src; | ||
79 | |||
80 | if (src->length > len) | ||
81 | break; | ||
82 | |||
83 | len -= src->length; | ||
84 | src = sg_next(src); | ||
85 | } | ||
86 | |||
87 | sg_init_table(dst, 2); | ||
88 | sg_set_page(dst, sg_page(src), src->length - len, src->offset + len); | ||
89 | scatterwalk_crypto_chain(dst, sg_next(src), 2); | ||
90 | |||
91 | return dst; | ||
92 | } | ||
93 | EXPORT_SYMBOL_GPL(scatterwalk_ffwd); | ||