Update CustomDecompress library to support algorithm guid and Update DxeIpl and DxeCo...
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / BaseUefiTianoCustomDecompressLib / BaseUefiTianoCustomDecompressLib.c
1 /**@file
2 UEFI and Custom Decompress Library
3
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <Guid/CustomDecompress.h>
16 #include "BaseUefiTianoCustomDecompressLibInternals.h"
17
18 VOID
19 FillBuf (
20 IN SCRATCH_DATA *Sd,
21 IN UINT16 NumOfBits
22 )
23 /*++
24
25 Routine Description:
26
27 Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
28
29 Arguments:
30
31 Sd - The global scratch data
32 NumOfBits - The number of bits to shift and read.
33
34 Returns: (VOID)
35
36 --*/
37 {
38 Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);
39
40 while (NumOfBits > Sd->mBitCount) {
41
42 Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));
43
44 if (Sd->mCompSize > 0) {
45 //
46 // Get 1 byte into SubBitBuf
47 //
48 Sd->mCompSize--;
49 Sd->mSubBitBuf = 0;
50 Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];
51 Sd->mBitCount = 8;
52
53 } else {
54 //
55 // No more bits from the source, just pad zero bit.
56 //
57 Sd->mSubBitBuf = 0;
58 Sd->mBitCount = 8;
59
60 }
61 }
62
63 Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);
64 Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;
65 }
66
67 UINT32
68 GetBits (
69 IN SCRATCH_DATA *Sd,
70 IN UINT16 NumOfBits
71 )
72 /*++
73
74 Routine Description:
75
76 Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
77 NumOfBits of bits from source. Returns NumOfBits of bits that are
78 popped out.
79
80 Arguments:
81
82 Sd - The global scratch data.
83 NumOfBits - The number of bits to pop and read.
84
85 Returns:
86
87 The bits that are popped out.
88
89 --*/
90 {
91 UINT32 OutBits;
92
93 OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
94
95 FillBuf (Sd, NumOfBits);
96
97 return OutBits;
98 }
99
100 UINT16
101 MakeTable (
102 IN SCRATCH_DATA *Sd,
103 IN UINT16 NumOfChar,
104 IN UINT8 *BitLen,
105 IN UINT16 TableBits,
106 OUT UINT16 *Table
107 )
108 /*++
109
110 Routine Description:
111
112 Creates Huffman Code mapping table according to code length array.
113
114 Arguments:
115
116 Sd - The global scratch data
117 NumOfChar - Number of symbols in the symbol set
118 BitLen - Code length array
119 TableBits - The width of the mapping table
120 Table - The table
121
122 Returns:
123
124 0 - OK.
125 BAD_TABLE - The table is corrupted.
126
127 --*/
128 {
129 UINT16 Count[17];
130 UINT16 Weight[17];
131 UINT16 Start[18];
132 UINT16 *Pointer;
133 UINT16 Index3;
134 volatile UINT16 Index;
135 UINT16 Len;
136 UINT16 Char;
137 UINT16 JuBits;
138 UINT16 Avail;
139 UINT16 NextCode;
140 UINT16 Mask;
141 UINT16 WordOfStart;
142 UINT16 WordOfCount;
143
144 for (Index = 1; Index <= 16; Index++) {
145 Count[Index] = 0;
146 }
147
148 for (Index = 0; Index < NumOfChar; Index++) {
149 Count[BitLen[Index]]++;
150 }
151
152 Start[1] = 0;
153
154 for (Index = 1; Index <= 16; Index++) {
155 WordOfStart = Start[Index];
156 WordOfCount = Count[Index];
157 Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index)));
158 }
159
160 if (Start[17] != 0) {
161 /*(1U << 16)*/
162 return (UINT16) BAD_TABLE;
163 }
164
165 JuBits = (UINT16) (16 - TableBits);
166
167 for (Index = 1; Index <= TableBits; Index++) {
168 Start[Index] >>= JuBits;
169 Weight[Index] = (UINT16) (1U << (TableBits - Index));
170 }
171
172 while (Index <= 16) {
173 Weight[Index] = (UINT16) (1U << (16 - Index));
174 Index++;
175 }
176
177 Index = (UINT16) (Start[TableBits + 1] >> JuBits);
178
179 if (Index != 0) {
180 Index3 = (UINT16) (1U << TableBits);
181 while (Index != Index3) {
182 Table[Index++] = 0;
183 }
184 }
185
186 Avail = NumOfChar;
187 Mask = (UINT16) (1U << (15 - TableBits));
188
189 for (Char = 0; Char < NumOfChar; Char++) {
190
191 Len = BitLen[Char];
192 if (Len == 0) {
193 continue;
194 }
195
196 NextCode = (UINT16) (Start[Len] + Weight[Len]);
197
198 if (Len <= TableBits) {
199
200 for (Index = Start[Len]; Index < NextCode; Index++) {
201 Table[Index] = Char;
202 }
203
204 } else {
205
206 Index3 = Start[Len];
207 Pointer = &Table[Index3 >> JuBits];
208 Index = (UINT16) (Len - TableBits);
209
210 while (Index != 0) {
211 if (*Pointer == 0) {
212 Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;
213 *Pointer = Avail++;
214 }
215
216 if (Index3 & Mask) {
217 Pointer = &Sd->mRight[*Pointer];
218 } else {
219 Pointer = &Sd->mLeft[*Pointer];
220 }
221
222 Index3 <<= 1;
223 Index--;
224 }
225
226 *Pointer = Char;
227
228 }
229
230 Start[Len] = NextCode;
231 }
232 //
233 // Succeeds
234 //
235 return 0;
236 }
237
238 UINT32
239 DecodeP (
240 IN SCRATCH_DATA *Sd
241 )
242 /*++
243
244 Routine Description:
245
246 Decodes a position value.
247
248 Arguments:
249
250 Sd - the global scratch data
251
252 Returns:
253
254 The position value decoded.
255
256 --*/
257 {
258 UINT16 Val;
259 UINT32 Mask;
260 UINT32 Pos;
261
262 Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
263
264 if (Val >= MAXNP) {
265 Mask = 1U << (BITBUFSIZ - 1 - 8);
266
267 do {
268
269 if (Sd->mBitBuf & Mask) {
270 Val = Sd->mRight[Val];
271 } else {
272 Val = Sd->mLeft[Val];
273 }
274
275 Mask >>= 1;
276 } while (Val >= MAXNP);
277 }
278 //
279 // Advance what we have read
280 //
281 FillBuf (Sd, Sd->mPTLen[Val]);
282
283 Pos = Val;
284 if (Val > 1) {
285 Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));
286 }
287
288 return Pos;
289 }
290
291 UINT16
292 ReadPTLen (
293 IN SCRATCH_DATA *Sd,
294 IN UINT16 nn,
295 IN UINT16 nbit,
296 IN UINT16 Special
297 )
298 /*++
299
300 Routine Description:
301
302 Reads code lengths for the Extra Set or the Position Set
303
304 Arguments:
305
306 Sd - The global scratch data
307 nn - Number of symbols
308 nbit - Number of bits needed to represent nn
309 Special - The special symbol that needs to be taken care of
310
311 Returns:
312
313 0 - OK.
314 BAD_TABLE - Table is corrupted.
315
316 --*/
317 {
318 UINT16 Number;
319 UINT16 CharC;
320 volatile UINT16 Index;
321 UINT32 Mask;
322
323 Number = (UINT16) GetBits (Sd, nbit);
324
325 if (Number == 0) {
326 CharC = (UINT16) GetBits (Sd, nbit);
327
328 for (Index = 0; Index < 256; Index++) {
329 Sd->mPTTable[Index] = CharC;
330 }
331
332 for (Index = 0; Index < nn; Index++) {
333 Sd->mPTLen[Index] = 0;
334 }
335
336 return 0;
337 }
338
339 Index = 0;
340
341 while (Index < Number) {
342
343 CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));
344
345 if (CharC == 7) {
346 Mask = 1U << (BITBUFSIZ - 1 - 3);
347 while (Mask & Sd->mBitBuf) {
348 Mask >>= 1;
349 CharC += 1;
350 }
351 }
352
353 FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));
354
355 Sd->mPTLen[Index++] = (UINT8) CharC;
356
357 if (Index == Special) {
358 CharC = (UINT16) GetBits (Sd, 2);
359 while ((INT16) (--CharC) >= 0) {
360 Sd->mPTLen[Index++] = 0;
361 }
362 }
363 }
364
365 while (Index < nn) {
366 Sd->mPTLen[Index++] = 0;
367 }
368
369 return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);
370 }
371
372 VOID
373 ReadCLen (
374 SCRATCH_DATA *Sd
375 )
376 /*++
377
378 Routine Description:
379
380 Reads code lengths for Char&Len Set.
381
382 Arguments:
383
384 Sd - the global scratch data
385
386 Returns: (VOID)
387
388 --*/
389 {
390 UINT16 Number;
391 UINT16 CharC;
392 volatile UINT16 Index;
393 UINT32 Mask;
394
395 Number = (UINT16) GetBits (Sd, CBIT);
396
397 if (Number == 0) {
398 CharC = (UINT16) GetBits (Sd, CBIT);
399
400 for (Index = 0; Index < NC; Index++) {
401 Sd->mCLen[Index] = 0;
402 }
403
404 for (Index = 0; Index < 4096; Index++) {
405 Sd->mCTable[Index] = CharC;
406 }
407
408 return ;
409 }
410
411 Index = 0;
412 while (Index < Number) {
413
414 CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
415 if (CharC >= NT) {
416 Mask = 1U << (BITBUFSIZ - 1 - 8);
417
418 do {
419
420 if (Mask & Sd->mBitBuf) {
421 CharC = Sd->mRight[CharC];
422 } else {
423 CharC = Sd->mLeft[CharC];
424 }
425
426 Mask >>= 1;
427
428 } while (CharC >= NT);
429 }
430 //
431 // Advance what we have read
432 //
433 FillBuf (Sd, Sd->mPTLen[CharC]);
434
435 if (CharC <= 2) {
436
437 if (CharC == 0) {
438 CharC = 1;
439 } else if (CharC == 1) {
440 CharC = (UINT16) (GetBits (Sd, 4) + 3);
441 } else if (CharC == 2) {
442 CharC = (UINT16) (GetBits (Sd, CBIT) + 20);
443 }
444
445 while ((INT16) (--CharC) >= 0) {
446 Sd->mCLen[Index++] = 0;
447 }
448
449 } else {
450
451 Sd->mCLen[Index++] = (UINT8) (CharC - 2);
452
453 }
454 }
455
456 while (Index < NC) {
457 Sd->mCLen[Index++] = 0;
458 }
459
460 MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);
461
462 return ;
463 }
464
465 UINT16
466 DecodeC (
467 SCRATCH_DATA *Sd
468 )
469 /*++
470
471 Routine Description:
472
473 Decode a character/length value.
474
475 Arguments:
476
477 Sd - The global scratch data.
478
479 Returns:
480
481 The value decoded.
482
483 --*/
484 {
485 UINT16 Index2;
486 UINT32 Mask;
487
488 if (Sd->mBlockSize == 0) {
489 //
490 // Starting a new block
491 //
492 Sd->mBlockSize = (UINT16) GetBits (Sd, 16);
493 Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);
494 if (Sd->mBadTableFlag != 0) {
495 return 0;
496 }
497
498 ReadCLen (Sd);
499
500 Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));
501 if (Sd->mBadTableFlag != 0) {
502 return 0;
503 }
504 }
505
506 Sd->mBlockSize--;
507 Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];
508
509 if (Index2 >= NC) {
510 Mask = 1U << (BITBUFSIZ - 1 - 12);
511
512 do {
513 if (Sd->mBitBuf & Mask) {
514 Index2 = Sd->mRight[Index2];
515 } else {
516 Index2 = Sd->mLeft[Index2];
517 }
518
519 Mask >>= 1;
520 } while (Index2 >= NC);
521 }
522 //
523 // Advance what we have read
524 //
525 FillBuf (Sd, Sd->mCLen[Index2]);
526
527 return Index2;
528 }
529
530 VOID
531 Decode (
532 SCRATCH_DATA *Sd
533 )
534 /*++
535
536 Routine Description:
537
538 Decode the source data and put the resulting data into the destination buffer.
539
540 Arguments:
541
542 Sd - The global scratch data
543
544 Returns: (VOID)
545
546 --*/
547 {
548 UINT16 BytesRemain;
549 UINT32 DataIdx;
550 UINT16 CharC;
551
552 BytesRemain = (UINT16) (-1);
553
554 DataIdx = 0;
555
556 for (;;) {
557 CharC = DecodeC (Sd);
558 if (Sd->mBadTableFlag != 0) {
559 goto Done ;
560 }
561
562 if (CharC < 256) {
563 //
564 // Process an Original character
565 //
566 if (Sd->mOutBuf >= Sd->mOrigSize) {
567 goto Done ;
568 } else {
569 Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;
570 }
571
572 } else {
573 //
574 // Process a Pointer
575 //
576 CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));
577
578 BytesRemain = CharC;
579
580 DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;
581
582 BytesRemain--;
583 while ((INT16) (BytesRemain) >= 0) {
584 Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
585 if (Sd->mOutBuf >= Sd->mOrigSize) {
586 goto Done ;
587 }
588
589 BytesRemain--;
590 }
591 }
592 }
593
594 Done:
595 return ;
596 }
597
598 RETURN_STATUS
599 EFIAPI
600 UefiDecompressGetInfo (
601 IN CONST VOID *Source,
602 IN UINT32 SourceSize,
603 OUT UINT32 *DestinationSize,
604 OUT UINT32 *ScratchSize
605 )
606 /*++
607
608 Routine Description:
609
610 The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
611
612 Arguments:
613
614 Source - The source buffer containing the compressed data.
615 SourceSize - The size of source buffer
616 DestinationSize - The size of destination buffer.
617 ScratchSize - The size of scratch buffer.
618
619 Returns:
620
621 RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
622 RETURN_INVALID_PARAMETER - The source data is corrupted
623
624 --*/
625 {
626 UINT32 CompressedSize;
627
628 ASSERT (Source != NULL);
629 ASSERT (DestinationSize != NULL);
630 ASSERT (ScratchSize != NULL);
631
632 *ScratchSize = sizeof (SCRATCH_DATA);
633
634 if (SourceSize < 8) {
635 return RETURN_INVALID_PARAMETER;
636 }
637
638 CopyMem (&CompressedSize, Source, sizeof (UINT32));
639 CopyMem (DestinationSize, (VOID *)((UINT8 *)Source + 4), sizeof (UINT32));
640
641 if (SourceSize < (CompressedSize + 8)) {
642 return RETURN_INVALID_PARAMETER;
643 }
644
645 return RETURN_SUCCESS;
646 }
647
648 RETURN_STATUS
649 EFIAPI
650 UefiTianoDecompress (
651 IN CONST VOID *Source,
652 IN OUT VOID *Destination,
653 IN OUT VOID *Scratch,
654 IN UINT32 Version
655 )
656 /*++
657
658 Routine Description:
659
660 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
661
662 Arguments:
663
664 Source - The source buffer containing the compressed data.
665 Destination - The destination buffer to store the decompressed data
666 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
667 Version - 1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm
668
669 Returns:
670
671 RETURN_SUCCESS - Decompression is successfull
672 RETURN_INVALID_PARAMETER - The source data is corrupted
673
674 --*/
675 {
676 volatile UINT32 Index;
677 UINT32 CompSize;
678 UINT32 OrigSize;
679 SCRATCH_DATA *Sd;
680 CONST UINT8 *Src;
681 UINT8 *Dst;
682
683 ASSERT (Source != NULL);
684 ASSERT (Destination != NULL);
685 ASSERT (Scratch != NULL);
686
687 Src = Source;
688 Dst = Destination;
689
690 Sd = (SCRATCH_DATA *) Scratch;
691
692 CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
693 OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
694
695 //
696 // If compressed file size is 0, return
697 //
698 if (OrigSize == 0) {
699 return RETURN_SUCCESS;
700 }
701
702 Src = Src + 8;
703
704 for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {
705 ((UINT8 *) Sd)[Index] = 0;
706 }
707 //
708 // The length of the field 'Position Set Code Length Array Size' in Block Header.
709 // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
710 // For Tiano de/compression algorithm(Version 2), mPBit = 5
711 //
712 switch (Version) {
713 case 1 :
714 Sd->mPBit = 4;
715 break;
716 case 2 :
717 Sd->mPBit = 5;
718 break;
719 default:
720 ASSERT (FALSE);
721 }
722 Sd->mSrcBase = (UINT8 *)Src;
723 Sd->mDstBase = Dst;
724 Sd->mCompSize = CompSize;
725 Sd->mOrigSize = OrigSize;
726
727 //
728 // Fill the first BITBUFSIZ bits
729 //
730 FillBuf (Sd, BITBUFSIZ);
731
732 //
733 // Decompress it
734 //
735 Decode (Sd);
736
737 if (Sd->mBadTableFlag != 0) {
738 //
739 // Something wrong with the source
740 //
741 return RETURN_INVALID_PARAMETER;
742 }
743
744 return RETURN_SUCCESS;
745 }
746
747 RETURN_STATUS
748 EFIAPI
749 UefiDecompress (
750 IN CONST VOID *Source,
751 IN OUT VOID *Destination,
752 IN OUT VOID *Scratch
753 )
754 /*++
755
756 Routine Description:
757
758 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
759
760 Arguments:
761
762 Source - The source buffer containing the compressed data.
763 Destination - The destination buffer to store the decompressed data
764 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
765
766 Returns:
767
768 RETURN_SUCCESS - Decompression is successfull
769 RETURN_INVALID_PARAMETER - The source data is corrupted
770
771 --*/
772 {
773 return UefiTianoDecompress (Source, Destination, Scratch, 1);
774 }
775
776 RETURN_STATUS
777 EFIAPI
778 CustomDecompressGetInfo (
779 IN CONST GUID *DecompressGuid,
780 IN CONST VOID *Source,
781 IN UINT32 SourceSize,
782 OUT UINT32 *DestinationSize,
783 OUT UINT32 *ScratchSize
784 )
785 /*++
786
787 Routine Description:
788
789 The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
790
791 Arguments:
792 DecompressGuid The guid matches this decompress method.
793 Source - The source buffer containing the compressed data.
794 SourceSize - The size of source buffer
795 DestinationSize - The size of destination buffer.
796 ScratchSize - The size of scratch buffer.
797
798 Returns:
799
800 RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
801 RETURN_INVALID_PARAMETER - The source data is corrupted
802 RETURN_UNSUPPORTED - Decompress method is not supported.
803
804 --*/
805 {
806 if (CompareGuid (DecompressGuid, &gTianoCustomDecompressGuid)) {
807 return UefiDecompressGetInfo (Source, SourceSize, DestinationSize, ScratchSize);
808 } else {
809 return RETURN_UNSUPPORTED;
810 }
811 }
812
813 RETURN_STATUS
814 EFIAPI
815 CustomDecompress (
816 IN CONST GUID *DecompressGuid,
817 IN CONST VOID *Source,
818 IN OUT VOID *Destination,
819 IN OUT VOID *Scratch
820 )
821 /*++
822
823 Routine Description:
824
825 The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
826
827 Arguments:
828 DecompressGuid The guid matches this decompress method.
829 Source - The source buffer containing the compressed data.
830 Destination - The destination buffer to store the decompressed data
831 Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
832
833 Returns:
834
835 RETURN_SUCCESS - Decompression is successfull
836 RETURN_INVALID_PARAMETER - The source data is corrupted
837 RETURN_UNSUPPORTED - Decompress method is not supported.
838
839 --*/
840 {
841 if (CompareGuid (DecompressGuid, &gTianoCustomDecompressGuid)) {
842 return UefiTianoDecompress (Source, Destination, Scratch, 2);
843 } else {
844 return RETURN_UNSUPPORTED;
845 }
846 }
847
848 /**
849 Get decompress method guid list.
850
851 @param[in, out] AlgorithmGuidTable The decompress method guid list.
852 @param[in, out] NumberOfAlgorithms The number of decompress methods.
853
854 @retval RETURN_SUCCESS Get all algorithmes list successfully.
855 @retval RETURN_INVALID_PARAMETER Input paramter error.
856 @retval RETURN_OUT_OF_RESOURCES Source is not enough.
857
858 **/
859 RETURN_STATUS
860 EFIAPI
861 CustomDecompressGetAlgorithms (
862 IN OUT GUID **AlgorithmGuidTable,
863 IN OUT UINTN *NumberOfAlgorithms
864 )
865 {
866 if (NumberOfAlgorithms == NULL) {
867 return RETURN_INVALID_PARAMETER;
868 }
869
870 if (*NumberOfAlgorithms < 1) {
871 *NumberOfAlgorithms = 1;
872 return RETURN_OUT_OF_RESOURCES;
873 }
874
875 if (AlgorithmGuidTable == NULL) {
876 return RETURN_INVALID_PARAMETER;
877 }
878
879 AlgorithmGuidTable [0] = &gTianoCustomDecompressGuid;
880 *NumberOfAlgorithms = 1;
881
882 return RETURN_SUCCESS;
883 }