2019-05-27 08:55:01 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-16 15:20:36 -07:00
/*
* Cryptographic API .
*
* Cipher operations .
*
* Copyright ( c ) 2002 James Morris < jmorris @ intercode . com . au >
* 2002 Adam J . Richter < adam @ yggdrasil . com >
* 2004 Jean - Luc Cooke < jlcooke @ certainkey . com >
*/
2007-12-07 18:52:49 +08:00
# include <crypto/scatterwalk.h>
2005-04-16 15:20:36 -07:00
# include <linux/kernel.h>
# include <linux/mm.h>
2006-08-12 21:56:17 +10:00
# include <linux/module.h>
# include <linux/scatterlist.h>
static inline void memcpy_dir ( void * buf , void * sgdata , size_t nbytes , int out )
2005-04-16 15:20:36 -07:00
{
2006-08-12 21:56:17 +10:00
void * src = out ? buf : sgdata ;
void * dst = out ? sgdata : buf ;
memcpy ( dst , src , nbytes ) ;
2005-04-16 15:20:36 -07:00
}
2006-08-12 21:56:17 +10:00
void scatterwalk_copychunks ( void * buf , struct scatter_walk * walk ,
size_t nbytes , int out )
2005-04-16 15:20:36 -07:00
{
2006-08-12 21:56:17 +10:00
for ( ; ; ) {
unsigned int len_this_page = scatterwalk_pagelen ( walk ) ;
u8 * vaddr ;
if ( len_this_page > nbytes )
len_this_page = nbytes ;
2016-07-12 13:17:55 +08:00
if ( out ! = 2 ) {
vaddr = scatterwalk_map ( walk ) ;
memcpy_dir ( buf , vaddr , len_this_page , out ) ;
scatterwalk_unmap ( vaddr ) ;
}
2006-08-12 21:56:17 +10:00
2007-03-31 12:16:20 +10:00
scatterwalk_advance ( walk , len_this_page ) ;
2007-03-21 08:50:12 +11:00
2006-08-12 21:56:17 +10:00
if ( nbytes = = len_this_page )
break ;
buf + = len_this_page ;
nbytes - = len_this_page ;
2005-04-16 15:20:36 -07:00
2016-07-12 13:17:55 +08:00
scatterwalk_pagedone ( walk , out & 1 , 1 ) ;
2005-07-06 13:51:31 -07:00
}
2005-04-16 15:20:36 -07:00
}
2006-08-12 21:56:17 +10:00
EXPORT_SYMBOL_GPL ( scatterwalk_copychunks ) ;
2007-08-29 16:31:34 +08:00
void scatterwalk_map_and_copy ( void * buf , struct scatterlist * sg ,
unsigned int start , unsigned int nbytes , int out )
{
struct scatter_walk walk ;
2015-05-21 15:11:12 +08:00
struct scatterlist tmp [ 2 ] ;
2007-08-29 16:31:34 +08:00
2007-12-14 00:44:11 +08:00
if ( ! nbytes )
return ;
2015-05-21 15:11:12 +08:00
sg = scatterwalk_ffwd ( tmp , sg , start ) ;
2007-08-29 16:31:34 +08:00
2015-05-21 15:11:12 +08:00
scatterwalk_start ( & walk , sg ) ;
2007-08-29 16:31:34 +08:00
scatterwalk_copychunks ( buf , & walk , nbytes , out ) ;
scatterwalk_done ( & walk , out , 0 ) ;
}
EXPORT_SYMBOL_GPL ( scatterwalk_map_and_copy ) ;
2013-08-17 21:42:22 -05:00
2015-05-21 15:10:59 +08:00
struct scatterlist * scatterwalk_ffwd ( struct scatterlist dst [ 2 ] ,
struct scatterlist * src ,
unsigned int len )
{
for ( ; ; ) {
if ( ! len )
return src ;
if ( src - > length > len )
break ;
len - = src - > length ;
src = sg_next ( src ) ;
}
2015-05-27 14:37:27 +08:00
sg_init_table ( dst , 2 ) ;
2015-05-21 15:10:59 +08:00
sg_set_page ( dst , sg_page ( src ) , src - > length - len , src - > offset + len ) ;
2018-07-23 10:01:33 -07:00
scatterwalk_crypto_chain ( dst , sg_next ( src ) , 2 ) ;
2015-05-21 15:10:59 +08:00
return dst ;
}
EXPORT_SYMBOL_GPL ( scatterwalk_ffwd ) ;