diff options
| author | Chris Zankel <chris@zankel.net> | 2016-01-21 00:16:13 -0500 |
|---|---|---|
| committer | Chris Zankel <chris@zankel.net> | 2016-01-21 00:16:13 -0500 |
| commit | d1208404dd477c142680437137c9996b95bfd508 (patch) | |
| tree | 0cba53f59f487c0de2b1a0d9fb1b11ae27de96ec /lib/mpi/mpicoder.c | |
| parent | afaa7c542cc9c4d8a99ba252a8ea5e8bc7c897e2 (diff) | |
| parent | afd2ff9b7e1b367172f18ba7f693dfb62bdcb2dc (diff) | |
Merge tag 'v4.4'
Linux 4.4
Diffstat (limited to 'lib/mpi/mpicoder.c')
| -rw-r--r-- | lib/mpi/mpicoder.c | 201 |
1 files changed, 200 insertions, 1 deletions
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 95c52a95259e..3db76b8c1115 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
| 22 | #include <asm-generic/bitops/count_zeros.h> | 22 | #include <linux/count_zeros.h> |
| 23 | #include "mpi-internal.h" | 23 | #include "mpi-internal.h" |
| 24 | 24 | ||
| 25 | #define MAX_EXTERN_MPI_BITS 16384 | 25 | #define MAX_EXTERN_MPI_BITS 16384 |
| @@ -319,3 +319,202 @@ 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 | len--; | ||
| 452 | buff++; | ||
| 453 | } | ||
| 454 | |||
| 455 | if (len && *buff) | ||
| 456 | break; | ||
| 457 | |||
| 458 | ents--; | ||
| 459 | lzeros = 0; | ||
| 460 | } | ||
| 461 | |||
| 462 | sgl = sg; | ||
| 463 | |||
| 464 | if (!ents) | ||
| 465 | nbytes = 0; | ||
| 466 | else | ||
| 467 | nbytes = len - lzeros; | ||
| 468 | |||
| 469 | nbits = nbytes * 8; | ||
| 470 | if (nbits > MAX_EXTERN_MPI_BITS) { | ||
| 471 | pr_info("MPI: mpi too large (%u bits)\n", nbits); | ||
| 472 | return NULL; | ||
| 473 | } | ||
| 474 | |||
| 475 | if (nbytes > 0) | ||
| 476 | nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)); | ||
| 477 | else | ||
| 478 | nbits = 0; | ||
| 479 | |||
| 480 | nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); | ||
| 481 | val = mpi_alloc(nlimbs); | ||
| 482 | if (!val) | ||
| 483 | return NULL; | ||
| 484 | |||
| 485 | val->nbits = nbits; | ||
| 486 | val->sign = 0; | ||
| 487 | val->nlimbs = nlimbs; | ||
| 488 | |||
| 489 | if (nbytes == 0) | ||
| 490 | return val; | ||
| 491 | |||
| 492 | j = nlimbs - 1; | ||
| 493 | a = 0; | ||
| 494 | z = 0; | ||
| 495 | x = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; | ||
| 496 | x %= BYTES_PER_MPI_LIMB; | ||
| 497 | |||
| 498 | for_each_sg(sgl, sg, ents, i) { | ||
| 499 | const u8 *buffer = sg_virt(sg) + lzeros; | ||
| 500 | int len = sg->length - lzeros; | ||
| 501 | int buf_shift = x; | ||
| 502 | |||
| 503 | if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB)) | ||
| 504 | len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB); | ||
| 505 | |||
| 506 | for (; x < len + buf_shift; x++) { | ||
| 507 | a <<= 8; | ||
| 508 | a |= *buffer++; | ||
| 509 | if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { | ||
| 510 | val->d[j--] = a; | ||
| 511 | a = 0; | ||
| 512 | } | ||
| 513 | } | ||
| 514 | z += x; | ||
| 515 | x = 0; | ||
| 516 | lzeros = 0; | ||
| 517 | } | ||
| 518 | return val; | ||
| 519 | } | ||
| 520 | EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl); | ||
