Fix prototype of random() and move to stdlib.h
[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 TWIDDLE
99 **************************************************************************/
100 void twiddle(void)
101 {
102 #ifdef BAR_PROGRESS
103         static int count=0;
104         static const char tiddles[]="-\\|/";
105         static unsigned long lastticks = 0;
106         unsigned long ticks;
107 #endif
108         if ( ! as_main_program ) return;
109 #ifdef  BAR_PROGRESS
110         /* Limit the maximum rate at which characters are printed */
111         ticks = currticks();
112         if ((lastticks + (TICKS_PER_SEC/18)) > ticks)
113                 return;
114         lastticks = ticks;
115
116         putchar(tiddles[(count++)&3]);
117         putchar('\b');
118 #else
119         putchar('.');
120 #endif  /* BAR_PROGRESS */
121 }
122
123 /**************************************************************************
124 STRCASECMP (not entirely correct, but this will do for our purposes)
125 **************************************************************************/
126 int strcasecmp(const char *a, const char *b)
127 {
128         while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
129         return((*a & ~0x20) - (*b & ~0x20));
130 }
131
132 /**************************************************************************
133 INET_ATON - Convert an ascii x.x.x.x to binary form
134 **************************************************************************/
135 int inet_aton ( const char *cp, struct in_addr *inp ) {
136         const char *p = cp;
137         const char *digits_start;
138         unsigned long ip = 0;
139         unsigned long val;
140         int j;
141         for(j = 0; j <= 3; j++) {
142                 digits_start = p;
143                 val = strtoul(p, ( char ** ) &p, 10);
144                 if ((p == digits_start) || (val > 255)) return 0;
145                 if ( ( j < 3 ) && ( *(p++) != '.' ) ) return 0;
146                 ip = (ip << 8) | val;
147         }
148         if ( *p == '\0' ) {
149                 inp->s_addr = htonl(ip);
150                 return 1;
151         }
152         return 0;
153 }
154
155 unsigned long strtoul ( const char *p, char **endp, int base ) {
156         unsigned long ret = 0;
157         unsigned int charval;
158
159         if ( base == 0 ) {
160                 base = 10;
161                 if ( *p == '0' ) {
162                         p++;
163                         base = 8;
164                         if ( ( *p | 0x20 ) == 'x' ) {
165                                 p++;
166                                 base = 16;
167                         }
168                 }
169         }
170
171         while ( 1 ) {
172                 charval = *p;
173                 if ( charval >= 'a' ) {
174                         charval = ( charval - 'a' + 10 );
175                 } else if ( charval >= 'A' ) {
176                         charval = ( charval - 'A' + 10 );
177                 } else {
178                         charval = ( charval - '0' );
179                 }
180                 if ( charval >= ( unsigned int ) base )
181                         break;
182                 ret = ( ( ret * base ) + charval );
183                 p++;
184         }
185
186         if ( endp )
187                 *endp = ( char * ) p;
188
189         return ( ret );
190 }
191
192 /*
193  * Local variables:
194  *  c-basic-offset: 8
195  * End:
196  */