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