0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <crypto/scatterwalk.h>
0013 #include <linux/kernel.h>
0014 #include <linux/mm.h>
0015 #include <linux/module.h>
0016 #include <linux/scatterlist.h>
0017
0018 static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
0019 {
0020 void *src = out ? buf : sgdata;
0021 void *dst = out ? sgdata : buf;
0022
0023 memcpy(dst, src, nbytes);
0024 }
0025
0026 void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
0027 size_t nbytes, int out)
0028 {
0029 for (;;) {
0030 unsigned int len_this_page = scatterwalk_pagelen(walk);
0031 u8 *vaddr;
0032
0033 if (len_this_page > nbytes)
0034 len_this_page = nbytes;
0035
0036 if (out != 2) {
0037 vaddr = scatterwalk_map(walk);
0038 memcpy_dir(buf, vaddr, len_this_page, out);
0039 scatterwalk_unmap(vaddr);
0040 }
0041
0042 scatterwalk_advance(walk, len_this_page);
0043
0044 if (nbytes == len_this_page)
0045 break;
0046
0047 buf += len_this_page;
0048 nbytes -= len_this_page;
0049
0050 scatterwalk_pagedone(walk, out & 1, 1);
0051 }
0052 }
0053 EXPORT_SYMBOL_GPL(scatterwalk_copychunks);
0054
0055 void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
0056 unsigned int start, unsigned int nbytes, int out)
0057 {
0058 struct scatter_walk walk;
0059 struct scatterlist tmp[2];
0060
0061 if (!nbytes)
0062 return;
0063
0064 sg = scatterwalk_ffwd(tmp, sg, start);
0065
0066 scatterwalk_start(&walk, sg);
0067 scatterwalk_copychunks(buf, &walk, nbytes, out);
0068 scatterwalk_done(&walk, out, 0);
0069 }
0070 EXPORT_SYMBOL_GPL(scatterwalk_map_and_copy);
0071
0072 struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2],
0073 struct scatterlist *src,
0074 unsigned int len)
0075 {
0076 for (;;) {
0077 if (!len)
0078 return src;
0079
0080 if (src->length > len)
0081 break;
0082
0083 len -= src->length;
0084 src = sg_next(src);
0085 }
0086
0087 sg_init_table(dst, 2);
0088 sg_set_page(dst, sg_page(src), src->length - len, src->offset + len);
0089 scatterwalk_crypto_chain(dst, sg_next(src), 2);
0090
0091 return dst;
0092 }
0093 EXPORT_SYMBOL_GPL(scatterwalk_ffwd);