diff options
Diffstat (limited to 'util/nvramtool/compute_ip_checksum.c')
-rw-r--r-- | util/nvramtool/compute_ip_checksum.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/util/nvramtool/compute_ip_checksum.c b/util/nvramtool/compute_ip_checksum.c new file mode 100644 index 0000000000..3d2c29feb8 --- /dev/null +++ b/util/nvramtool/compute_ip_checksum.c @@ -0,0 +1,45 @@ +/*****************************************************************************\ + * compute_ip_checksum.c + * $Id$ +\*****************************************************************************/ + +#include <stdint.h> +#include "ip_checksum.h" + +/* Note: The contents of this file were borrowed from the coreboot source + * code which may be obtained from http://www.coreboot.org. + * Specifically, this code was obtained from coreboot (LinuxBIOS) + * version 1.0.0.8. + */ + +unsigned long compute_ip_checksum(void *addr, unsigned long length) +{ + uint8_t *ptr; + volatile union { + uint8_t byte[2]; + uint16_t word; + } value; + unsigned long sum; + unsigned long i; + /* In the most straight forward way possible, + * compute an ip style checksum. + */ + sum = 0; + ptr = addr; + for(i = 0; i < length; i++) { + unsigned long value; + value = ptr[i]; + if (i & 1) { + value <<= 8; + } + /* Add the new value */ + sum += value; + /* Wrap around the carry */ + if (sum > 0xFFFF) { + sum = (sum + (sum >> 16)) & 0xFFFF; + } + } + value.byte[0] = sum & 0xff; + value.byte[1] = (sum >> 8) & 0xff; + return (~value.word) & 0xFFFF; +} |