2 Utility functions to generate checksum based on 2's complement
5 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 Copyright (c) 2022, Pedro Falcato. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "BaseLibInternals.h"
14 Returns the sum of all elements in a buffer in unit of UINT8.
15 During calculation, the carry bits are dropped.
17 This function calculates the sum of all elements in a buffer
18 in unit of UINT8. The carry bits in result of addition are dropped.
19 The result is returned as UINT8. If Length is Zero, then Zero is
22 If Buffer is NULL, then ASSERT().
23 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
25 @param Buffer The pointer to the buffer to carry out the sum operation.
26 @param Length The size, in bytes, of Buffer.
28 @return Sum The sum of Buffer with carry bits dropped during additions.
34 IN CONST UINT8
*Buffer
,
41 ASSERT (Buffer
!= NULL
);
42 ASSERT (Length
<= (MAX_ADDRESS
- ((UINTN
)Buffer
) + 1));
44 for (Sum
= 0, Count
= 0; Count
< Length
; Count
++) {
45 Sum
= (UINT8
)(Sum
+ *(Buffer
+ Count
));
52 Returns the two's complement checksum of all elements in a buffer
55 This function first calculates the sum of the 8-bit values in the
56 buffer specified by Buffer and Length. The carry bits in the result
57 of addition are dropped. Then, the two's complement of the sum is
58 returned. If Length is 0, then 0 is returned.
60 If Buffer is NULL, then ASSERT().
61 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
63 @param Buffer The pointer to the buffer to carry out the checksum operation.
64 @param Length The size, in bytes, of Buffer.
66 @return Checksum The 2's complement checksum of Buffer.
72 IN CONST UINT8
*Buffer
,
78 CheckSum
= CalculateSum8 (Buffer
, Length
);
81 // Return the checksum based on 2's complement.
83 return (UINT8
)(0x100 - CheckSum
);
87 Returns the sum of all elements in a buffer of 16-bit values. During
88 calculation, the carry bits are dropped.
90 This function calculates the sum of the 16-bit values in the buffer
91 specified by Buffer and Length. The carry bits in result of addition are dropped.
92 The 16-bit result is returned. If Length is 0, then 0 is returned.
94 If Buffer is NULL, then ASSERT().
95 If Buffer is not aligned on a 16-bit boundary, then ASSERT().
96 If Length is not aligned on a 16-bit boundary, then ASSERT().
97 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
99 @param Buffer The pointer to the buffer to carry out the sum operation.
100 @param Length The size, in bytes, of Buffer.
102 @return Sum The sum of Buffer with carry bits dropped during additions.
108 IN CONST UINT16
*Buffer
,
116 ASSERT (Buffer
!= NULL
);
117 ASSERT (((UINTN
)Buffer
& 0x1) == 0);
118 ASSERT ((Length
& 0x1) == 0);
119 ASSERT (Length
<= (MAX_ADDRESS
- ((UINTN
)Buffer
) + 1));
121 Total
= Length
/ sizeof (*Buffer
);
122 for (Sum
= 0, Count
= 0; Count
< Total
; Count
++) {
123 Sum
= (UINT16
)(Sum
+ *(Buffer
+ Count
));
130 Returns the two's complement checksum of all elements in a buffer of
133 This function first calculates the sum of the 16-bit values in the buffer
134 specified by Buffer and Length. The carry bits in the result of addition
135 are dropped. Then, the two's complement of the sum is returned. If Length
136 is 0, then 0 is returned.
138 If Buffer is NULL, then ASSERT().
139 If Buffer is not aligned on a 16-bit boundary, then ASSERT().
140 If Length is not aligned on a 16-bit boundary, then ASSERT().
141 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
143 @param Buffer The pointer to the buffer to carry out the checksum operation.
144 @param Length The size, in bytes, of Buffer.
146 @return Checksum The 2's complement checksum of Buffer.
151 CalculateCheckSum16 (
152 IN CONST UINT16
*Buffer
,
158 CheckSum
= CalculateSum16 (Buffer
, Length
);
161 // Return the checksum based on 2's complement.
163 return (UINT16
)(0x10000 - CheckSum
);
167 Returns the sum of all elements in a buffer of 32-bit values. During
168 calculation, the carry bits are dropped.
170 This function calculates the sum of the 32-bit values in the buffer
171 specified by Buffer and Length. The carry bits in result of addition are dropped.
172 The 32-bit result is returned. If Length is 0, then 0 is returned.
174 If Buffer is NULL, then ASSERT().
175 If Buffer is not aligned on a 32-bit boundary, then ASSERT().
176 If Length is not aligned on a 32-bit boundary, then ASSERT().
177 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
179 @param Buffer The pointer to the buffer to carry out the sum operation.
180 @param Length The size, in bytes, of Buffer.
182 @return Sum The sum of Buffer with carry bits dropped during additions.
188 IN CONST UINT32
*Buffer
,
196 ASSERT (Buffer
!= NULL
);
197 ASSERT (((UINTN
)Buffer
& 0x3) == 0);
198 ASSERT ((Length
& 0x3) == 0);
199 ASSERT (Length
<= (MAX_ADDRESS
- ((UINTN
)Buffer
) + 1));
201 Total
= Length
/ sizeof (*Buffer
);
202 for (Sum
= 0, Count
= 0; Count
< Total
; Count
++) {
203 Sum
= Sum
+ *(Buffer
+ Count
);
210 Returns the two's complement checksum of all elements in a buffer of
213 This function first calculates the sum of the 32-bit values in the buffer
214 specified by Buffer and Length. The carry bits in the result of addition
215 are dropped. Then, the two's complement of the sum is returned. If Length
216 is 0, then 0 is returned.
218 If Buffer is NULL, then ASSERT().
219 If Buffer is not aligned on a 32-bit boundary, then ASSERT().
220 If Length is not aligned on a 32-bit boundary, then ASSERT().
221 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
223 @param Buffer The pointer to the buffer to carry out the checksum operation.
224 @param Length The size, in bytes, of Buffer.
226 @return Checksum The 2's complement checksum of Buffer.
231 CalculateCheckSum32 (
232 IN CONST UINT32
*Buffer
,
238 CheckSum
= CalculateSum32 (Buffer
, Length
);
241 // Return the checksum based on 2's complement.
243 return (UINT32
)((UINT32
)(-1) - CheckSum
+ 1);
247 Returns the sum of all elements in a buffer of 64-bit values. During
248 calculation, the carry bits are dropped.
250 This function calculates the sum of the 64-bit values in the buffer
251 specified by Buffer and Length. The carry bits in result of addition are dropped.
252 The 64-bit result is returned. If Length is 0, then 0 is returned.
254 If Buffer is NULL, then ASSERT().
255 If Buffer is not aligned on a 64-bit boundary, then ASSERT().
256 If Length is not aligned on a 64-bit boundary, then ASSERT().
257 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
259 @param Buffer The pointer to the buffer to carry out the sum operation.
260 @param Length The size, in bytes, of Buffer.
262 @return Sum The sum of Buffer with carry bits dropped during additions.
268 IN CONST UINT64
*Buffer
,
276 ASSERT (Buffer
!= NULL
);
277 ASSERT (((UINTN
)Buffer
& 0x7) == 0);
278 ASSERT ((Length
& 0x7) == 0);
279 ASSERT (Length
<= (MAX_ADDRESS
- ((UINTN
)Buffer
) + 1));
281 Total
= Length
/ sizeof (*Buffer
);
282 for (Sum
= 0, Count
= 0; Count
< Total
; Count
++) {
283 Sum
= Sum
+ *(Buffer
+ Count
);
290 Returns the two's complement checksum of all elements in a buffer of
293 This function first calculates the sum of the 64-bit values in the buffer
294 specified by Buffer and Length. The carry bits in the result of addition
295 are dropped. Then, the two's complement of the sum is returned. If Length
296 is 0, then 0 is returned.
298 If Buffer is NULL, then ASSERT().
299 If Buffer is not aligned on a 64-bit boundary, then ASSERT().
300 If Length is not aligned on a 64-bit boundary, then ASSERT().
301 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
303 @param Buffer The pointer to the buffer to carry out the checksum operation.
304 @param Length The size, in bytes, of Buffer.
306 @return Checksum The 2's complement checksum of Buffer.
311 CalculateCheckSum64 (
312 IN CONST UINT64
*Buffer
,
318 CheckSum
= CalculateSum64 (Buffer
, Length
);
321 // Return the checksum based on 2's complement.
323 return (UINT64
)((UINT64
)(-1) - CheckSum
+ 1);
326 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 mCrcTable
[256] = {
586 Computes and returns a 32-bit CRC for a data buffer.
587 CRC32 value bases on ITU-T V.42.
589 If Buffer is NULL, then ASSERT().
590 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
592 @param[in] Buffer A pointer to the buffer on which the 32-bit CRC is to be computed.
593 @param[in] Length The number of bytes in the buffer Data.
595 @retval Crc32 The 32-bit CRC was computed for the data buffer.
609 ASSERT (Buffer
!= NULL
);
610 ASSERT (Length
<= (MAX_ADDRESS
- ((UINTN
)Buffer
) + 1));
616 for (Index
= 0, Ptr
= Buffer
; Index
< Length
; Index
++, Ptr
++) {
617 Crc
= (Crc
>> 8) ^ mCrcTable
[(UINT8
)Crc
^ *Ptr
];
620 return Crc
^ 0xffffffff;
623 GLOBAL_REMOVE_IF_UNREFERENCED STATIC CONST UINT16 mCrc16LookupTable
[256] =
625 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
626 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
627 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
628 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
629 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
630 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
631 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
632 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
633 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
634 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
635 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
636 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
637 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
638 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
639 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
640 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
641 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
642 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
643 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
644 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
645 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
646 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
647 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
648 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
649 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
650 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
651 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
652 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
653 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
654 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
655 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
656 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
660 Calculates the CRC16-ANSI checksum of the given buffer.
662 @param[in] Buffer Pointer to the buffer.
663 @param[in] Length Length of the buffer, in bytes.
664 @param[in] InitialValue Initial value of the CRC.
666 @return The CRC16-ANSI checksum.
671 IN CONST VOID
*Buffer
,
673 IN UINT16 InitialValue
683 while (Length
-- != 0) {
684 Crc
= mCrc16LookupTable
[(Crc
& 0xFF) ^ *(Buf
++)] ^ (Crc
>> 8);
690 GLOBAL_REMOVE_IF_UNREFERENCED STATIC CONST UINT32 mCrc32cLookupTable
[256] = {
691 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c,
692 0x26a1e7e8, 0xd4ca64eb, 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
693 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, 0x105ec76f, 0xe235446c,
694 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
695 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc,
696 0xbc267848, 0x4e4dfb4b, 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
697 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, 0xaa64d611, 0x580f5512,
698 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
699 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad,
700 0x1642ae59, 0xe4292d5a, 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
701 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, 0x417b1dbc, 0xb3109ebf,
702 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
703 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f,
704 0xed03a29b, 0x1f682198, 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
705 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, 0xdbfc821c, 0x2997011f,
706 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
707 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e,
708 0x4767748a, 0xb50cf789, 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
709 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, 0x7198540d, 0x83f3d70e,
710 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
711 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de,
712 0xdde0eb2a, 0x2f8b6829, 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
713 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, 0x082f63b7, 0xfa44e0b4,
714 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
715 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b,
716 0xb4091bff, 0x466298fc, 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
717 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, 0xa24bb5a6, 0x502036a5,
718 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
719 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975,
720 0x0e330a81, 0xfc588982, 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
721 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, 0x38cc2a06, 0xcaa7a905,
722 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
723 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8,
724 0xe52cc12c, 0x1747422f, 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
725 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, 0xd3d3e1ab, 0x21b862a8,
726 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
727 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78,
728 0x7fab5e8c, 0x8dc0dd8f, 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
729 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, 0x69e9f0d5, 0x9b8273d6,
730 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
731 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69,
732 0xd5cf889d, 0x27a40b9e, 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
733 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351
737 Calculates the CRC32c checksum of the given buffer.
739 @param[in] Buffer Pointer to the buffer.
740 @param[in] Length Length of the buffer, in bytes.
741 @param[in] InitialValue Initial value of the CRC.
743 @return The CRC32c checksum.
748 IN CONST VOID
*Buffer
,
750 IN UINT32 InitialValue
759 while (Length
-- != 0) {
760 Crc
= mCrc32cLookupTable
[(Crc
& 0xFF) ^ *(Buf
++)] ^ (Crc
>> 8);