Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / libopenbios / ipchecksum.c
1 /* Taken from Etherboot */
2
3 #include "libopenbios/ipchecksum.h"
4
5 unsigned short ipchksum(const void *data, unsigned long length)
6 {
7         unsigned long sum;
8         unsigned long i;
9         const unsigned char *ptr;
10         union {
11             unsigned char byte[2];
12             unsigned short word;
13         } u;
14
15         /* In the most straight forward way possible,
16          * compute an ip style checksum.
17          */
18         sum = 0;
19         ptr = data;
20         for(i = 0; i < length; i++) {
21                 unsigned long value;
22                 value = ptr[i];
23                 if (i & 1) {
24                         value <<= 8;
25                 }
26                 /* Add the new value */
27                 sum += value;
28                 /* Wrap around the carry */
29                 if (sum > 0xFFFF) {
30                         sum = (sum + (sum >> 16)) & 0xFFFF;
31                 }
32         }
33         u.byte[0] = (unsigned char) sum;
34         u.byte[1] = (unsigned char) (sum >> 8);
35         return (unsigned short) ~u.word;
36 }
37
38 unsigned short add_ipchksums(unsigned long offset, unsigned short sum, unsigned short new)
39 {
40         unsigned long checksum;
41         sum = ~sum & 0xFFFF;
42         new = ~new & 0xFFFF;
43         if (offset & 1) {
44                 /* byte swap the sum if it came from an odd offset
45                  * since the computation is endian independant this
46                  * works.
47                  */
48                 new = (new << 8) | (new >> 8);
49         }
50         checksum = sum + new;
51         if (checksum > 0xFFFF) {
52                 checksum -= 0xFFFF;
53         }
54         return (~checksum) & 0xFFFF;
55 }