/ util / nvramtool / compute_ip_checksum.c
compute_ip_checksum.c
 1  /*****************************************************************************\
 2   * compute_ip_checksum.c
 3  \*****************************************************************************/
 4  
 5  #include <stdint.h>
 6  #include "ip_checksum.h"
 7  
 8  /* Note: The contents of this file were borrowed from the coreboot source
 9   *       code which may be obtained from https://www.coreboot.org.
10   *       Specifically, this code was obtained from coreboot (LinuxBIOS)
11   *       version 1.0.0.8.
12   */
13  
14  unsigned long compute_ip_checksum(void *addr, unsigned long length)
15  {
16  	uint8_t *ptr;
17  	volatile union {
18  		uint8_t byte[2];
19  		uint16_t word;
20  	} value;
21  	unsigned long sum;
22  	unsigned long i;
23  	/* In the most straight forward way possible,
24  	 * compute an ip style checksum.
25  	 */
26  	sum = 0;
27  	ptr = addr;
28  	for (i = 0; i < length; i++) {
29  		unsigned long value;
30  		value = ptr[i];
31  		if (i & 1) {
32  			value <<= 8;
33  		}
34  		/* Add the new value */
35  		sum += value;
36  		/* Wrap around the carry */
37  		if (sum > 0xFFFF) {
38  			sum = (sum + (sum >> 16)) & 0xFFFF;
39  		}
40  	}
41  	value.byte[0] = sum & 0xff;
42  	value.byte[1] = (sum >> 8) & 0xff;
43  	return (~value.word) & 0xFFFF;
44  }