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