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 **************************************************************************/ 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 **************************************************************************/ 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 **************************************************************************/ 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 **************************************************************************/ 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 **************************************************************************/ 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 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 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 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 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 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