- Initial checkin of the freebios2 tree
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@784 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
53
src/lib/compute_ip_checksum.c
Normal file
53
src/lib/compute_ip_checksum.c
Normal file
@ -0,0 +1,53 @@
|
||||
#include <stdint.h>
|
||||
#include <ip_checksum.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new)
|
||||
{
|
||||
unsigned long checksum;
|
||||
sum = ~sum & 0xFFFF;
|
||||
new = ~new & 0xFFFF;
|
||||
if (offset & 1) {
|
||||
/* byte swap the sum if it came from an odd offset
|
||||
* since the computation is endian independant this
|
||||
* works.
|
||||
*/
|
||||
new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
|
||||
}
|
||||
checksum = sum + new;
|
||||
if (checksum > 0xFFFF) {
|
||||
checksum -= 0xFFFF;
|
||||
}
|
||||
return (~checksum) & 0xFFFF;
|
||||
}
|
Reference in New Issue
Block a user