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