- 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