1 /* misc.c - definitions of misc functions */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
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.
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.
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/>.
20 #include <grub/misc.h>
24 #include <grub/term.h>
26 #include <grub/i18n.h>
30 /* Yes, type is also part of union as the moment we fill the value
31 we don't need to store its type anymore (when we'll need it, we'll
32 have format spec again. So save some space. */
36 UNSIGNED_INT
= 3, UNSIGNED_LONG
, UNSIGNED_LONGLONG
43 union printf_arg prealloc
[32];
44 union printf_arg
*ptr
;
49 parse_printf_args (const char *fmt0
, struct printf_args
*args
,
52 grub_vsnprintf_real (char *str
, grub_size_t max_len
, const char *fmt0
,
53 struct printf_args
*args
);
56 free_printf_args (struct printf_args
*args
)
58 if (args
->ptr
!= args
->prealloc
)
59 grub_free (args
->ptr
);
63 grub_iswordseparator (int c
)
65 return (grub_isspace (c
) || c
== ',' || c
== ';' || c
== '|' || c
== '&');
68 /* grub_gettext_dummy is not translating anything. */
70 grub_gettext_dummy (const char *s
)
75 const char* (*grub_gettext
) (const char *s
) = grub_gettext_dummy
;
78 grub_memmove (void *dest
, const void *src
, grub_size_t n
)
80 char *d
= (char *) dest
;
81 const char *s
= (const char *) src
;
99 void *memmove (void *dest
, const void *src
, grub_size_t n
)
100 __attribute__ ((alias ("grub_memmove")));
101 /* GCC emits references to memcpy() for struct copies etc. */
102 void *memcpy (void *dest
, const void *src
, grub_size_t n
)
103 __attribute__ ((alias ("grub_memmove")));
105 void * GRUB_BUILTIN_ATTR
106 memcpy (void *dest
, const void *src
, grub_size_t n
)
108 return grub_memmove (dest
, src
, n
);
110 void * GRUB_BUILTIN_ATTR
111 memmove (void *dest
, const void *src
, grub_size_t n
)
113 return grub_memmove (dest
, src
, n
);
118 grub_strcpy (char *dest
, const char *src
)
122 while ((*p
++ = *src
++) != '\0')
129 grub_printf (const char *fmt
, ...)
135 ret
= grub_vprintf (fmt
, ap
);
142 grub_printf_ (const char *fmt
, ...)
148 ret
= grub_vprintf (_(fmt
), ap
);
155 grub_puts_ (const char *s
)
157 return grub_puts (_(s
));
160 #if defined (__APPLE__) && ! defined (GRUB_UTIL)
162 grub_err_printf (const char *fmt
, ...)
168 ret
= grub_vprintf (fmt
, ap
);
175 #if ! defined (__APPLE__) && ! defined (GRUB_UTIL)
176 int grub_err_printf (const char *fmt
, ...)
177 __attribute__ ((alias("grub_printf")));
181 grub_real_dprintf (const char *file
, const int line
, const char *condition
,
182 const char *fmt
, ...)
185 const char *debug
= grub_env_get ("debug");
190 if (grub_strword (debug
, "all") || grub_strword (debug
, condition
))
192 grub_printf ("%s:%d: ", file
, line
);
193 va_start (args
, fmt
);
194 grub_vprintf (fmt
, args
);
200 #define PREALLOC_SIZE 255
203 grub_vprintf (const char *fmt
, va_list ap
)
206 static char buf
[PREALLOC_SIZE
+ 1];
208 struct printf_args args
;
210 parse_printf_args (fmt
, &args
, ap
);
212 s
= grub_vsnprintf_real (buf
, PREALLOC_SIZE
, fmt
, &args
);
213 if (s
> PREALLOC_SIZE
)
215 curbuf
= grub_malloc (s
+ 1);
218 grub_errno
= GRUB_ERR_NONE
;
219 buf
[PREALLOC_SIZE
- 3] = '.';
220 buf
[PREALLOC_SIZE
- 2] = '.';
221 buf
[PREALLOC_SIZE
- 1] = '.';
222 buf
[PREALLOC_SIZE
] = 0;
226 s
= grub_vsnprintf_real (curbuf
, s
, fmt
, &args
);
229 free_printf_args (&args
);
240 grub_memcmp (const void *s1
, const void *s2
, grub_size_t n
)
242 const grub_uint8_t
*t1
= s1
;
243 const grub_uint8_t
*t2
= s2
;
248 return (int) *t1
- (int) *t2
;
257 int memcmp (const void *s1
, const void *s2
, grub_size_t n
)
258 __attribute__ ((alias ("grub_memcmp")));
260 int GRUB_BUILTIN_ATTR
261 memcmp (const void *s1
, const void *s2
, grub_size_t n
)
263 return grub_memcmp (s1
, s2
, n
);
268 grub_strcmp (const char *s1
, const char *s2
)
279 return (int) (grub_uint8_t
) *s1
- (int) (grub_uint8_t
) *s2
;
283 grub_strncmp (const char *s1
, const char *s2
, grub_size_t n
)
288 while (*s1
&& *s2
&& --n
)
297 return (int) (grub_uint8_t
) *s1
- (int) (grub_uint8_t
) *s2
;
301 grub_strchr (const char *s
, int c
)
314 grub_strrchr (const char *s
, int c
)
329 grub_strword (const char *haystack
, const char *needle
)
331 const char *n_pos
= needle
;
333 while (grub_iswordseparator (*haystack
))
338 /* Crawl both the needle and the haystack word we're on. */
339 while(*haystack
&& !grub_iswordseparator (*haystack
)
340 && *haystack
== *n_pos
)
346 /* If we reached the end of both words at the same time, the word
347 is found. If not, eat everything in the haystack that isn't the
348 next word (or the end of string) and "reset" the needle. */
349 if ( (!*haystack
|| grub_iswordseparator (*haystack
))
350 && (!*n_pos
|| grub_iswordseparator (*n_pos
)))
355 while (*haystack
&& !grub_iswordseparator (*haystack
))
357 while (grub_iswordseparator (*haystack
))
368 return (c
== '\n' || c
== '\r' || c
== ' ' || c
== '\t');
372 grub_strtoul (const char *str
, char **end
, int base
)
374 unsigned long long num
;
376 num
= grub_strtoull (str
, end
, base
);
377 #if GRUB_CPU_SIZEOF_LONG != 8
380 grub_error (GRUB_ERR_OUT_OF_RANGE
, N_("overflow is detected"));
385 return (unsigned long) num
;
389 grub_strtoull (const char *str
, char **end
, int base
)
391 unsigned long long num
= 0;
394 /* Skip white spaces. */
395 /* grub_isspace checks that *str != '\0'. */
396 while (grub_isspace (*str
))
399 /* Guess the base, if not specified. The prefix `0x' means 16, and
400 the prefix `0' means 8. */
405 if (base
== 0 || base
== 16)
411 else if (base
== 0 && str
[1] >= '0' && str
[1] <= '7')
422 digit
= grub_tolower (*str
) - '0';
425 digit
+= '0' - 'a' + 10;
426 if (digit
>= (unsigned long) base
)
432 /* NUM * BASE + DIGIT > ~0ULL */
433 if (num
> grub_divmod64 (~0ULL - digit
, base
, 0))
435 grub_error (GRUB_ERR_OUT_OF_RANGE
,
436 N_("overflow is detected"));
440 num
= num
* base
+ digit
;
446 grub_error (GRUB_ERR_BAD_NUMBER
,
447 N_("unrecognized number"));
458 grub_strdup (const char *s
)
463 len
= grub_strlen (s
) + 1;
464 p
= (char *) grub_malloc (len
);
468 return grub_memcpy (p
, s
, len
);
472 grub_strndup (const char *s
, grub_size_t n
)
477 len
= grub_strlen (s
);
480 p
= (char *) grub_malloc (len
+ 1);
484 grub_memcpy (p
, s
, len
);
489 /* clang detects that we're implementing here a memset so it decides to
490 optimise and calls memset resulting in infinite recursion. With volatile
491 we make it not optimise in this way. */
493 #define VOLATILE_CLANG volatile
495 #define VOLATILE_CLANG
499 grub_memset (void *s
, int c
, grub_size_t len
)
502 grub_uint8_t pattern8
= c
;
504 if (len
>= 3 * sizeof (unsigned long))
506 unsigned long patternl
= 0;
509 for (i
= 0; i
< sizeof (unsigned long); i
++)
510 patternl
|= ((unsigned long) pattern8
) << (8 * i
);
512 while (len
> 0 && (((grub_addr_t
) p
) & (sizeof (unsigned long) - 1)))
514 *(VOLATILE_CLANG grub_uint8_t
*) p
= pattern8
;
515 p
= (grub_uint8_t
*) p
+ 1;
518 while (len
>= sizeof (unsigned long))
520 *(VOLATILE_CLANG
unsigned long *) p
= patternl
;
521 p
= (unsigned long *) p
+ 1;
522 len
-= sizeof (unsigned long);
528 *(VOLATILE_CLANG grub_uint8_t
*) p
= pattern8
;
529 p
= (grub_uint8_t
*) p
+ 1;
536 void *memset (void *s
, int c
, grub_size_t n
)
537 __attribute__ ((alias ("grub_memset")));
539 void * GRUB_BUILTIN_ATTR
540 memset (void *s
, int c
, grub_size_t n
)
542 return grub_memset (s
, c
, n
);
547 #if !defined(GRUB_UTIL) && defined(__APPLE__)
548 void GRUB_BUILTIN_ATTR
549 __bzero (void *s
, grub_size_t n
)
551 grub_memset (s
, 0, n
);
557 grub_strlen (const char *s
)
568 grub_reverse (char *str
)
570 char *p
= str
+ grub_strlen (str
) - 1;
584 /* Divide N by D, return the quotient, and store the remainder in *R. */
586 grub_divmod64 (grub_uint64_t n
, grub_uint64_t d
, grub_uint64_t
*r
)
588 /* This algorithm is typically implemented by hardware. The idea
589 is to get the highest bit in N, 64 times, by keeping
590 upper(N * 2^i) = (Q * D + M), where upper
591 represents the high 64 bits in 128-bits space. */
596 /* ARM and IA64 don't have a fast 32-bit division.
597 Using that code would just make us use libgcc routines, calling
598 them twice (once for modulo and once for quotient.
600 #if !defined (__arm__) && !defined (__ia64__)
601 /* Skip the slow computation if 32-bit arithmetic is possible. */
602 if (n
< 0xffffffff && d
< 0xffffffff)
605 *r
= ((grub_uint32_t
) n
) % (grub_uint32_t
) d
;
607 return ((grub_uint32_t
) n
) / (grub_uint32_t
) d
;
615 if (n
& (1ULL << 63))
634 #if !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU)
636 #if defined (__arm__)
639 __udivsi3 (grub_uint32_t a
, grub_uint32_t b
)
641 return grub_divmod64 (a
, b
, 0);
645 __umodsi3 (grub_uint32_t a
, grub_uint32_t b
)
648 grub_divmod64 (a
, b
, &ret
);
657 __ctzdi2 (grub_uint64_t x
)
662 if (!(x
& 0xffffffff))
698 __ctzsi2 (grub_uint32_t x
)
736 __aeabi_uidiv (grub_uint32_t a
, grub_uint32_t b
)
737 __attribute__ ((alias ("__udivsi3")));
740 #if defined (__ia64__)
743 __udivdi3 (grub_uint64_t a
, grub_uint64_t b
)
745 return grub_divmod64 (a
, b
, 0);
749 __umoddi3 (grub_uint64_t a
, grub_uint64_t b
)
752 grub_divmod64 (a
, b
, &ret
);
758 #endif /* GRUB_UTIL */
760 /* Convert a long long value to a string. This function avoids 64-bit
761 modular arithmetic or divisions. */
763 grub_lltoa (char *str
, int c
, unsigned long long n
)
765 unsigned base
= (c
== 'x') ? 16 : 10;
768 if ((long long) n
< 0 && c
== 'd')
770 n
= (unsigned long long) (-((long long) n
));
779 unsigned d
= (unsigned) (n
& 0xf);
780 *p
++ = (d
> 9) ? d
+ 'a' - 10 : d
+ '0';
789 n
= grub_divmod64 (n
, 10, &m
);
801 parse_printf_args (const char *fmt0
, struct printf_args
*args
,
810 COMPILE_TIME_ASSERT (sizeof (int) == sizeof (grub_uint32_t
));
811 COMPILE_TIME_ASSERT (sizeof (int) <= sizeof (long long));
812 COMPILE_TIME_ASSERT (sizeof (long) <= sizeof (long long));
813 COMPILE_TIME_ASSERT (sizeof (long long) == sizeof (void *)
814 || sizeof (int) == sizeof (void *));
817 while ((c
= *fmt
++) != 0)
825 while (grub_isdigit (*fmt
))
834 while (grub_isdigit (*fmt
))
840 while (grub_isdigit (*fmt
))
863 if (args
->count
<= ARRAY_SIZE (args
->prealloc
))
864 args
->ptr
= args
->prealloc
;
867 args
->ptr
= grub_malloc (args
->count
* sizeof (args
->ptr
[0]));
870 grub_errno
= GRUB_ERR_NONE
;
871 args
->ptr
= args
->prealloc
;
872 args
->count
= ARRAY_SIZE (args
->prealloc
);
876 grub_memset (args
->ptr
, 0, args
->count
* sizeof (args
->ptr
[0]));
880 while ((c
= *fmt
++) != 0)
896 while (grub_isdigit (*fmt
))
901 curn
= grub_strtoull (p
, 0, 10) - 1;
908 while (grub_isdigit (*fmt
))
914 while (grub_isdigit (*fmt
))
928 if (curn
>= args
->count
)
934 args
->ptr
[curn
].type
= UNSIGNED_INT
+ longfmt
;
937 args
->ptr
[curn
].type
= INT
+ longfmt
;
941 if (sizeof (void *) == sizeof (long long))
942 args
->ptr
[curn
].type
= UNSIGNED_LONGLONG
;
944 args
->ptr
[curn
].type
= UNSIGNED_INT
;
948 args
->ptr
[curn
].type
= INT
;
953 for (n
= 0; n
< args
->count
; n
++)
954 switch (args
->ptr
[n
].type
)
957 args
->ptr
[n
].ll
= va_arg (args_in
, int);
960 args
->ptr
[n
].ll
= va_arg (args_in
, long);
963 args
->ptr
[n
].ll
= va_arg (args_in
, unsigned int);
966 args
->ptr
[n
].ll
= va_arg (args_in
, unsigned long);
969 case UNSIGNED_LONGLONG
:
970 args
->ptr
[n
].ll
= va_arg (args_in
, long long);
975 static inline void __attribute__ ((always_inline
))
976 write_char (char *str
, grub_size_t
*count
, grub_size_t max_len
, unsigned char ch
)
978 if (*count
< max_len
)
985 grub_vsnprintf_real (char *str
, grub_size_t max_len
, const char *fmt0
,
986 struct printf_args
*args
)
990 grub_size_t count
= 0;
995 while ((c
= *fmt
++) != 0)
997 unsigned int format1
= 0;
998 unsigned int format2
= ~ 0U;
1005 write_char (str
, &count
, max_len
,c
);
1019 /* Read formatting parameters. */
1020 if (grub_isdigit (*fmt
))
1024 format1
= grub_strtoul (fmt
, (char **) &fmt
, 10);
1030 if (grub_isdigit (*fmt
))
1031 format2
= grub_strtoul (fmt
, (char **) &fmt
, 10);
1053 write_char (str
, &count
, max_len
,c
);
1057 if (curn
>= args
->count
)
1060 long long curarg
= args
->ptr
[curn
].ll
;
1065 write_char (str
, &count
, max_len
, '0');
1066 write_char (str
, &count
, max_len
, 'x');
1074 const char *p
= tmp
;
1078 len
= grub_lltoa (tmp
, c
, curarg
) - tmp
;
1079 fill
= len
< format1
? format1
- len
: 0;
1082 write_char (str
, &count
, max_len
, zerofill
);
1084 write_char (str
, &count
, max_len
, *p
++);
1087 write_char (str
, &count
, max_len
, zerofill
);
1092 write_char (str
, &count
, max_len
,curarg
& 0xff);
1097 grub_uint32_t code
= curarg
;
1106 else if (code
<= 0x7ff)
1111 else if (code
<= 0xffff)
1116 else if (code
<= 0x10ffff)
1128 write_char (str
, &count
, max_len
,mask
| (code
>> shift
));
1130 for (shift
-= 6; shift
>= 0; shift
-= 6)
1131 write_char (str
, &count
, max_len
,0x80 | (0x3f & (code
>> shift
)));
1137 grub_size_t len
= 0;
1139 const char *p
= ((char *) (grub_addr_t
) curarg
) ? : "(null)";
1142 while (len
< format2
&& p
[len
])
1145 fill
= len
< format1
? format1
- len
: 0;
1149 write_char (str
, &count
, max_len
, zerofill
);
1151 for (i
= 0; i
< len
; i
++)
1152 write_char (str
, &count
, max_len
,*p
++);
1156 write_char (str
, &count
, max_len
, zerofill
);
1162 write_char (str
, &count
, max_len
,c
);
1167 if (count
< max_len
)
1170 str
[max_len
] = '\0';
1175 grub_vsnprintf (char *str
, grub_size_t n
, const char *fmt
, va_list ap
)
1178 struct printf_args args
;
1185 parse_printf_args (fmt
, &args
, ap
);
1187 ret
= grub_vsnprintf_real (str
, n
, fmt
, &args
);
1189 free_printf_args (&args
);
1191 return ret
< n
? ret
: n
;
1195 grub_snprintf (char *str
, grub_size_t n
, const char *fmt
, ...)
1201 ret
= grub_vsnprintf (str
, n
, fmt
, ap
);
1208 grub_xvasprintf (const char *fmt
, va_list ap
)
1210 grub_size_t s
, as
= PREALLOC_SIZE
;
1212 struct printf_args args
;
1214 parse_printf_args (fmt
, &args
, ap
);
1218 ret
= grub_malloc (as
+ 1);
1221 free_printf_args (&args
);
1225 s
= grub_vsnprintf_real (ret
, as
, fmt
, &args
);
1229 free_printf_args (&args
);
1239 grub_xasprintf (const char *fmt
, ...)
1245 ret
= grub_xvasprintf (fmt
, ap
);
1251 /* Abort GRUB. This function does not return. */
1252 static void __attribute__ ((noreturn
))
1255 grub_printf ("\nAborted.");
1258 if (grub_term_inputs
)
1261 grub_printf (" Press any key to exit.");
1268 #if defined (__clang__) && !defined (GRUB_UTIL)
1269 /* clang emits references to abort(). */
1270 void __attribute__ ((noreturn
))
1278 grub_fatal (const char *fmt
, ...)
1283 grub_vprintf (_(fmt
), ap
);
1289 #if (defined (__MINGW32__) || defined (__CYGWIN__)) && !defined(GRUB_UTIL)
1290 void __register_frame_info (void)
1294 void __deregister_frame_info (void)
1297 void ___chkstk_ms (void)
1301 void __chkstk_ms (void)
1308 #include <grub/time.h>
1310 struct grub_boot_time
*grub_boot_time_head
;
1311 static struct grub_boot_time
**boot_time_last
= &grub_boot_time_head
;
1314 grub_real_boot_time (const char *file
,
1316 const char *fmt
, ...)
1318 struct grub_boot_time
*n
;
1322 n
= grub_malloc (sizeof (*n
));
1331 n
->tp
= grub_get_time_ms ();
1334 va_start (args
, fmt
);
1335 n
->msg
= grub_xvasprintf (fmt
, args
);
1338 *boot_time_last
= n
;
1339 boot_time_last
= &n
->next
;