diff options
author | Tadeusz Struk <tadeusz.struk@intel.com> | 2015-10-08 12:26:50 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2015-10-14 10:23:00 -0400 |
commit | 2d4d1eea540b27c72488fd1914674c42473d53df (patch) | |
tree | 104068ce8d5e084fcb2ed7eb0fd626c15b4311f0 /lib/mpi | |
parent | 9ad92bdff7062d9925754607f5a92b4f651fc7d3 (diff) |
lib/mpi: Add mpi sgl helpers
Add mpi_read_raw_from_sgl and mpi_write_to_sgl helpers.
Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'lib/mpi')
-rw-r--r-- | lib/mpi/mpicoder.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 95c52a95259e..c20ef27ad876 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c | |||
@@ -319,3 +319,199 @@ int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign) | |||
319 | return 0; | 319 | return 0; |
320 | } | 320 | } |
321 | EXPORT_SYMBOL_GPL(mpi_set_buffer); | 321 | EXPORT_SYMBOL_GPL(mpi_set_buffer); |
322 | |||
323 | /** | ||
324 | * mpi_write_to_sgl() - Funnction exports MPI to an sgl (msb first) | ||
325 | * | ||
326 | * This function works in the same way as the mpi_read_buffer, but it | ||
327 | * takes an sgl instead of u8 * buf. | ||
328 | * | ||
329 | * @a: a multi precision integer | ||
330 | * @sgl: scatterlist to write to. Needs to be at least | ||
331 | * mpi_get_size(a) long. | ||
332 | * @nbytes: in/out param - it has the be set to the maximum number of | ||
333 | * bytes that can be written to sgl. This has to be at least | ||
334 | * the size of the integer a. On return it receives the actual | ||
335 | * length of the data written. | ||
336 | * @sign: if not NULL, it will be set to the sign of a. | ||
337 | * | ||
338 | * Return: 0 on success or error code in case of error | ||
339 | */ | ||
340 | int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, | ||
341 | int *sign) | ||
342 | { | ||
343 | u8 *p, *p2; | ||
344 | mpi_limb_t alimb, alimb2; | ||
345 | unsigned int n = mpi_get_size(a); | ||
346 | int i, x, y = 0, lzeros = 0, buf_len; | ||
347 | |||
348 | if (!nbytes || *nbytes < n) | ||
349 | return -EINVAL; | ||
350 | |||
351 | if (sign) | ||
352 | *sign = a->sign; | ||
353 | |||
354 | p = (void *)&a->d[a->nlimbs] - 1; | ||
355 | |||
356 | for (i = a->nlimbs * sizeof(alimb) - 1; i >= 0; i--, p--) { | ||
357 | if (!*p) | ||
358 | lzeros++; | ||
359 | else | ||
360 | break; | ||
361 | } | ||
362 | |||
363 | *nbytes = n - lzeros; | ||
364 | buf_len = sgl->length; | ||
365 | p2 = sg_virt(sgl); | ||
366 | |||
367 | for (i = a->nlimbs - 1; i >= 0; i--) { | ||
368 | alimb = a->d[i]; | ||
369 | p = (u8 *)&alimb2; | ||
370 | #if BYTES_PER_MPI_LIMB == 4 | ||
371 | *p++ = alimb >> 24; | ||
372 | *p++ = alimb >> 16; | ||
373 | *p++ = alimb >> 8; | ||
374 | *p++ = alimb; | ||
375 | #elif BYTES_PER_MPI_LIMB == 8 | ||
376 | *p++ = alimb >> 56; | ||
377 | *p++ = alimb >> 48; | ||
378 | *p++ = alimb >> 40; | ||
379 | *p++ = alimb >> 32; | ||
380 | *p++ = alimb >> 24; | ||
381 | *p++ = alimb >> 16; | ||
382 | *p++ = alimb >> 8; | ||
383 | *p++ = alimb; | ||
384 | #else | ||
385 | #error please implement for this limb size. | ||
386 | #endif | ||
387 | if (lzeros > 0) { | ||
388 | if (lzeros >= sizeof(alimb)) { | ||
389 | p -= sizeof(alimb); | ||
390 | continue; | ||
391 | } else { | ||
392 | mpi_limb_t *limb1 = (void *)p - sizeof(alimb); | ||
393 | mpi_limb_t *limb2 = (void *)p - sizeof(alimb) | ||
394 | + lzeros; | ||
395 | *limb1 = *limb2; | ||
396 | p -= lzeros; | ||
397 | y = lzeros; | ||
398 | } | ||
399 | lzeros -= sizeof(alimb); | ||
400 | } | ||
401 | |||
402 | p = p - (sizeof(alimb) - y); | ||
403 | |||
404 | for (x = 0; x < sizeof(alimb) - y; x++) { | ||
405 | if (!buf_len) { | ||
406 | sgl = sg_next(sgl); | ||
407 | if (!sgl) | ||
408 | return -EINVAL; | ||
409 | buf_len = sgl->length; | ||
410 | p2 = sg_virt(sgl); | ||
411 | } | ||
412 | *p2++ = *p++; | ||
413 | buf_len--; | ||
414 | } | ||
415 | y = 0; | ||
416 | } | ||
417 | return 0; | ||
418 | } | ||
419 | EXPORT_SYMBOL_GPL(mpi_write_to_sgl); | ||
420 | |||
421 | /* | ||
422 | * mpi_read_raw_from_sgl() - Function allocates an MPI and populates it with | ||
423 | * data from the sgl | ||
424 | * | ||
425 | * This function works in the same way as the mpi_read_raw_data, but it | ||
426 | * takes an sgl instead of void * buffer. i.e. it allocates | ||
427 | * a new MPI and reads the content of the sgl to the MPI. | ||
428 | * | ||
429 | * @sgl: scatterlist to read from | ||
430 | * @len: number of bytes to read | ||
431 | * | ||
432 | * Return: Pointer to a new MPI or NULL on error | ||
433 | */ | ||
434 | MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int len) | ||
435 | { | ||
436 | struct scatterlist *sg; | ||
437 | int x, i, j, z, lzeros, ents; | ||
438 | unsigned int nbits, nlimbs, nbytes; | ||
439 | mpi_limb_t a; | ||
440 | MPI val = NULL; | ||
441 | |||
442 | lzeros = 0; | ||
443 | ents = sg_nents(sgl); | ||
444 | |||
445 | for_each_sg(sgl, sg, ents, i) { | ||
446 | const u8 *buff = sg_virt(sg); | ||
447 | int len = sg->length; | ||
448 | |||
449 | while (len-- && !*buff++) | ||
450 | lzeros++; | ||
451 | |||
452 | if (len && *buff) | ||
453 | break; | ||
454 | |||
455 | ents--; | ||
456 | lzeros = 0; | ||
457 | } | ||
458 | |||
459 | sgl = sg; | ||
460 | |||
461 | if (!ents) | ||
462 | nbytes = 0; | ||
463 | else | ||
464 | nbytes = len - lzeros; | ||
465 | |||
466 | nbits = nbytes * 8; | ||
467 | if (nbits > MAX_EXTERN_MPI_BITS) { | ||
468 | pr_info("MPI: mpi too large (%u bits)\n", nbits); | ||
469 | return NULL; | ||
470 | } | ||
471 | |||
472 | if (nbytes > 0) | ||
473 | nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)); | ||
474 | else | ||
475 | nbits = 0; | ||
476 | |||
477 | nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); | ||
478 | val = mpi_alloc(nlimbs); | ||
479 | if (!val) | ||
480 | return NULL; | ||
481 | |||
482 | val->nbits = nbits; | ||
483 | val->sign = 0; | ||
484 | val->nlimbs = nlimbs; | ||
485 | |||
486 | if (nbytes == 0) | ||
487 | return val; | ||
488 | |||
489 | j = nlimbs - 1; | ||
490 | a = 0; | ||
491 | z = 0; | ||
492 | x = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; | ||
493 | x %= BYTES_PER_MPI_LIMB; | ||
494 | |||
495 | for_each_sg(sgl, sg, ents, i) { | ||
496 | const u8 *buffer = sg_virt(sg) + lzeros; | ||
497 | int len = sg->length - lzeros; | ||
498 | int buf_shift = x; | ||
499 | |||
500 | if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB)) | ||
501 | len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB); | ||
502 | |||
503 | for (; x < len + buf_shift; x++) { | ||
504 | a <<= 8; | ||
505 | a |= *buffer++; | ||
506 | if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { | ||
507 | val->d[j--] = a; | ||
508 | a = 0; | ||
509 | } | ||
510 | } | ||
511 | z += x; | ||
512 | x = 0; | ||
513 | lzeros = 0; | ||
514 | } | ||
515 | return val; | ||
516 | } | ||
517 | EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl); | ||