You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

633 lines
14 KiB

/** @file
Utility functions to generate checksum based on 2's complement
algorithm.
Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "BaseLibInternals.h"
/**
Returns the sum of all elements in a buffer in unit of UINT8.
During calculation, the carry bits are dropped.
This function calculates the sum of all elements in a buffer
in unit of UINT8. The carry bits in result of addition are dropped.
The result is returned as UINT8. If Length is Zero, then Zero is
returned.
If Buffer is NULL, then ASSERT().
If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
@param Buffer The pointer to the buffer to carry out the sum operation.
@param Length The size, in bytes, of Buffer.
@return Sum The sum of Buffer with carry bits dropped during additions.
**/
UINT8
EFIAPI
CalculateSum8 (
IN CONST UINT8 *Buffer,
IN UINTN Length
)
{
UINT8 Sum;
UINTN Count;
ASSERT (Buffer != NULL);
ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1));
for (Sum = 0, Count = 0; Count < Length; Count++) {
Sum = (UINT8) (Sum + *(Buffer + Count));
}
return Sum;
}
/**
Returns the two's complement checksum of all elements in a buffer
of 8-bit values.
This function first calculates the sum of the 8-bit values in the
buffer specified by Buffer and Length. The carry bits in the result
of addition are dropped. Then, the two's complement of the sum is
returned. If Length is 0, then 0 is returned.
If Buffer is NULL, then ASSERT().
If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
@param Buffer The pointer to the buffer to carry out the checksum operation.
@param Length The size, in bytes, of Buffer.
@return Checksum The 2's complement checksum of Buffer.
**/
UINT8
EFIAPI
CalculateCheckSum8 (
IN CONST UINT8 *Buffer,
IN UINTN Length
)
{
UINT8 CheckSum;
CheckSum = CalculateSum8 (Buffer, Length);
//
// Return the checksum based on 2's complement.
//
return (UINT8) (0x100 - CheckSum);
}
/**
Returns the sum of all elements in a buffer of 16-bit values. During
calculation, the carry bits are dropped.
This function calculates the sum of the 16-bit values in the buffer
specified by Buffer and Length. The carry bits in result of addition are dropped.
The 16-bit result is returned. If Length is 0, then 0 is returned.
If Buffer is NULL, then ASSERT().
If Buffer is not aligned on a 16-bit boundary, then ASSERT().
If Length is not aligned on a 16-bit boundary, then ASSERT().
If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
@param Buffer The pointer to the buffer to carry out the sum operation.
@param Length The size, in bytes, of Buffer.
@return Sum The sum of Buffer with carry bits dropped during additions.
**/
UINT16
EFIAPI
CalculateSum16 (
IN CONST UINT16 *Buffer,
IN UINTN Length
)
{
UINT16 Sum;
UINTN Count;
UINTN Total;
ASSERT (Buffer != NULL);
ASSERT (((UINTN) Buffer & 0x1) == 0);
ASSERT ((Length & 0x1) == 0);
ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1));
Total = Length / sizeof (*Buffer);
for (Sum = 0, Count = 0; Count < Total; Count++) {
Sum = (UINT16) (Sum + *(Buffer + Count));
}
return Sum;
}
/**
Returns the two's complement checksum of all elements in a buffer of
16-bit values.
This function first calculates the sum of the 16-bit values in the buffer
specified by Buffer and Length. The carry bits in the result of addition
are dropped. Then, the two's complement of the sum is returned. If Length
is 0, then 0 is returned.
If Buffer is NULL, then ASSERT().
If Buffer is not aligned on a 16-bit boundary, then ASSERT().
If Length is not aligned on a 16-bit boundary, then ASSERT().
If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
@param Buffer The pointer to the buffer to carry out the checksum operation.
@param Length The size, in bytes, of Buffer.
@return Checksum The 2's complement checksum of Buffer.
**/
UINT16
EFIAPI
CalculateCheckSum16 (
IN CONST UINT16 *Buffer,
IN UINTN Length
)
{
UINT16 CheckSum;
CheckSum = CalculateSum16 (Buffer, Length);
//
// Return the checksum based on 2's complement.
//
return (UINT16) (0x10000 - CheckSum);
}
/**
Returns the sum of all elements in a buffer of 32-bit values. During
calculation, the carry bits are dropped.
This function calculates the sum of the 32-bit values in the buffer
specified by Buffer and Length. The carry bits in result of addition are dropped.
The 32-bit result is returned. If Length is 0, then 0 is returned.
If Buffer is NULL, then ASSERT().
If Buffer is not aligned on a 32-bit boundary, then ASSERT().
If Length is not aligned on a 32-bit boundary, then ASSERT().
If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
@param Buffer The pointer to the buffer to carry out the sum operation.
@param Length The size, in bytes, of Buffer.
@return Sum The sum of Buffer with carry bits dropped during additions.
**/
UINT32
EFIAPI
CalculateSum32 (
IN CONST UINT32 *Buffer,
IN UINTN Length
)
{
UINT32 Sum;
UINTN Count;
UINTN Total;
ASSERT (Buffer != NULL);
ASSERT (((UINTN) Buffer & 0x3) == 0);
ASSERT ((Length & 0x3) == 0);
ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1));
Total = Length / sizeof (*Buffer);
for (Sum = 0, Count = 0; Count < Total; Count++) {
Sum = Sum + *(Buffer + Count);
}
return Sum;
}
/**
Returns the two's complement checksum of all elements in a buffer of
32-bit values.
This function first calculates the sum of the 32-bit values in the buffer
specified by Buffer and Length. The carry bits in the result of addition
are dropped. Then, the two's complement of the sum is returned. If Length
is 0, then 0 is returned.
If Buffer is NULL, then ASSERT().
If Buffer is not aligned on a 32-bit boundary, then ASSERT().
If Length is not aligned on a 32-bit boundary, then ASSERT().
If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
@param Buffer The pointer to the buffer to carry out the checksum operation.
@param Length The size, in bytes, of Buffer.
@return Checksum The 2's complement checksum of Buffer.
**/
UINT32
EFIAPI
CalculateCheckSum32 (
IN CONST UINT32 *Buffer,
IN UINTN Length
)
{
UINT32 CheckSum;
CheckSum = CalculateSum32 (Buffer, Length);
//
// Return the checksum based on 2's complement.
//
return (UINT32) ((UINT32)(-1) - CheckSum + 1);
}
/**
Returns the sum of all elements in a buffer of 64-bit values. During
calculation, the carry bits are dropped.
This function calculates the sum of the 64-bit values in the buffer
specified by Buffer and Length. The carry bits in result of addition are dropped.
The 64-bit result is returned. If Length is 0, then 0 is returned.
If Buffer is NULL, then ASSERT().
If Buffer is not aligned on a 64-bit boundary, then ASSERT().
If Length is not aligned on a 64-bit boundary, then ASSERT().
If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
@param Buffer The pointer to the buffer to carry out the sum operation.
@param Length The size, in bytes, of Buffer.
@return Sum The sum of Buffer with carry bits dropped during additions.
**/
UINT64
EFIAPI
CalculateSum64 (
IN CONST UINT64 *Buffer,
IN UINTN Length
)
{
UINT64 Sum;
UINTN Count;
UINTN Total;
ASSERT (Buffer != NULL);
ASSERT (((UINTN) Buffer & 0x7) == 0);
ASSERT ((Length & 0x7) == 0);
ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1));
Total = Length / sizeof (*Buffer);
for (Sum = 0, Count = 0; Count < Total; Count++) {
Sum = Sum + *(Buffer + Count);
}
return Sum;
}
/**
Returns the two's complement checksum of all elements in a buffer of
64-bit values.
This function first calculates the sum of the 64-bit values in the buffer
specified by Buffer and Length. The carry bits in the result of addition
are dropped. Then, the two's complement of the sum is returned. If Length
is 0, then 0 is returned.
If Buffer is NULL, then ASSERT().
If Buffer is not aligned on a 64-bit boundary, then ASSERT().
If Length is not aligned on a 64-bit boundary, then ASSERT().
If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
@param Buffer The pointer to the buffer to carry out the checksum operation.
@param Length The size, in bytes, of Buffer.
@return Checksum The 2's complement checksum of Buffer.
**/
UINT64
EFIAPI
CalculateCheckSum64 (
IN CONST UINT64 *Buffer,
IN UINTN Length
)
{
UINT64 CheckSum;
CheckSum = CalculateSum64 (Buffer, Length);
//
// Return the checksum based on 2's complement.
//
return (UINT64) ((UINT64)(-1) - CheckSum + 1);
}
GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 mCrcTable[256] = {
0x00000000,
0x77073096,
0xEE0E612C,
0x990951BA,
0x076DC419,
0x706AF48F,
0xE963A535,
0x9E6495A3,
0x0EDB8832,
0x79DCB8A4,
0xE0D5E91E,
0x97D2D988,
0x09B64C2B,
0x7EB17CBD,
0xE7B82D07,
0x90BF1D91,
0x1DB71064,
0x6AB020F2,
0xF3B97148,
0x84BE41DE,
0x1ADAD47D,
0x6DDDE4EB,
0xF4D4B551,
0x83D385C7,
0x136C9856,
0x646BA8C0,
0xFD62F97A,
0x8A65C9EC,
0x14015C4F,
0x63066CD9,
0xFA0F3D63,
0x8D080DF5,
0x3B6E20C8,
0x4C69105E,
0xD56041E4,
0xA2677172,
0x3C03E4D1,
0x4B04D447,
0xD20D85FD,
0xA50AB56B,
0x35B5A8FA,
0x42B2986C,
0xDBBBC9D6,
0xACBCF940,
0x32D86CE3,
0x45DF5C75,
0xDCD60DCF,
0xABD13D59,
0x26D930AC,
0x51DE003A,
0xC8D75180,
0xBFD06116,
0x21B4F4B5,
0x56B3C423,
0xCFBA9599,
0xB8BDA50F,
0x2802B89E,
0x5F058808,
0xC60CD9B2,
0xB10BE924,
0x2F6F7C87,
0x58684C11,
0xC1611DAB,
0xB6662D3D,
0x76DC4190,
0x01DB7106,
0x98D220BC,
0xEFD5102A,
0x71B18589,
0x06B6B51F,
0x9FBFE4A5,
0xE8B8D433,
0x7807C9A2,
0x0F00F934,
0x9609A88E,
0xE10E9818,
0x7F6A0DBB,
0x086D3D2D,
0x91646C97,
0xE6635C01,
0x6B6B51F4,
0x1C6C6162,
0x856530D8,
0xF262004E,
0x6C0695ED,
0x1B01A57B,
0x8208F4C1,
0xF50FC457,
0x65B0D9C6,
0x12B7E950,
0x8BBEB8EA,
0xFCB9887C,
0x62DD1DDF,
0x15DA2D49,
0x8CD37CF3,
0xFBD44C65,
0x4DB26158,
0x3AB551CE,
0xA3BC0074,
0xD4BB30E2,
0x4ADFA541,
0x3DD895D7,
0xA4D1C46D,
0xD3D6F4FB,
0x4369E96A,
0x346ED9FC,
0xAD678846,
0xDA60B8D0,
0x44042D73,
0x33031DE5,
0xAA0A4C5F,
0xDD0D7CC9,
0x5005713C,
0x270241AA,
0xBE0B1010,
0xC90C2086,
0x5768B525,
0x206F85B3,
0xB966D409,
0xCE61E49F,
0x5EDEF90E,
0x29D9C998,
0xB0D09822,
0xC7D7A8B4,
0x59B33D17,
0x2EB40D81,
0xB7BD5C3B,
0xC0BA6CAD,
0xEDB88320,
0x9ABFB3B6,
0x03B6E20C,
0x74B1D29A,
0xEAD54739,
0x9DD277AF,
0x04DB2615,
0x73DC1683,
0xE3630B12,
0x94643B84,
0x0D6D6A3E,
0x7A6A5AA8,
0xE40ECF0B,
0x9309FF9D,
0x0A00AE27,
0x7D079EB1,
0xF00F9344,
0x8708A3D2,
0x1E01F268,
0x6906C2FE,
0xF762575D,
0x806567CB,
0x196C3671,
0x6E6B06E7,
0xFED41B76,
0x89D32BE0,
0x10DA7A5A,
0x67DD4ACC,
0xF9B9DF6F,
0x8EBEEFF9,
0x17B7BE43,
0x60B08ED5,
0xD6D6A3E8,
0xA1D1937E,
0x38D8C2C4,
0x4FDFF252,
0xD1BB67F1,
0xA6BC5767,
0x3FB506DD,
0x48B2364B,
0xD80D2BDA,
0xAF0A1B4C,
0x36034AF6,
0x41047A60,
0xDF60EFC3,
0xA867DF55,
0x316E8EEF,
0x4669BE79,
0xCB61B38C,
0xBC66831A,
0x256FD2A0,
0x5268E236,
0xCC0C7795,
0xBB0B4703,
0x220216B9,
0x5505262F,
0xC5BA3BBE,
0xB2BD0B28,
0x2BB45A92,
0x5CB36A04,
0xC2D7FFA7,
0xB5D0CF31,
0x2CD99E8B,
0x5BDEAE1D,
0x9B64C2B0,
0xEC63F226,
0x756AA39C,
0x026D930A,
0x9C0906A9,
0xEB0E363F,
0x72076785,
0x05005713,
0x95BF4A82,
0xE2B87A14,
0x7BB12BAE,
0x0CB61B38,
0x92D28E9B,
0xE5D5BE0D,
0x7CDCEFB7,
0x0BDBDF21,
0x86D3D2D4,
0xF1D4E242,
0x68DDB3F8,
0x1FDA836E,
0x81BE16CD,
0xF6B9265B,
0x6FB077E1,
0x18B74777,
0x88085AE6,
0xFF0F6A70,
0x66063BCA,
0x11010B5C,
0x8F659EFF,
0xF862AE69,
0x616BFFD3,
0x166CCF45,
0xA00AE278,
0xD70DD2EE,
0x4E048354,
0x3903B3C2,
0xA7672661,
0xD06016F7,
0x4969474D,
0x3E6E77DB,
0xAED16A4A,
0xD9D65ADC,
0x40DF0B66,
0x37D83BF0,
0xA9BCAE53,
0xDEBB9EC5,
0x47B2CF7F,
0x30B5FFE9,
0xBDBDF21C,
0xCABAC28A,
0x53B39330,
0x24B4A3A6,
0xBAD03605,
0xCDD70693,
0x54DE5729,
0x23D967BF,
0xB3667A2E,
0xC4614AB8,
0x5D681B02,
0x2A6F2B94,
0xB40BBE37,
0xC30C8EA1,
0x5A05DF1B,
0x2D02EF8D
};
/**
Computes and returns a 32-bit CRC for a data buffer.
CRC32 value bases on ITU-T V.42.
If Buffer is NULL, then ASSERT().
If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
@param[in] Buffer A pointer to the buffer on which the 32-bit CRC is to be computed.
@param[in] Length The number of bytes in the buffer Data.
@retval Crc32 The 32-bit CRC was computed for the data buffer.
**/
UINT32
EFIAPI
CalculateCrc32(
IN VOID *Buffer,
IN UINTN Length
)
{
UINTN Index;
UINT32 Crc;
UINT8 *Ptr;
ASSERT (Buffer != NULL);
ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1));
//
// Compute CRC
//
Crc = 0xffffffff;
for (Index = 0, Ptr = Buffer; Index < Length; Index++, Ptr++) {
Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr];
}
return Crc ^ 0xffffffff;
}