e150709a1d44625ad606406a58a2c46fcf2497fd
[people/xl0/gpxe.git] / src / core / misc.c
1 /**************************************************************************
2 MISC Support Routines
3 **************************************************************************/
4
5 #include "etherboot.h"
6 #include "console.h"
7 #include <stdlib.h>
8
9 /**************************************************************************
10 IPCHKSUM - Checksum IP Header
11 **************************************************************************/
12 uint16_t ipchksum(const void *data, unsigned long length)
13 {
14         unsigned long sum;
15         unsigned long i;
16         const uint8_t *ptr;
17
18         /* In the most straight forward way possible,
19          * compute an ip style checksum.
20          */
21         sum = 0;
22         ptr = data;
23         for(i = 0; i < length; i++) {
24                 unsigned long value;
25                 value = ptr[i];
26                 if (i & 1) {
27                         value <<= 8;
28                 }
29                 /* Add the new value */
30                 sum += value;
31                 /* Wrap around the carry */
32                 if (sum > 0xFFFF) {
33                         sum = (sum + (sum >> 16)) & 0xFFFF;
34                 }
35         }
36         return (~cpu_to_le16(sum)) & 0xFFFF;
37 }
38
39 uint16_t add_ipchksums(unsigned long offset, uint16_t sum, uint16_t new)
40 {
41         unsigned long checksum;
42         sum = ~sum & 0xFFFF;
43         new = ~new & 0xFFFF;
44         if (offset & 1) {
45                 /* byte swap the sum if it came from an odd offset 
46                  * since the computation is endian independant this
47                  * works.
48                  */
49                 new = bswap_16(new);
50         }
51         checksum = sum + new;
52         if (checksum > 0xFFFF) {
53                 checksum -= 0xFFFF;
54         }
55         return (~checksum) & 0xFFFF;
56 }
57
58
59
60 /**************************************************************************
61 RANDOM - compute a random number between 0 and 2147483647L or 2147483562?
62 **************************************************************************/
63 long int random(void)
64 {
65         static int32_t seed = 0;
66         int32_t q;
67         if (!seed) /* Initialize linear congruential generator */
68                 seed = currticks();
69         /* simplified version of the LCG given in Bruce Schneier's
70            "Applied Cryptography" */
71         q = seed/53668;
72         if ((seed = 40014*(seed-53668*q) - 12211*q) < 0) seed += 2147483563L;
73         return seed;
74 }
75
76 /**************************************************************************
77 SLEEP
78 **************************************************************************/
79 unsigned int sleep(unsigned int secs)
80 {
81         unsigned long tmo;
82
83         for (tmo = currticks()+secs*TICKS_PER_SEC; currticks() < tmo; ) {
84         }
85         return 0;
86 }
87
88 /**************************************************************************
89 INTERRUPTIBLE SLEEP
90 **************************************************************************/
91 void interruptible_sleep(int secs)
92 {
93         printf("<sleep>\n");
94         sleep(secs);
95 }
96
97 /**************************************************************************
98 STRCASECMP (not entirely correct, but this will do for our purposes)
99 **************************************************************************/
100 int strcasecmp(const char *a, const char *b)
101 {
102         while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
103         return((*a & ~0x20) - (*b & ~0x20));
104 }
105
106 /**************************************************************************
107 INET_ATON - Convert an ascii x.x.x.x to binary form
108 **************************************************************************/
109 int inet_aton ( const char *cp, struct in_addr *inp ) {
110         const char *p = cp;
111         const char *digits_start;
112         unsigned long ip = 0;
113         unsigned long val;
114         int j;
115         for(j = 0; j <= 3; j++) {
116                 digits_start = p;
117                 val = strtoul(p, ( char ** ) &p, 10);
118                 if ((p == digits_start) || (val > 255)) return 0;
119                 if ( ( j < 3 ) && ( *(p++) != '.' ) ) return 0;
120                 ip = (ip << 8) | val;
121         }
122         if ( *p == '\0' ) {
123                 inp->s_addr = htonl(ip);
124                 return 1;
125         }
126         return 0;
127 }
128
129 int isspace ( int c ) {
130         switch ( c ) {
131         case ' ':
132         case '\f':
133         case '\n':
134         case '\r':
135         case '\t':
136         case '\v':
137                 return 1;
138         default:
139                 return 0;
140         }
141 }
142
143 unsigned long strtoul ( const char *p, char **endp, int base ) {
144         unsigned long ret = 0;
145         unsigned int charval;
146
147         while ( isspace ( *p ) )
148                 p++;
149
150         if ( base == 0 ) {
151                 base = 10;
152                 if ( *p == '0' ) {
153                         p++;
154                         base = 8;
155                         if ( ( *p | 0x20 ) == 'x' ) {
156                                 p++;
157                                 base = 16;
158                         }
159                 }
160         }
161
162         while ( 1 ) {
163                 charval = *p;
164                 if ( charval >= 'a' ) {
165                         charval = ( charval - 'a' + 10 );
166                 } else if ( charval >= 'A' ) {
167                         charval = ( charval - 'A' + 10 );
168                 } else {
169                         charval = ( charval - '0' );
170                 }
171                 if ( charval >= ( unsigned int ) base )
172                         break;
173                 ret = ( ( ret * base ) + charval );
174                 p++;
175         }
176
177         if ( endp )
178                 *endp = ( char * ) p;
179
180         return ( ret );
181 }
182
183 /*
184  * Local variables:
185  *  c-basic-offset: 8
186  * End:
187  */