1 /** @file 2 Utility functions to generate checksum based on 2's complement 3 algorithm. 4 5 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php. 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "BaseLibInternals.h" 17 18 /** 19 Returns the sum of all elements in a buffer in unit of UINT8. 20 During calculation, the carry bits are dropped. 21 22 This function calculates the sum of all elements in a buffer 23 in unit of UINT8. The carry bits in result of addition are dropped. 24 The result is returned as UINT8. If Length is Zero, then Zero is 25 returned. 26 27 If Buffer is NULL, then ASSERT(). 28 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 29 30 @param Buffer The pointer to the buffer to carry out the sum operation. 31 @param Length The size, in bytes, of Buffer. 32 33 @return Sum The sum of Buffer with carry bits dropped during additions. 34 35 **/ 36 UINT8 37 EFIAPI 38 CalculateSum8 ( 39 IN CONST UINT8 *Buffer, 40 IN UINTN Length 41 ) 42 { 43 UINT8 Sum; 44 UINTN Count; 45 46 ASSERT (Buffer != NULL); 47 ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); 48 49 for (Sum = 0, Count = 0; Count < Length; Count++) { 50 Sum = (UINT8) (Sum + *(Buffer + Count)); 51 } 52 53 return Sum; 54 } 55 56 57 /** 58 Returns the two's complement checksum of all elements in a buffer 59 of 8-bit values. 60 61 This function first calculates the sum of the 8-bit values in the 62 buffer specified by Buffer and Length. The carry bits in the result 63 of addition are dropped. Then, the two's complement of the sum is 64 returned. If Length is 0, then 0 is returned. 65 66 If Buffer is NULL, then ASSERT(). 67 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 68 69 @param Buffer The pointer to the buffer to carry out the checksum operation. 70 @param Length The size, in bytes, of Buffer. 71 72 @return Checksum The 2's complement checksum of Buffer. 73 74 **/ 75 UINT8 76 EFIAPI 77 CalculateCheckSum8 ( 78 IN CONST UINT8 *Buffer, 79 IN UINTN Length 80 ) 81 { 82 UINT8 CheckSum; 83 84 CheckSum = CalculateSum8 (Buffer, Length); 85 86 // 87 // Return the checksum based on 2's complement. 88 // 89 return (UINT8) (0x100 - CheckSum); 90 } 91 92 /** 93 Returns the sum of all elements in a buffer of 16-bit values. During 94 calculation, the carry bits are dropped. 95 96 This function calculates the sum of the 16-bit values in the buffer 97 specified by Buffer and Length. The carry bits in result of addition are dropped. 98 The 16-bit result is returned. If Length is 0, then 0 is returned. 99 100 If Buffer is NULL, then ASSERT(). 101 If Buffer is not aligned on a 16-bit boundary, then ASSERT(). 102 If Length is not aligned on a 16-bit boundary, then ASSERT(). 103 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 104 105 @param Buffer The pointer to the buffer to carry out the sum operation. 106 @param Length The size, in bytes, of Buffer. 107 108 @return Sum The sum of Buffer with carry bits dropped during additions. 109 110 **/ 111 UINT16 112 EFIAPI 113 CalculateSum16 ( 114 IN CONST UINT16 *Buffer, 115 IN UINTN Length 116 ) 117 { 118 UINT16 Sum; 119 UINTN Count; 120 UINTN Total; 121 122 ASSERT (Buffer != NULL); 123 ASSERT (((UINTN) Buffer & 0x1) == 0); 124 ASSERT ((Length & 0x1) == 0); 125 ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); 126 127 Total = Length / sizeof (*Buffer); 128 for (Sum = 0, Count = 0; Count < Total; Count++) { 129 Sum = (UINT16) (Sum + *(Buffer + Count)); 130 } 131 132 return Sum; 133 } 134 135 136 /** 137 Returns the two's complement checksum of all elements in a buffer of 138 16-bit values. 139 140 This function first calculates the sum of the 16-bit values in the buffer 141 specified by Buffer and Length. The carry bits in the result of addition 142 are dropped. Then, the two's complement of the sum is returned. If Length 143 is 0, then 0 is returned. 144 145 If Buffer is NULL, then ASSERT(). 146 If Buffer is not aligned on a 16-bit boundary, then ASSERT(). 147 If Length is not aligned on a 16-bit boundary, then ASSERT(). 148 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 149 150 @param Buffer The pointer to the buffer to carry out the checksum operation. 151 @param Length The size, in bytes, of Buffer. 152 153 @return Checksum The 2's complement checksum of Buffer. 154 155 **/ 156 UINT16 157 EFIAPI 158 CalculateCheckSum16 ( 159 IN CONST UINT16 *Buffer, 160 IN UINTN Length 161 ) 162 { 163 UINT16 CheckSum; 164 165 CheckSum = CalculateSum16 (Buffer, Length); 166 167 // 168 // Return the checksum based on 2's complement. 169 // 170 return (UINT16) (0x10000 - CheckSum); 171 } 172 173 174 /** 175 Returns the sum of all elements in a buffer of 32-bit values. During 176 calculation, the carry bits are dropped. 177 178 This function calculates the sum of the 32-bit values in the buffer 179 specified by Buffer and Length. The carry bits in result of addition are dropped. 180 The 32-bit result is returned. If Length is 0, then 0 is returned. 181 182 If Buffer is NULL, then ASSERT(). 183 If Buffer is not aligned on a 32-bit boundary, then ASSERT(). 184 If Length is not aligned on a 32-bit boundary, then ASSERT(). 185 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 186 187 @param Buffer The pointer to the buffer to carry out the sum operation. 188 @param Length The size, in bytes, of Buffer. 189 190 @return Sum The sum of Buffer with carry bits dropped during additions. 191 192 **/ 193 UINT32 194 EFIAPI 195 CalculateSum32 ( 196 IN CONST UINT32 *Buffer, 197 IN UINTN Length 198 ) 199 { 200 UINT32 Sum; 201 UINTN Count; 202 UINTN Total; 203 204 ASSERT (Buffer != NULL); 205 ASSERT (((UINTN) Buffer & 0x3) == 0); 206 ASSERT ((Length & 0x3) == 0); 207 ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); 208 209 Total = Length / sizeof (*Buffer); 210 for (Sum = 0, Count = 0; Count < Total; Count++) { 211 Sum = Sum + *(Buffer + Count); 212 } 213 214 return Sum; 215 } 216 217 218 /** 219 Returns the two's complement checksum of all elements in a buffer of 220 32-bit values. 221 222 This function first calculates the sum of the 32-bit values in the buffer 223 specified by Buffer and Length. The carry bits in the result of addition 224 are dropped. Then, the two's complement of the sum is returned. If Length 225 is 0, then 0 is returned. 226 227 If Buffer is NULL, then ASSERT(). 228 If Buffer is not aligned on a 32-bit boundary, then ASSERT(). 229 If Length is not aligned on a 32-bit boundary, then ASSERT(). 230 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 231 232 @param Buffer The pointer to the buffer to carry out the checksum operation. 233 @param Length The size, in bytes, of Buffer. 234 235 @return Checksum The 2's complement checksum of Buffer. 236 237 **/ 238 UINT32 239 EFIAPI 240 CalculateCheckSum32 ( 241 IN CONST UINT32 *Buffer, 242 IN UINTN Length 243 ) 244 { 245 UINT32 CheckSum; 246 247 CheckSum = CalculateSum32 (Buffer, Length); 248 249 // 250 // Return the checksum based on 2's complement. 251 // 252 return (UINT32) ((UINT32)(-1) - CheckSum + 1); 253 } 254 255 256 /** 257 Returns the sum of all elements in a buffer of 64-bit values. During 258 calculation, the carry bits are dropped. 259 260 This function calculates the sum of the 64-bit values in the buffer 261 specified by Buffer and Length. The carry bits in result of addition are dropped. 262 The 64-bit result is returned. If Length is 0, then 0 is returned. 263 264 If Buffer is NULL, then ASSERT(). 265 If Buffer is not aligned on a 64-bit boundary, then ASSERT(). 266 If Length is not aligned on a 64-bit boundary, then ASSERT(). 267 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 268 269 @param Buffer The pointer to the buffer to carry out the sum operation. 270 @param Length The size, in bytes, of Buffer. 271 272 @return Sum The sum of Buffer with carry bits dropped during additions. 273 274 **/ 275 UINT64 276 EFIAPI 277 CalculateSum64 ( 278 IN CONST UINT64 *Buffer, 279 IN UINTN Length 280 ) 281 { 282 UINT64 Sum; 283 UINTN Count; 284 UINTN Total; 285 286 ASSERT (Buffer != NULL); 287 ASSERT (((UINTN) Buffer & 0x7) == 0); 288 ASSERT ((Length & 0x7) == 0); 289 ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); 290 291 Total = Length / sizeof (*Buffer); 292 for (Sum = 0, Count = 0; Count < Total; Count++) { 293 Sum = Sum + *(Buffer + Count); 294 } 295 296 return Sum; 297 } 298 299 300 /** 301 Returns the two's complement checksum of all elements in a buffer of 302 64-bit values. 303 304 This function first calculates the sum of the 64-bit values in the buffer 305 specified by Buffer and Length. The carry bits in the result of addition 306 are dropped. Then, the two's complement of the sum is returned. If Length 307 is 0, then 0 is returned. 308 309 If Buffer is NULL, then ASSERT(). 310 If Buffer is not aligned on a 64-bit boundary, then ASSERT(). 311 If Length is not aligned on a 64-bit boundary, then ASSERT(). 312 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 313 314 @param Buffer The pointer to the buffer to carry out the checksum operation. 315 @param Length The size, in bytes, of Buffer. 316 317 @return Checksum The 2's complement checksum of Buffer. 318 319 **/ 320 UINT64 321 EFIAPI 322 CalculateCheckSum64 ( 323 IN CONST UINT64 *Buffer, 324 IN UINTN Length 325 ) 326 { 327 UINT64 CheckSum; 328 329 CheckSum = CalculateSum64 (Buffer, Length); 330 331 // 332 // Return the checksum based on 2's complement. 333 // 334 return (UINT64) ((UINT64)(-1) - CheckSum + 1); 335 } 336 337 338