1*8044SWilliam.Kucharski@Sun.COM /*
2*8044SWilliam.Kucharski@Sun.COM * GRUB -- GRand Unified Bootloader
3*8044SWilliam.Kucharski@Sun.COM * Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
4*8044SWilliam.Kucharski@Sun.COM *
5*8044SWilliam.Kucharski@Sun.COM * This program is free software; you can redistribute it and/or modify
6*8044SWilliam.Kucharski@Sun.COM * it under the terms of the GNU General Public License as published by
7*8044SWilliam.Kucharski@Sun.COM * the Free Software Foundation; either version 2 of the License, or
8*8044SWilliam.Kucharski@Sun.COM * (at your option) any later version.
9*8044SWilliam.Kucharski@Sun.COM *
10*8044SWilliam.Kucharski@Sun.COM * This program is distributed in the hope that it will be useful,
11*8044SWilliam.Kucharski@Sun.COM * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*8044SWilliam.Kucharski@Sun.COM * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*8044SWilliam.Kucharski@Sun.COM * GNU General Public License for more details.
14*8044SWilliam.Kucharski@Sun.COM *
15*8044SWilliam.Kucharski@Sun.COM * You should have received a copy of the GNU General Public License
16*8044SWilliam.Kucharski@Sun.COM * along with this program; if not, write to the Free Software
17*8044SWilliam.Kucharski@Sun.COM * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*8044SWilliam.Kucharski@Sun.COM */
19*8044SWilliam.Kucharski@Sun.COM
20*8044SWilliam.Kucharski@Sun.COM /* Based on "src/misc.c" in etherboot-5.0.5. */
21*8044SWilliam.Kucharski@Sun.COM
22*8044SWilliam.Kucharski@Sun.COM #include "grub.h"
23*8044SWilliam.Kucharski@Sun.COM #include "timer.h"
24*8044SWilliam.Kucharski@Sun.COM
25*8044SWilliam.Kucharski@Sun.COM #include "nic.h"
26*8044SWilliam.Kucharski@Sun.COM
27*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
28*8044SWilliam.Kucharski@Sun.COM RANDOM - compute a random number between 0 and 2147483647L or 2147483562?
29*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
random(void)30*8044SWilliam.Kucharski@Sun.COM int32_t random(void)
31*8044SWilliam.Kucharski@Sun.COM {
32*8044SWilliam.Kucharski@Sun.COM static int32_t seed = 0;
33*8044SWilliam.Kucharski@Sun.COM int32_t q;
34*8044SWilliam.Kucharski@Sun.COM if (!seed) /* Initialize linear congruential generator */
35*8044SWilliam.Kucharski@Sun.COM seed = currticks() + *(int32_t *)&arptable[ARP_CLIENT].node
36*8044SWilliam.Kucharski@Sun.COM + ((int16_t *)arptable[ARP_CLIENT].node)[2];
37*8044SWilliam.Kucharski@Sun.COM /* simplified version of the LCG given in Bruce Schneier's
38*8044SWilliam.Kucharski@Sun.COM "Applied Cryptography" */
39*8044SWilliam.Kucharski@Sun.COM q = seed/53668;
40*8044SWilliam.Kucharski@Sun.COM if ((seed = 40014*(seed-53668*q) - 12211*q) < 0) seed += 2147483563L;
41*8044SWilliam.Kucharski@Sun.COM return seed;
42*8044SWilliam.Kucharski@Sun.COM }
43*8044SWilliam.Kucharski@Sun.COM
44*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
45*8044SWilliam.Kucharski@Sun.COM POLL INTERRUPTIONS
46*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
poll_interruptions(void)47*8044SWilliam.Kucharski@Sun.COM void poll_interruptions(void)
48*8044SWilliam.Kucharski@Sun.COM {
49*8044SWilliam.Kucharski@Sun.COM if (checkkey() != -1 && ASCII_CHAR(getkey()) == K_INTR) {
50*8044SWilliam.Kucharski@Sun.COM user_abort++;
51*8044SWilliam.Kucharski@Sun.COM }
52*8044SWilliam.Kucharski@Sun.COM }
53*8044SWilliam.Kucharski@Sun.COM
54*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
55*8044SWilliam.Kucharski@Sun.COM SLEEP
56*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
sleep(int secs)57*8044SWilliam.Kucharski@Sun.COM void sleep(int secs)
58*8044SWilliam.Kucharski@Sun.COM {
59*8044SWilliam.Kucharski@Sun.COM unsigned long tmo;
60*8044SWilliam.Kucharski@Sun.COM
61*8044SWilliam.Kucharski@Sun.COM for (tmo = currticks()+secs*TICKS_PER_SEC; currticks() < tmo; ) {
62*8044SWilliam.Kucharski@Sun.COM poll_interruptions();
63*8044SWilliam.Kucharski@Sun.COM }
64*8044SWilliam.Kucharski@Sun.COM }
65*8044SWilliam.Kucharski@Sun.COM
66*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
67*8044SWilliam.Kucharski@Sun.COM INTERRUPTIBLE SLEEP
68*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
interruptible_sleep(int secs)69*8044SWilliam.Kucharski@Sun.COM void interruptible_sleep(int secs)
70*8044SWilliam.Kucharski@Sun.COM {
71*8044SWilliam.Kucharski@Sun.COM printf("<sleep>\n");
72*8044SWilliam.Kucharski@Sun.COM return sleep(secs);
73*8044SWilliam.Kucharski@Sun.COM }
74*8044SWilliam.Kucharski@Sun.COM
75*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
76*8044SWilliam.Kucharski@Sun.COM TWIDDLE
77*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
twiddle(void)78*8044SWilliam.Kucharski@Sun.COM void twiddle(void)
79*8044SWilliam.Kucharski@Sun.COM {
80*8044SWilliam.Kucharski@Sun.COM #ifdef BAR_PROGRESS
81*8044SWilliam.Kucharski@Sun.COM static int count=0;
82*8044SWilliam.Kucharski@Sun.COM static const char tiddles[]="-\\|/";
83*8044SWilliam.Kucharski@Sun.COM static unsigned long lastticks = 0;
84*8044SWilliam.Kucharski@Sun.COM unsigned long ticks;
85*8044SWilliam.Kucharski@Sun.COM #endif
86*8044SWilliam.Kucharski@Sun.COM #ifdef FREEBSD_PXEEMU
87*8044SWilliam.Kucharski@Sun.COM extern char pxeemu_nbp_active;
88*8044SWilliam.Kucharski@Sun.COM if(pxeemu_nbp_active != 0)
89*8044SWilliam.Kucharski@Sun.COM return;
90*8044SWilliam.Kucharski@Sun.COM #endif
91*8044SWilliam.Kucharski@Sun.COM #ifdef BAR_PROGRESS
92*8044SWilliam.Kucharski@Sun.COM /* Limit the maximum rate at which characters are printed */
93*8044SWilliam.Kucharski@Sun.COM ticks = currticks();
94*8044SWilliam.Kucharski@Sun.COM if ((lastticks + (TICKS_PER_SEC/18)) > ticks)
95*8044SWilliam.Kucharski@Sun.COM return;
96*8044SWilliam.Kucharski@Sun.COM lastticks = ticks;
97*8044SWilliam.Kucharski@Sun.COM
98*8044SWilliam.Kucharski@Sun.COM putchar(tiddles[(count++)&3]);
99*8044SWilliam.Kucharski@Sun.COM putchar('\b');
100*8044SWilliam.Kucharski@Sun.COM #else
101*8044SWilliam.Kucharski@Sun.COM //putchar('.');
102*8044SWilliam.Kucharski@Sun.COM #endif /* BAR_PROGRESS */
103*8044SWilliam.Kucharski@Sun.COM }
104*8044SWilliam.Kucharski@Sun.COM
105*8044SWilliam.Kucharski@Sun.COM
106*8044SWilliam.Kucharski@Sun.COM /* Because Etherboot uses its own formats for the printf family,
107*8044SWilliam.Kucharski@Sun.COM define separate definitions from GRUB. */
108*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
109*8044SWilliam.Kucharski@Sun.COM PRINTF and friends
110*8044SWilliam.Kucharski@Sun.COM
111*8044SWilliam.Kucharski@Sun.COM Formats:
112*8044SWilliam.Kucharski@Sun.COM %[#]x - 4 bytes long (8 hex digits, lower case)
113*8044SWilliam.Kucharski@Sun.COM %[#]X - 4 bytes long (8 hex digits, upper case)
114*8044SWilliam.Kucharski@Sun.COM %[#]hx - 2 bytes int (4 hex digits, lower case)
115*8044SWilliam.Kucharski@Sun.COM %[#]hX - 2 bytes int (4 hex digits, upper case)
116*8044SWilliam.Kucharski@Sun.COM %[#]hhx - 1 byte int (2 hex digits, lower case)
117*8044SWilliam.Kucharski@Sun.COM %[#]hhX - 1 byte int (2 hex digits, upper case)
118*8044SWilliam.Kucharski@Sun.COM - optional # prefixes 0x or 0X
119*8044SWilliam.Kucharski@Sun.COM %d - decimal int
120*8044SWilliam.Kucharski@Sun.COM %c - char
121*8044SWilliam.Kucharski@Sun.COM %s - string
122*8044SWilliam.Kucharski@Sun.COM %@ - Internet address in ddd.ddd.ddd.ddd notation
123*8044SWilliam.Kucharski@Sun.COM %! - Ethernet address in xx:xx:xx:xx:xx:xx notation
124*8044SWilliam.Kucharski@Sun.COM Note: width specification not supported
125*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
126*8044SWilliam.Kucharski@Sun.COM static int
etherboot_vsprintf(char * buf,const char * fmt,const int * dp)127*8044SWilliam.Kucharski@Sun.COM etherboot_vsprintf (char *buf, const char *fmt, const int *dp)
128*8044SWilliam.Kucharski@Sun.COM {
129*8044SWilliam.Kucharski@Sun.COM char *p, *s;
130*8044SWilliam.Kucharski@Sun.COM
131*8044SWilliam.Kucharski@Sun.COM s = buf;
132*8044SWilliam.Kucharski@Sun.COM for ( ; *fmt != '\0'; ++fmt)
133*8044SWilliam.Kucharski@Sun.COM {
134*8044SWilliam.Kucharski@Sun.COM if (*fmt != '%')
135*8044SWilliam.Kucharski@Sun.COM {
136*8044SWilliam.Kucharski@Sun.COM buf ? *s++ = *fmt : grub_putchar (*fmt);
137*8044SWilliam.Kucharski@Sun.COM continue;
138*8044SWilliam.Kucharski@Sun.COM }
139*8044SWilliam.Kucharski@Sun.COM
140*8044SWilliam.Kucharski@Sun.COM if (*++fmt == 's')
141*8044SWilliam.Kucharski@Sun.COM {
142*8044SWilliam.Kucharski@Sun.COM for (p = (char *) *dp++; *p != '\0'; p++)
143*8044SWilliam.Kucharski@Sun.COM buf ? *s++ = *p : grub_putchar (*p);
144*8044SWilliam.Kucharski@Sun.COM }
145*8044SWilliam.Kucharski@Sun.COM else
146*8044SWilliam.Kucharski@Sun.COM {
147*8044SWilliam.Kucharski@Sun.COM /* Length of item is bounded */
148*8044SWilliam.Kucharski@Sun.COM char tmp[20], *q = tmp;
149*8044SWilliam.Kucharski@Sun.COM int alt = 0;
150*8044SWilliam.Kucharski@Sun.COM int shift = 28;
151*8044SWilliam.Kucharski@Sun.COM
152*8044SWilliam.Kucharski@Sun.COM if (*fmt == '#')
153*8044SWilliam.Kucharski@Sun.COM {
154*8044SWilliam.Kucharski@Sun.COM alt = 1;
155*8044SWilliam.Kucharski@Sun.COM fmt++;
156*8044SWilliam.Kucharski@Sun.COM }
157*8044SWilliam.Kucharski@Sun.COM
158*8044SWilliam.Kucharski@Sun.COM if (*fmt == 'h')
159*8044SWilliam.Kucharski@Sun.COM {
160*8044SWilliam.Kucharski@Sun.COM shift = 12;
161*8044SWilliam.Kucharski@Sun.COM fmt++;
162*8044SWilliam.Kucharski@Sun.COM }
163*8044SWilliam.Kucharski@Sun.COM
164*8044SWilliam.Kucharski@Sun.COM if (*fmt == 'h')
165*8044SWilliam.Kucharski@Sun.COM {
166*8044SWilliam.Kucharski@Sun.COM shift = 4;
167*8044SWilliam.Kucharski@Sun.COM fmt++;
168*8044SWilliam.Kucharski@Sun.COM }
169*8044SWilliam.Kucharski@Sun.COM
170*8044SWilliam.Kucharski@Sun.COM /*
171*8044SWilliam.Kucharski@Sun.COM * Before each format q points to tmp buffer
172*8044SWilliam.Kucharski@Sun.COM * After each format q points past end of item
173*8044SWilliam.Kucharski@Sun.COM */
174*8044SWilliam.Kucharski@Sun.COM if ((*fmt | 0x20) == 'x')
175*8044SWilliam.Kucharski@Sun.COM {
176*8044SWilliam.Kucharski@Sun.COM /* With x86 gcc, sizeof(long) == sizeof(int) */
177*8044SWilliam.Kucharski@Sun.COM const long *lp = (const long *) dp;
178*8044SWilliam.Kucharski@Sun.COM long h = *lp++;
179*8044SWilliam.Kucharski@Sun.COM int ncase = (*fmt & 0x20);
180*8044SWilliam.Kucharski@Sun.COM
181*8044SWilliam.Kucharski@Sun.COM dp = (const int *) lp;
182*8044SWilliam.Kucharski@Sun.COM if (alt)
183*8044SWilliam.Kucharski@Sun.COM {
184*8044SWilliam.Kucharski@Sun.COM *q++ = '0';
185*8044SWilliam.Kucharski@Sun.COM *q++ = 'X' | ncase;
186*8044SWilliam.Kucharski@Sun.COM }
187*8044SWilliam.Kucharski@Sun.COM for (; shift >= 0; shift -= 4)
188*8044SWilliam.Kucharski@Sun.COM *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
189*8044SWilliam.Kucharski@Sun.COM }
190*8044SWilliam.Kucharski@Sun.COM else if (*fmt == 'd')
191*8044SWilliam.Kucharski@Sun.COM {
192*8044SWilliam.Kucharski@Sun.COM int i = *dp++;
193*8044SWilliam.Kucharski@Sun.COM char *r;
194*8044SWilliam.Kucharski@Sun.COM
195*8044SWilliam.Kucharski@Sun.COM if (i < 0)
196*8044SWilliam.Kucharski@Sun.COM {
197*8044SWilliam.Kucharski@Sun.COM *q++ = '-';
198*8044SWilliam.Kucharski@Sun.COM i = -i;
199*8044SWilliam.Kucharski@Sun.COM }
200*8044SWilliam.Kucharski@Sun.COM
201*8044SWilliam.Kucharski@Sun.COM p = q; /* save beginning of digits */
202*8044SWilliam.Kucharski@Sun.COM do
203*8044SWilliam.Kucharski@Sun.COM {
204*8044SWilliam.Kucharski@Sun.COM *q++ = '0' + (i % 10);
205*8044SWilliam.Kucharski@Sun.COM i /= 10;
206*8044SWilliam.Kucharski@Sun.COM }
207*8044SWilliam.Kucharski@Sun.COM while (i);
208*8044SWilliam.Kucharski@Sun.COM
209*8044SWilliam.Kucharski@Sun.COM /* reverse digits, stop in middle */
210*8044SWilliam.Kucharski@Sun.COM r = q; /* don't alter q */
211*8044SWilliam.Kucharski@Sun.COM while (--r > p)
212*8044SWilliam.Kucharski@Sun.COM {
213*8044SWilliam.Kucharski@Sun.COM i = *r;
214*8044SWilliam.Kucharski@Sun.COM *r = *p;
215*8044SWilliam.Kucharski@Sun.COM *p++ = i;
216*8044SWilliam.Kucharski@Sun.COM }
217*8044SWilliam.Kucharski@Sun.COM }
218*8044SWilliam.Kucharski@Sun.COM else if (*fmt == '@')
219*8044SWilliam.Kucharski@Sun.COM {
220*8044SWilliam.Kucharski@Sun.COM unsigned char *r;
221*8044SWilliam.Kucharski@Sun.COM union
222*8044SWilliam.Kucharski@Sun.COM {
223*8044SWilliam.Kucharski@Sun.COM long l;
224*8044SWilliam.Kucharski@Sun.COM unsigned char c[4];
225*8044SWilliam.Kucharski@Sun.COM }
226*8044SWilliam.Kucharski@Sun.COM u;
227*8044SWilliam.Kucharski@Sun.COM const long *lp = (const long *) dp;
228*8044SWilliam.Kucharski@Sun.COM
229*8044SWilliam.Kucharski@Sun.COM u.l = *lp++;
230*8044SWilliam.Kucharski@Sun.COM dp = (const int *) lp;
231*8044SWilliam.Kucharski@Sun.COM
232*8044SWilliam.Kucharski@Sun.COM for (r = &u.c[0]; r < &u.c[4]; ++r)
233*8044SWilliam.Kucharski@Sun.COM q += etherboot_sprintf (q, "%d.", *r);
234*8044SWilliam.Kucharski@Sun.COM
235*8044SWilliam.Kucharski@Sun.COM --q;
236*8044SWilliam.Kucharski@Sun.COM }
237*8044SWilliam.Kucharski@Sun.COM else if (*fmt == '!')
238*8044SWilliam.Kucharski@Sun.COM {
239*8044SWilliam.Kucharski@Sun.COM char *r;
240*8044SWilliam.Kucharski@Sun.COM p = (char *) *dp++;
241*8044SWilliam.Kucharski@Sun.COM
242*8044SWilliam.Kucharski@Sun.COM for (r = p + ETH_ALEN; p < r; ++p)
243*8044SWilliam.Kucharski@Sun.COM q += etherboot_sprintf (q, "%hhX:", *p);
244*8044SWilliam.Kucharski@Sun.COM
245*8044SWilliam.Kucharski@Sun.COM --q;
246*8044SWilliam.Kucharski@Sun.COM }
247*8044SWilliam.Kucharski@Sun.COM else if (*fmt == 'c')
248*8044SWilliam.Kucharski@Sun.COM *q++ = *dp++;
249*8044SWilliam.Kucharski@Sun.COM else
250*8044SWilliam.Kucharski@Sun.COM *q++ = *fmt;
251*8044SWilliam.Kucharski@Sun.COM
252*8044SWilliam.Kucharski@Sun.COM /* now output the saved string */
253*8044SWilliam.Kucharski@Sun.COM for (p = tmp; p < q; ++p)
254*8044SWilliam.Kucharski@Sun.COM buf ? *s++ = *p : grub_putchar (*p);
255*8044SWilliam.Kucharski@Sun.COM }
256*8044SWilliam.Kucharski@Sun.COM }
257*8044SWilliam.Kucharski@Sun.COM
258*8044SWilliam.Kucharski@Sun.COM if (buf)
259*8044SWilliam.Kucharski@Sun.COM *s = '\0';
260*8044SWilliam.Kucharski@Sun.COM
261*8044SWilliam.Kucharski@Sun.COM return (s - buf);
262*8044SWilliam.Kucharski@Sun.COM }
263*8044SWilliam.Kucharski@Sun.COM
264*8044SWilliam.Kucharski@Sun.COM int
etherboot_sprintf(char * buf,const char * fmt,...)265*8044SWilliam.Kucharski@Sun.COM etherboot_sprintf (char *buf, const char *fmt, ...)
266*8044SWilliam.Kucharski@Sun.COM {
267*8044SWilliam.Kucharski@Sun.COM return etherboot_vsprintf (buf, fmt, ((const int *) &fmt) + 1);
268*8044SWilliam.Kucharski@Sun.COM }
269*8044SWilliam.Kucharski@Sun.COM
270*8044SWilliam.Kucharski@Sun.COM void
etherboot_printf(const char * fmt,...)271*8044SWilliam.Kucharski@Sun.COM etherboot_printf (const char *fmt, ...)
272*8044SWilliam.Kucharski@Sun.COM {
273*8044SWilliam.Kucharski@Sun.COM (void) etherboot_vsprintf (0, fmt, ((const int *) &fmt) + 1);
274*8044SWilliam.Kucharski@Sun.COM }
275*8044SWilliam.Kucharski@Sun.COM
276*8044SWilliam.Kucharski@Sun.COM int
inet_aton(char * p,in_addr * addr)277*8044SWilliam.Kucharski@Sun.COM inet_aton (char *p, in_addr *addr)
278*8044SWilliam.Kucharski@Sun.COM {
279*8044SWilliam.Kucharski@Sun.COM unsigned long ip = 0;
280*8044SWilliam.Kucharski@Sun.COM int val;
281*8044SWilliam.Kucharski@Sun.COM int i;
282*8044SWilliam.Kucharski@Sun.COM
283*8044SWilliam.Kucharski@Sun.COM for (i = 0; i < 4; i++)
284*8044SWilliam.Kucharski@Sun.COM {
285*8044SWilliam.Kucharski@Sun.COM val = getdec (&p);
286*8044SWilliam.Kucharski@Sun.COM
287*8044SWilliam.Kucharski@Sun.COM if (val < 0 || val > 255)
288*8044SWilliam.Kucharski@Sun.COM return 0;
289*8044SWilliam.Kucharski@Sun.COM
290*8044SWilliam.Kucharski@Sun.COM if (i != 3 && *p++ != '.')
291*8044SWilliam.Kucharski@Sun.COM return 0;
292*8044SWilliam.Kucharski@Sun.COM
293*8044SWilliam.Kucharski@Sun.COM ip = (ip << 8) | val;
294*8044SWilliam.Kucharski@Sun.COM }
295*8044SWilliam.Kucharski@Sun.COM
296*8044SWilliam.Kucharski@Sun.COM addr->s_addr = htonl (ip);
297*8044SWilliam.Kucharski@Sun.COM
298*8044SWilliam.Kucharski@Sun.COM return 1;
299*8044SWilliam.Kucharski@Sun.COM }
300*8044SWilliam.Kucharski@Sun.COM
301*8044SWilliam.Kucharski@Sun.COM int
getdec(char ** ptr)302*8044SWilliam.Kucharski@Sun.COM getdec (char **ptr)
303*8044SWilliam.Kucharski@Sun.COM {
304*8044SWilliam.Kucharski@Sun.COM char *p = *ptr;
305*8044SWilliam.Kucharski@Sun.COM int ret = 0;
306*8044SWilliam.Kucharski@Sun.COM
307*8044SWilliam.Kucharski@Sun.COM if (*p < '0' || *p > '9')
308*8044SWilliam.Kucharski@Sun.COM return -1;
309*8044SWilliam.Kucharski@Sun.COM
310*8044SWilliam.Kucharski@Sun.COM while (*p >= '0' && *p <= '9')
311*8044SWilliam.Kucharski@Sun.COM {
312*8044SWilliam.Kucharski@Sun.COM ret = ret * 10 + (*p - '0');
313*8044SWilliam.Kucharski@Sun.COM p++;
314*8044SWilliam.Kucharski@Sun.COM }
315*8044SWilliam.Kucharski@Sun.COM
316*8044SWilliam.Kucharski@Sun.COM *ptr = p;
317*8044SWilliam.Kucharski@Sun.COM
318*8044SWilliam.Kucharski@Sun.COM return ret;
319*8044SWilliam.Kucharski@Sun.COM }
320*8044SWilliam.Kucharski@Sun.COM
321*8044SWilliam.Kucharski@Sun.COM
322