~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to kern/misc.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* misc.c - definitions of misc functions */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010  Free Software Foundation, Inc.
5
 
 *
6
 
 *  GRUB is free software: you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation, either version 3 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  GRUB is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include <grub/misc.h>
21
 
#include <grub/err.h>
22
 
#include <grub/mm.h>
23
 
#include <stdarg.h>
24
 
#include <grub/term.h>
25
 
#include <grub/env.h>
26
 
#include <grub/i18n.h>
27
 
 
28
 
static int
29
 
grub_vsnprintf_real (char *str, grub_size_t n, const char *fmt, va_list args);
30
 
 
31
 
static int
32
 
grub_iswordseparator (int c)
33
 
{
34
 
  return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
35
 
}
36
 
 
37
 
/* grub_gettext_dummy is not translating anything.  */
38
 
static const char *
39
 
grub_gettext_dummy (const char *s)
40
 
{
41
 
  return s;
42
 
}
43
 
 
44
 
const char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
45
 
 
46
 
void *
47
 
grub_memmove (void *dest, const void *src, grub_size_t n)
48
 
{
49
 
  char *d = (char *) dest;
50
 
  const char *s = (const char *) src;
51
 
 
52
 
  if (d < s)
53
 
    while (n--)
54
 
      *d++ = *s++;
55
 
  else
56
 
    {
57
 
      d += n;
58
 
      s += n;
59
 
 
60
 
      while (n--)
61
 
        *--d = *--s;
62
 
    }
63
 
 
64
 
  return dest;
65
 
}
66
 
 
67
 
#ifndef APPLE_CC
68
 
void *memmove (void *dest, const void *src, grub_size_t n)
69
 
  __attribute__ ((alias ("grub_memmove")));
70
 
/* GCC emits references to memcpy() for struct copies etc.  */
71
 
void *memcpy (void *dest, const void *src, grub_size_t n)
72
 
  __attribute__ ((alias ("grub_memmove")));
73
 
#else
74
 
void *memcpy (void *dest, const void *src, grub_size_t n)
75
 
{
76
 
        return grub_memmove (dest, src, n);
77
 
}
78
 
void *memmove (void *dest, const void *src, grub_size_t n)
79
 
{
80
 
        return grub_memmove (dest, src, n);
81
 
}
82
 
#endif
83
 
 
84
 
char *
85
 
grub_strcpy (char *dest, const char *src)
86
 
{
87
 
  char *p = dest;
88
 
 
89
 
  while ((*p++ = *src++) != '\0')
90
 
    ;
91
 
 
92
 
  return dest;
93
 
}
94
 
 
95
 
char *
96
 
grub_strncpy (char *dest, const char *src, int c)
97
 
{
98
 
  char *p = dest;
99
 
 
100
 
  while ((*p++ = *src++) != '\0' && --c)
101
 
    ;
102
 
 
103
 
  return dest;
104
 
}
105
 
 
106
 
char *
107
 
grub_stpcpy (char *dest, const char *src)
108
 
{
109
 
  char *d = dest;
110
 
  const char *s = src;
111
 
 
112
 
  do
113
 
    *d++ = *s;
114
 
  while (*s++ != '\0');
115
 
 
116
 
  return d - 1;
117
 
}
118
 
 
119
 
int
120
 
grub_printf (const char *fmt, ...)
121
 
{
122
 
  va_list ap;
123
 
  int ret;
124
 
 
125
 
  va_start (ap, fmt);
126
 
  ret = grub_vprintf (fmt, ap);
127
 
  va_end (ap);
128
 
 
129
 
  return ret;
130
 
}
131
 
 
132
 
int
133
 
grub_printf_ (const char *fmt, ...)
134
 
{
135
 
  va_list ap;
136
 
  int ret;
137
 
 
138
 
  va_start (ap, fmt);
139
 
  ret = grub_vprintf (_(fmt), ap);
140
 
  va_end (ap);
141
 
 
142
 
  return ret;
143
 
}
144
 
 
145
 
int
146
 
grub_puts_ (const char *s)
147
 
{
148
 
  return grub_puts (_(s));
149
 
}
150
 
 
151
 
#if defined (APPLE_CC) && ! defined (GRUB_UTIL)
152
 
int
153
 
grub_err_printf (const char *fmt, ...)
154
 
{
155
 
        va_list ap;
156
 
        int ret;
157
 
 
158
 
        va_start (ap, fmt);
159
 
        ret = grub_vprintf (fmt, ap);
160
 
        va_end (ap);
161
 
 
162
 
        return ret;
163
 
}
164
 
#endif
165
 
 
166
 
#if ! defined (APPLE_CC) && ! defined (GRUB_UTIL)
167
 
int grub_err_printf (const char *fmt, ...)
168
 
__attribute__ ((alias("grub_printf")));
169
 
#endif
170
 
 
171
 
void
172
 
grub_real_dprintf (const char *file, const int line, const char *condition,
173
 
                   const char *fmt, ...)
174
 
{
175
 
  va_list args;
176
 
  const char *debug = grub_env_get ("debug");
177
 
 
178
 
  if (! debug)
179
 
    return;
180
 
 
181
 
  if (grub_strword (debug, "all") || grub_strword (debug, condition))
182
 
    {
183
 
      grub_printf ("%s:%d: ", file, line);
184
 
      va_start (args, fmt);
185
 
      grub_vprintf (fmt, args);
186
 
      va_end (args);
187
 
    }
188
 
}
189
 
 
190
 
#define PREALLOC_SIZE 255
191
 
 
192
 
int
193
 
grub_vprintf (const char *fmt, va_list args)
194
 
{
195
 
  grub_size_t s;
196
 
  static char buf[PREALLOC_SIZE + 1];
197
 
  char *curbuf = buf;
198
 
 
199
 
  s = grub_vsnprintf_real (buf, PREALLOC_SIZE, fmt, args);
200
 
  if (s > PREALLOC_SIZE)
201
 
    {
202
 
      curbuf = grub_malloc (s + 1);
203
 
      if (!curbuf)
204
 
        {
205
 
          grub_errno = GRUB_ERR_NONE;
206
 
          buf[PREALLOC_SIZE - 3] = '.';
207
 
          buf[PREALLOC_SIZE - 2] = '.';
208
 
          buf[PREALLOC_SIZE - 1] = '.';
209
 
          buf[PREALLOC_SIZE] = 0;
210
 
        }
211
 
      else
212
 
        s = grub_vsnprintf_real (curbuf, s, fmt, args);
213
 
    }
214
 
 
215
 
  grub_xputs (curbuf);
216
 
 
217
 
  if (curbuf != buf)
218
 
    grub_free (curbuf);
219
 
  
220
 
  return s;
221
 
}
222
 
 
223
 
int
224
 
grub_memcmp (const void *s1, const void *s2, grub_size_t n)
225
 
{
226
 
  const char *t1 = s1;
227
 
  const char *t2 = s2;
228
 
 
229
 
  while (n--)
230
 
    {
231
 
      if (*t1 != *t2)
232
 
        return (int) *t1 - (int) *t2;
233
 
 
234
 
      t1++;
235
 
      t2++;
236
 
    }
237
 
 
238
 
  return 0;
239
 
}
240
 
#ifndef APPLE_CC
241
 
int memcmp (const void *s1, const void *s2, grub_size_t n)
242
 
  __attribute__ ((alias ("grub_memcmp")));
243
 
#else
244
 
int memcmp (const void *s1, const void *s2, grub_size_t n)
245
 
{
246
 
  return grub_memcmp (s1, s2, n);
247
 
}
248
 
#endif
249
 
 
250
 
int
251
 
grub_strcmp (const char *s1, const char *s2)
252
 
{
253
 
  while (*s1 && *s2)
254
 
    {
255
 
      if (*s1 != *s2)
256
 
        break;
257
 
 
258
 
      s1++;
259
 
      s2++;
260
 
    }
261
 
 
262
 
  return (int) *s1 - (int) *s2;
263
 
}
264
 
 
265
 
int
266
 
grub_strncmp (const char *s1, const char *s2, grub_size_t n)
267
 
{
268
 
  if (n == 0)
269
 
    return 0;
270
 
 
271
 
  while (*s1 && *s2 && --n)
272
 
    {
273
 
      if (*s1 != *s2)
274
 
        break;
275
 
 
276
 
      s1++;
277
 
      s2++;
278
 
    }
279
 
 
280
 
  return (int) *s1 - (int) *s2;
281
 
}
282
 
 
283
 
char *
284
 
grub_strchr (const char *s, int c)
285
 
{
286
 
  do
287
 
    {
288
 
      if (*s == c)
289
 
        return (char *) s;
290
 
    }
291
 
  while (*s++);
292
 
 
293
 
  return 0;
294
 
}
295
 
 
296
 
char *
297
 
grub_strrchr (const char *s, int c)
298
 
{
299
 
  char *p = NULL;
300
 
 
301
 
  do
302
 
    {
303
 
      if (*s == c)
304
 
        p = (char *) s;
305
 
    }
306
 
  while (*s++);
307
 
 
308
 
  return p;
309
 
}
310
 
 
311
 
/* Copied from gnulib.
312
 
   Written by Bruno Haible <bruno@clisp.org>, 2005. */
313
 
char *
314
 
grub_strstr (const char *haystack, const char *needle)
315
 
{
316
 
  /* Be careful not to look at the entire extent of haystack or needle
317
 
     until needed.  This is useful because of these two cases:
318
 
       - haystack may be very long, and a match of needle found early,
319
 
       - needle may be very long, and not even a short initial segment of
320
 
       needle may be found in haystack.  */
321
 
  if (*needle != '\0')
322
 
    {
323
 
      /* Speed up the following searches of needle by caching its first
324
 
         character.  */
325
 
      char b = *needle++;
326
 
 
327
 
      for (;; haystack++)
328
 
        {
329
 
          if (*haystack == '\0')
330
 
            /* No match.  */
331
 
            return NULL;
332
 
          if (*haystack == b)
333
 
            /* The first character matches.  */
334
 
            {
335
 
              const char *rhaystack = haystack + 1;
336
 
              const char *rneedle = needle;
337
 
 
338
 
              for (;; rhaystack++, rneedle++)
339
 
                {
340
 
                  if (*rneedle == '\0')
341
 
                    /* Found a match.  */
342
 
                    return (char *) haystack;
343
 
                  if (*rhaystack == '\0')
344
 
                    /* No match.  */
345
 
                    return NULL;
346
 
                  if (*rhaystack != *rneedle)
347
 
                    /* Nothing in this round.  */
348
 
                    break;
349
 
                }
350
 
            }
351
 
        }
352
 
    }
353
 
  else
354
 
    return (char *) haystack;
355
 
}
356
 
 
357
 
int
358
 
grub_strword (const char *haystack, const char *needle)
359
 
{
360
 
  const char *n_pos = needle;
361
 
 
362
 
  while (grub_iswordseparator (*haystack))
363
 
    haystack++;
364
 
 
365
 
  while (*haystack)
366
 
    {
367
 
      /* Crawl both the needle and the haystack word we're on.  */
368
 
      while(*haystack && !grub_iswordseparator (*haystack)
369
 
            && *haystack == *n_pos)
370
 
        {
371
 
          haystack++;
372
 
          n_pos++;
373
 
        }
374
 
 
375
 
      /* If we reached the end of both words at the same time, the word
376
 
      is found. If not, eat everything in the haystack that isn't the
377
 
      next word (or the end of string) and "reset" the needle.  */
378
 
      if ( (!*haystack || grub_iswordseparator (*haystack))
379
 
         && (!*n_pos || grub_iswordseparator (*n_pos)))
380
 
        return 1;
381
 
      else
382
 
        {
383
 
          n_pos = needle;
384
 
          while (*haystack && !grub_iswordseparator (*haystack))
385
 
            haystack++;
386
 
          while (grub_iswordseparator (*haystack))
387
 
            haystack++;
388
 
        }
389
 
    }
390
 
 
391
 
  return 0;
392
 
}
393
 
 
394
 
int
395
 
grub_isspace (int c)
396
 
{
397
 
  return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
398
 
}
399
 
 
400
 
int
401
 
grub_isprint (int c)
402
 
{
403
 
  return (c >= ' ' && c <= '~');
404
 
}
405
 
 
406
 
 
407
 
unsigned long
408
 
grub_strtoul (const char *str, char **end, int base)
409
 
{
410
 
  unsigned long long num;
411
 
 
412
 
  num = grub_strtoull (str, end, base);
413
 
  if (num > ~0UL)
414
 
    {
415
 
      grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
416
 
      return ~0UL;
417
 
    }
418
 
 
419
 
  return (unsigned long) num;
420
 
}
421
 
 
422
 
unsigned long long
423
 
grub_strtoull (const char *str, char **end, int base)
424
 
{
425
 
  unsigned long long num = 0;
426
 
  int found = 0;
427
 
 
428
 
  /* Skip white spaces.  */
429
 
  while (*str && grub_isspace (*str))
430
 
    str++;
431
 
 
432
 
  /* Guess the base, if not specified. The prefix `0x' means 16, and
433
 
     the prefix `0' means 8.  */
434
 
  if (str[0] == '0')
435
 
    {
436
 
      if (str[1] == 'x')
437
 
        {
438
 
          if (base == 0 || base == 16)
439
 
            {
440
 
              base = 16;
441
 
              str += 2;
442
 
            }
443
 
        }
444
 
      else if (base == 0 && str[1] >= '0' && str[1] <= '7')
445
 
        base = 8;
446
 
    }
447
 
 
448
 
  if (base == 0)
449
 
    base = 10;
450
 
 
451
 
  while (*str)
452
 
    {
453
 
      unsigned long digit;
454
 
 
455
 
      digit = grub_tolower (*str) - '0';
456
 
      if (digit > 9)
457
 
        {
458
 
          digit += '0' - 'a' + 10;
459
 
          if (digit >= (unsigned long) base)
460
 
            break;
461
 
        }
462
 
 
463
 
      found = 1;
464
 
 
465
 
      /* NUM * BASE + DIGIT > ~0ULL */
466
 
      if (num > grub_divmod64 (~0ULL - digit, base, 0))
467
 
        {
468
 
          grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
469
 
          return ~0ULL;
470
 
        }
471
 
 
472
 
      num = num * base + digit;
473
 
      str++;
474
 
    }
475
 
 
476
 
  if (! found)
477
 
    {
478
 
      grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
479
 
      return 0;
480
 
    }
481
 
 
482
 
  if (end)
483
 
    *end = (char *) str;
484
 
 
485
 
  return num;
486
 
}
487
 
 
488
 
char *
489
 
grub_strdup (const char *s)
490
 
{
491
 
  grub_size_t len;
492
 
  char *p;
493
 
 
494
 
  len = grub_strlen (s) + 1;
495
 
  p = (char *) grub_malloc (len);
496
 
  if (! p)
497
 
    return 0;
498
 
 
499
 
  return grub_memcpy (p, s, len);
500
 
}
501
 
 
502
 
char *
503
 
grub_strndup (const char *s, grub_size_t n)
504
 
{
505
 
  grub_size_t len;
506
 
  char *p;
507
 
 
508
 
  len = grub_strlen (s);
509
 
  if (len > n)
510
 
    len = n;
511
 
  p = (char *) grub_malloc (len + 1);
512
 
  if (! p)
513
 
    return 0;
514
 
 
515
 
  grub_memcpy (p, s, len);
516
 
  p[len] = '\0';
517
 
  return p;
518
 
}
519
 
 
520
 
void *
521
 
grub_memset (void *s, int c, grub_size_t len)
522
 
{
523
 
  void *p = s;
524
 
  grub_uint8_t pattern8 = c;
525
 
 
526
 
  if (len >= 3 * sizeof (unsigned long))
527
 
    {
528
 
      unsigned long patternl = 0;
529
 
      grub_size_t i;
530
 
 
531
 
      for (i = 0; i < sizeof (unsigned long); i++)
532
 
        patternl |= ((unsigned long) pattern8) << (8 * i);
533
 
 
534
 
      while (len > 0 && (((grub_addr_t) p) & (sizeof (unsigned long) - 1)))
535
 
        {
536
 
          *(grub_uint8_t *) p = pattern8;
537
 
          p = (grub_uint8_t *) p + 1;
538
 
          len--;
539
 
        }
540
 
      while (len >= sizeof (unsigned long))
541
 
        {
542
 
          *(unsigned long *) p = patternl;
543
 
          p = (unsigned long *) p + 1;
544
 
          len -= sizeof (unsigned long);
545
 
        }
546
 
    }
547
 
 
548
 
  while (len > 0)
549
 
    {
550
 
      *(grub_uint8_t *) p = pattern8;
551
 
      p = (grub_uint8_t *) p + 1;
552
 
      len--;
553
 
    }
554
 
 
555
 
  return s;
556
 
}
557
 
#ifndef APPLE_CC
558
 
void *memset (void *s, int c, grub_size_t n)
559
 
  __attribute__ ((alias ("grub_memset")));
560
 
#else
561
 
void *memset (void *s, int c, grub_size_t n)
562
 
{
563
 
  return grub_memset (s, c, n);
564
 
}
565
 
#endif
566
 
 
567
 
grub_size_t
568
 
grub_strlen (const char *s)
569
 
{
570
 
  const char *p = s;
571
 
 
572
 
  while (*p)
573
 
    p++;
574
 
 
575
 
  return p - s;
576
 
}
577
 
 
578
 
static inline void
579
 
grub_reverse (char *str)
580
 
{
581
 
  char *p = str + grub_strlen (str) - 1;
582
 
 
583
 
  while (str < p)
584
 
    {
585
 
      char tmp;
586
 
 
587
 
      tmp = *str;
588
 
      *str = *p;
589
 
      *p = tmp;
590
 
      str++;
591
 
      p--;
592
 
    }
593
 
}
594
 
 
595
 
/* Divide N by D, return the quotient, and store the remainder in *R.  */
596
 
grub_uint64_t
597
 
grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
598
 
{
599
 
  /* This algorithm is typically implemented by hardware. The idea
600
 
     is to get the highest bit in N, 64 times, by keeping
601
 
     upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper
602
 
     represents the high 64 bits in 128-bits space.  */
603
 
  unsigned bits = 64;
604
 
  unsigned long long q = 0;
605
 
  unsigned m = 0;
606
 
 
607
 
  /* Skip the slow computation if 32-bit arithmetic is possible.  */
608
 
  if (n < 0xffffffff)
609
 
    {
610
 
      if (r)
611
 
        *r = ((grub_uint32_t) n) % d;
612
 
 
613
 
      return ((grub_uint32_t) n) / d;
614
 
    }
615
 
 
616
 
  while (bits--)
617
 
    {
618
 
      m <<= 1;
619
 
 
620
 
      if (n & (1ULL << 63))
621
 
        m |= 1;
622
 
 
623
 
      q <<= 1;
624
 
      n <<= 1;
625
 
 
626
 
      if (m >= d)
627
 
        {
628
 
          q |= 1;
629
 
          m -= d;
630
 
        }
631
 
    }
632
 
 
633
 
  if (r)
634
 
    *r = m;
635
 
 
636
 
  return q;
637
 
}
638
 
 
639
 
/* Convert a long long value to a string. This function avoids 64-bit
640
 
   modular arithmetic or divisions.  */
641
 
static char *
642
 
grub_lltoa (char *str, int c, unsigned long long n)
643
 
{
644
 
  unsigned base = (c == 'x') ? 16 : 10;
645
 
  char *p;
646
 
 
647
 
  if ((long long) n < 0 && c == 'd')
648
 
    {
649
 
      n = (unsigned long long) (-((long long) n));
650
 
      *str++ = '-';
651
 
    }
652
 
 
653
 
  p = str;
654
 
 
655
 
  if (base == 16)
656
 
    do
657
 
      {
658
 
        unsigned d = (unsigned) (n & 0xf);
659
 
        *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
660
 
      }
661
 
    while (n >>= 4);
662
 
  else
663
 
    /* BASE == 10 */
664
 
    do
665
 
      {
666
 
        unsigned m;
667
 
 
668
 
        n = grub_divmod64 (n, 10, &m);
669
 
        *p++ = m + '0';
670
 
      }
671
 
    while (n);
672
 
 
673
 
  *p = 0;
674
 
 
675
 
  grub_reverse (str);
676
 
  return p;
677
 
}
678
 
 
679
 
static int
680
 
grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt, va_list args)
681
 
{
682
 
  char c;
683
 
  grub_size_t count = 0;
684
 
  auto void write_char (unsigned char ch);
685
 
  auto void write_str (const char *s);
686
 
  auto void write_fill (const char ch, int n);
687
 
 
688
 
  void write_char (unsigned char ch)
689
 
    {
690
 
      if (count < max_len)
691
 
        *str++ = ch;
692
 
 
693
 
      count++;
694
 
    }
695
 
 
696
 
  void write_str (const char *s)
697
 
    {
698
 
      while (*s)
699
 
        write_char (*s++);
700
 
    }
701
 
 
702
 
  void write_fill (const char ch, int n)
703
 
    {
704
 
      int i;
705
 
      for (i = 0; i < n; i++)
706
 
        write_char (ch);
707
 
    }
708
 
 
709
 
  while ((c = *fmt++) != 0)
710
 
    {
711
 
      if (c != '%')
712
 
        write_char (c);
713
 
      else
714
 
        {
715
 
          char tmp[32];
716
 
          char *p;
717
 
          unsigned int format1 = 0;
718
 
          unsigned int format2 = ~ 0U;
719
 
          char zerofill = ' ';
720
 
          int rightfill = 0;
721
 
          int n;
722
 
          int longfmt = 0;
723
 
          int longlongfmt = 0;
724
 
          int unsig = 0;
725
 
 
726
 
          if (*fmt && *fmt =='-')
727
 
            {
728
 
              rightfill = 1;
729
 
              fmt++;
730
 
            }
731
 
 
732
 
          p = (char *) fmt;
733
 
          /* Read formatting parameters.  */
734
 
          while (*p && grub_isdigit (*p))
735
 
            p++;
736
 
 
737
 
          if (p > fmt)
738
 
            {
739
 
              char s[p - fmt + 1];
740
 
              grub_strncpy (s, fmt, p - fmt);
741
 
              s[p - fmt] = 0;
742
 
              if (s[0] == '0')
743
 
                zerofill = '0';
744
 
              format1 = grub_strtoul (s, 0, 10);
745
 
              fmt = p;
746
 
            }
747
 
 
748
 
          if (*p && *p == '.')
749
 
            {
750
 
              p++;
751
 
              fmt++;
752
 
              while (*p && grub_isdigit (*p))
753
 
                p++;
754
 
 
755
 
              if (p > fmt)
756
 
                {
757
 
                  char fstr[p - fmt + 1];
758
 
                  grub_strncpy (fstr, fmt, p - fmt);
759
 
                  fstr[p - fmt] = 0;
760
 
                  format2 = grub_strtoul (fstr, 0, 10);
761
 
                  fmt = p;
762
 
                }
763
 
            }
764
 
 
765
 
          c = *fmt++;
766
 
          if (c == 'l')
767
 
            {
768
 
              longfmt = 1;
769
 
              c = *fmt++;
770
 
              if (c == 'l')
771
 
                {
772
 
                  longlongfmt = 1;
773
 
                  c = *fmt++;
774
 
                }
775
 
            }
776
 
 
777
 
          switch (c)
778
 
            {
779
 
            case 'p':
780
 
              write_str ("0x");
781
 
              c = 'x';
782
 
              longlongfmt |= (sizeof (void *) == sizeof (long long));
783
 
              /* Fall through. */
784
 
            case 'x':
785
 
            case 'u':
786
 
              unsig = 1;
787
 
              /* Fall through. */
788
 
            case 'd':
789
 
              if (longlongfmt)
790
 
                {
791
 
                  long long ll;
792
 
 
793
 
                  ll = va_arg (args, long long);
794
 
                  grub_lltoa (tmp, c, ll);
795
 
                }
796
 
              else if (longfmt && unsig)
797
 
                {
798
 
                  unsigned long l = va_arg (args, unsigned long);
799
 
                  grub_lltoa (tmp, c, l);
800
 
                }
801
 
              else if (longfmt)
802
 
                {
803
 
                  long l = va_arg (args, long);
804
 
                  grub_lltoa (tmp, c, l);
805
 
                }
806
 
              else if (unsig)
807
 
                {
808
 
                  unsigned u = va_arg (args, unsigned);
809
 
                  grub_lltoa (tmp, c, u);
810
 
                }
811
 
              else
812
 
                {
813
 
                  n = va_arg (args, int);
814
 
                  grub_lltoa (tmp, c, n);
815
 
                }
816
 
              if (! rightfill && grub_strlen (tmp) < format1)
817
 
                write_fill (zerofill, format1 - grub_strlen (tmp));
818
 
              write_str (tmp);
819
 
              if (rightfill && grub_strlen (tmp) < format1)
820
 
                write_fill (zerofill, format1 - grub_strlen (tmp));
821
 
              break;
822
 
 
823
 
            case 'c':
824
 
              n = va_arg (args, int);
825
 
              write_char (n & 0xff);
826
 
              break;
827
 
 
828
 
            case 'C':
829
 
              {
830
 
                grub_uint32_t code = va_arg (args, grub_uint32_t);
831
 
                int shift;
832
 
                unsigned mask;
833
 
 
834
 
                if (code <= 0x7f)
835
 
                  {
836
 
                    shift = 0;
837
 
                    mask = 0;
838
 
                  }
839
 
                else if (code <= 0x7ff)
840
 
                  {
841
 
                    shift = 6;
842
 
                    mask = 0xc0;
843
 
                  }
844
 
                else if (code <= 0xffff)
845
 
                  {
846
 
                    shift = 12;
847
 
                    mask = 0xe0;
848
 
                  }
849
 
                else if (code <= 0x1fffff)
850
 
                  {
851
 
                    shift = 18;
852
 
                    mask = 0xf0;
853
 
                  }
854
 
                else if (code <= 0x3ffffff)
855
 
                  {
856
 
                    shift = 24;
857
 
                    mask = 0xf8;
858
 
                  }
859
 
                else if (code <= 0x7fffffff)
860
 
                  {
861
 
                    shift = 30;
862
 
                    mask = 0xfc;
863
 
                  }
864
 
                else
865
 
                  {
866
 
                    code = '?';
867
 
                    shift = 0;
868
 
                    mask = 0;
869
 
                  }
870
 
 
871
 
                write_char (mask | (code >> shift));
872
 
 
873
 
                for (shift -= 6; shift >= 0; shift -= 6)
874
 
                  write_char (0x80 | (0x3f & (code >> shift)));
875
 
              }
876
 
              break;
877
 
 
878
 
            case 's':
879
 
              p = va_arg (args, char *);
880
 
              if (p)
881
 
                {
882
 
                  grub_size_t len = 0;
883
 
                  while (len < format2 && p[len])
884
 
                    len++;
885
 
 
886
 
                  if (!rightfill && len < format1)
887
 
                    write_fill (zerofill, format1 - len);
888
 
 
889
 
                  grub_size_t i;
890
 
                  for (i = 0; i < len; i++)
891
 
                    write_char (*p++);
892
 
 
893
 
                  if (rightfill && len < format1)
894
 
                    write_fill (zerofill, format1 - len);
895
 
                }
896
 
              else
897
 
                write_str ("(null)");
898
 
 
899
 
              break;
900
 
 
901
 
            default:
902
 
              write_char (c);
903
 
              break;
904
 
            }
905
 
        }
906
 
    }
907
 
 
908
 
  *str = '\0';
909
 
 
910
 
  return count;
911
 
}
912
 
 
913
 
int
914
 
grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list ap)
915
 
{
916
 
  grub_size_t ret;
917
 
 
918
 
  if (!n)
919
 
    return 0;
920
 
 
921
 
  n--;
922
 
 
923
 
  ret = grub_vsnprintf_real (str, n, fmt, ap);
924
 
 
925
 
  return ret < n ? ret : n;
926
 
}
927
 
 
928
 
int
929
 
grub_snprintf (char *str, grub_size_t n, const char *fmt, ...)
930
 
{
931
 
  va_list ap;
932
 
  int ret;
933
 
 
934
 
  va_start (ap, fmt);
935
 
  ret = grub_vsnprintf (str, n, fmt, ap);
936
 
  va_end (ap);
937
 
 
938
 
  return ret;
939
 
}
940
 
 
941
 
char *
942
 
grub_xvasprintf (const char *fmt, va_list ap)
943
 
{
944
 
  grub_size_t s, as = PREALLOC_SIZE;
945
 
  char *ret;
946
 
 
947
 
  while (1)
948
 
    {
949
 
      ret = grub_malloc (as + 1);
950
 
      if (!ret)
951
 
        return NULL;
952
 
 
953
 
      s = grub_vsnprintf_real (ret, as, fmt, ap);
954
 
      if (s <= as)
955
 
        return ret;
956
 
 
957
 
      grub_free (ret);
958
 
      as = s;
959
 
    }
960
 
}
961
 
 
962
 
char *
963
 
grub_xasprintf (const char *fmt, ...)
964
 
{
965
 
  va_list ap;
966
 
  char *ret;
967
 
 
968
 
  va_start (ap, fmt);
969
 
  ret = grub_xvasprintf (fmt, ap);
970
 
  va_end (ap);
971
 
 
972
 
  return ret;
973
 
}
974
 
 
975
 
/* Abort GRUB. This function does not return.  */
976
 
void
977
 
grub_abort (void)
978
 
{
979
 
  grub_printf ("\nAborted.");
980
 
  
981
 
#ifndef GRUB_UTIL
982
 
  if (grub_term_inputs)
983
 
#endif
984
 
    {
985
 
      grub_printf (" Press any key to exit.");
986
 
      grub_getkey ();
987
 
    }
988
 
 
989
 
  grub_exit ();
990
 
}
991
 
 
992
 
#ifndef APPLE_CC
993
 
/* GCC emits references to abort().  */
994
 
void abort (void) __attribute__ ((alias ("grub_abort")));
995
 
#endif
996
 
 
997
 
#if defined(NEED_ENABLE_EXECUTE_STACK) && !defined(GRUB_UTIL) && !defined(GRUB_MACHINE_EMU)
998
 
/* Some gcc versions generate a call to this function
999
 
   in trampolines for nested functions.  */
1000
 
void __enable_execute_stack (void *addr __attribute__ ((unused)))
1001
 
{
1002
 
}
1003
 
#endif
1004
 
 
1005
 
#if defined (NEED_REGISTER_FRAME_INFO) && !defined(GRUB_UTIL)
1006
 
void __register_frame_info (void)
1007
 
{
1008
 
}
1009
 
 
1010
 
void __deregister_frame_info (void)
1011
 
{
1012
 
}
1013
 
#endif
1014