xref: /aosp_15_r20/external/coreboot/util/nvramtool/compute_ip_checksum.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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 
compute_ip_checksum(void * addr,unsigned long length)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 }
45