aboutsummaryrefslogtreecommitdiff
path: root/stage2/char_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'stage2/char_io.c')
-rw-r--r--stage2/char_io.c1283
1 files changed, 0 insertions, 1283 deletions
diff --git a/stage2/char_io.c b/stage2/char_io.c
deleted file mode 100644
index c86c240..0000000
--- a/stage2/char_io.c
+++ /dev/null
@@ -1,1283 +0,0 @@
-/* char_io.c - basic console input and output */
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <shared.h>
-#include <term.h>
-
-#ifdef SUPPORT_HERCULES
-# include <hercules.h>
-#endif
-
-#ifdef SUPPORT_SERIAL
-# include <serial.h>
-#endif
-
-#ifndef STAGE1_5
-struct term_entry term_table[] =
- {
- {
- "console",
- 0,
- console_putchar,
- console_checkkey,
- console_getkey,
- console_getxy,
- console_gotoxy,
- console_cls,
- console_setcolorstate,
- console_setcolor,
- console_setcursor
- },
-#ifdef SUPPORT_SERIAL
- {
- "serial",
- /* A serial device must be initialized. */
- TERM_NEED_INIT,
- serial_putchar,
- serial_checkkey,
- serial_getkey,
- serial_getxy,
- serial_gotoxy,
- serial_cls,
- serial_setcolorstate,
- 0,
- 0
- },
-#endif /* SUPPORT_SERIAL */
-#ifdef SUPPORT_HERCULES
- {
- "hercules",
- 0,
- hercules_putchar,
- console_checkkey,
- console_getkey,
- hercules_getxy,
- hercules_gotoxy,
- hercules_cls,
- hercules_setcolorstate,
- hercules_setcolor,
- hercules_setcursor
- },
-#endif /* SUPPORT_HERCULES */
- /* This must be the last entry. */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
- };
-
-/* This must be console. */
-struct term_entry *current_term = term_table;
-
-int max_lines = 24;
-int count_lines = -1;
-int use_pager = 1;
-#endif
-
-void
-print_error (void)
-{
- if (errnum > ERR_NONE && errnum < MAX_ERR_NUM)
-#ifndef STAGE1_5
- /* printf("\7\n %s\n", err_list[errnum]); */
- printf ("\nError %u: %s\n", errnum, err_list[errnum]);
-#else /* STAGE1_5 */
- printf ("Error %u\n", errnum);
-#endif /* STAGE1_5 */
-}
-
-char *
-convert_to_ascii (char *buf, int c,...)
-{
- unsigned long num = *((&c) + 1), mult = 10;
- char *ptr = buf;
-
-#ifndef STAGE1_5
- if (c == 'x' || c == 'X')
- mult = 16;
-
- if ((num & 0x80000000uL) && c == 'd')
- {
- num = (~num) + 1;
- *(ptr++) = '-';
- buf++;
- }
-#endif
-
- do
- {
- int dig = num % mult;
- *(ptr++) = ((dig > 9) ? dig + 'a' - 10 : '0' + dig);
- }
- while (num /= mult);
-
- /* reorder to correct direction!! */
- {
- char *ptr1 = ptr - 1;
- char *ptr2 = buf;
- while (ptr1 > ptr2)
- {
- int tmp = *ptr1;
- *ptr1 = *ptr2;
- *ptr2 = tmp;
- ptr1--;
- ptr2++;
- }
- }
-
- return ptr;
-}
-
-void
-grub_putstr (const char *str)
-{
- while (*str)
- grub_putchar (*str++);
-}
-
-void
-grub_printf (const char *format,...)
-{
- int *dataptr = (int *) &format;
- char c, str[16];
-
- dataptr++;
-
- while ((c = *(format++)) != 0)
- {
- if (c != '%')
- grub_putchar (c);
- else
- switch (c = *(format++))
- {
-#ifndef STAGE1_5
- case 'd':
- case 'x':
- case 'X':
-#endif
- case 'u':
- *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
- grub_putstr (str);
- break;
-
-#ifndef STAGE1_5
- case 'c':
- grub_putchar ((*(dataptr++)) & 0xff);
- break;
-
- case 's':
- grub_putstr ((char *) *(dataptr++));
- break;
-#endif
- }
- }
-}
-
-#ifndef STAGE1_5
-int
-grub_sprintf (char *buffer, const char *format, ...)
-{
- /* XXX hohmuth
- ugly hack -- should unify with printf() */
- int *dataptr = (int *) &format;
- char c, *ptr, str[16];
- char *bp = buffer;
-
- dataptr++;
-
- while ((c = *format++) != 0)
- {
- if (c != '%')
- *bp++ = c; /* putchar(c); */
- else
- switch (c = *(format++))
- {
- case 'd': case 'u': case 'x':
- *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
-
- ptr = str;
-
- while (*ptr)
- *bp++ = *(ptr++); /* putchar(*(ptr++)); */
- break;
-
- case 'c': *bp++ = (*(dataptr++))&0xff;
- /* putchar((*(dataptr++))&0xff); */
- break;
-
- case 's':
- ptr = (char *) (*(dataptr++));
-
- while ((c = *ptr++) != 0)
- *bp++ = c; /* putchar(c); */
- break;
- }
- }
-
- *bp = 0;
- return bp - buffer;
-}
-
-
-void
-init_page (void)
-{
- cls ();
-
- grub_printf ("\n GNU GRUB version %s (%dK lower / %dK upper memory)\n\n",
- version_string, mbi.mem_lower, mbi.mem_upper);
-}
-
-/* The number of the history entries. */
-static int num_history = 0;
-
-/* Get the NOth history. If NO is less than zero or greater than or
- equal to NUM_HISTORY, return NULL. Otherwise return a valid string. */
-static char *
-get_history (int no)
-{
- if (no < 0 || no >= num_history)
- return 0;
-
- return (char *) HISTORY_BUF + MAX_CMDLINE * no;
-}
-
-/* Add CMDLINE to the history buffer. */
-static void
-add_history (const char *cmdline, int no)
-{
- grub_memmove ((char *) HISTORY_BUF + MAX_CMDLINE * (no + 1),
- (char *) HISTORY_BUF + MAX_CMDLINE * no,
- MAX_CMDLINE * (num_history - no));
- grub_strcpy ((char *) HISTORY_BUF + MAX_CMDLINE * no, cmdline);
- if (num_history < HISTORY_SIZE)
- num_history++;
-}
-
-static int
-real_get_cmdline (char *prompt, char *cmdline, int maxlen,
- int echo_char, int readline)
-{
- /* This is a rather complicated function. So explain the concept.
-
- A command-line consists of ``section''s. A section is a part of the
- line which may be displayed on the screen, but a section is never
- displayed with another section simultaneously.
-
- Each section is basically 77 or less characters, but the exception
- is the first section, which is 78 or less characters, because the
- starting point is special. See below.
-
- The first section contains a prompt and a command-line (or the
- first part of a command-line when it is too long to be fit in the
- screen). So, in the first section, the number of command-line
- characters displayed is 78 minus the length of the prompt (or
- less). If the command-line has more characters, `>' is put at the
- position 78 (zero-origin), to inform the user of the hidden
- characters.
-
- Other sections always have `<' at the first position, since there
- is absolutely a section before each section. If there is a section
- after another section, this section consists of 77 characters and
- `>' at the last position. The last section has 77 or less
- characters and doesn't have `>'.
-
- Each section other than the last shares some characters with the
- previous section. This region is called ``margin''. If the cursor
- is put at the magin which is shared by the first section and the
- second, the first section is displayed. Otherwise, a displayed
- section is switched to another section, only if the cursor is put
- outside that section. */
-
- /* XXX: These should be defined in shared.h, but I leave these here,
- until this code is freezed. */
-#define CMDLINE_WIDTH 78
-#define CMDLINE_MARGIN 10
-
- int xpos, lpos, c, section;
- /* The length of PROMPT. */
- int plen;
- /* The length of the command-line. */
- int llen;
- /* The index for the history. */
- int history = -1;
- /* The working buffer for the command-line. */
- char *buf = (char *) CMDLINE_BUF;
- /* The kill buffer. */
- char *kill_buf = (char *) KILL_BUF;
-
- /* Nested function definitions for code simplicity. */
-
- /* The forward declarations of nested functions are prefixed
- with `auto'. */
- auto void cl_refresh (int full, int len);
- auto void cl_backward (int count);
- auto void cl_forward (int count);
- auto void cl_insert (const char *str);
- auto void cl_delete (int count);
- auto void cl_init (void);
-
- /* Move the cursor backward. */
- void cl_backward (int count)
- {
- lpos -= count;
-
- /* If the cursor is in the first section, display the first section
- instead of the second. */
- if (section == 1 && plen + lpos < CMDLINE_WIDTH)
- cl_refresh (1, 0);
- else if (xpos - count < 1)
- cl_refresh (1, 0);
- else
- {
- xpos -= count;
-
- if (current_term->flags & TERM_DUMB)
- {
- int i;
-
- for (i = 0; i < count; i++)
- grub_putchar ('\b');
- }
- else
- gotoxy (xpos, getxy () & 0xFF);
- }
- }
-
- /* Move the cursor forward. */
- void cl_forward (int count)
- {
- lpos += count;
-
- /* If the cursor goes outside, scroll the screen to the right. */
- if (xpos + count >= CMDLINE_WIDTH)
- cl_refresh (1, 0);
- else
- {
- xpos += count;
-
- if (current_term->flags & TERM_DUMB)
- {
- int i;
-
- for (i = lpos - count; i < lpos; i++)
- {
- if (! echo_char)
- grub_putchar (buf[i]);
- else
- grub_putchar (echo_char);
- }
- }
- else
- gotoxy (xpos, getxy () & 0xFF);
- }
- }
-
- /* Refresh the screen. If FULL is true, redraw the full line, otherwise,
- only LEN characters from LPOS. */
- void cl_refresh (int full, int len)
- {
- int i;
- int start;
- int pos = xpos;
-
- if (full)
- {
- /* Recompute the section number. */
- if (lpos + plen < CMDLINE_WIDTH)
- section = 0;
- else
- section = ((lpos + plen - CMDLINE_WIDTH)
- / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1);
-
- /* From the start to the end. */
- len = CMDLINE_WIDTH;
- pos = 0;
- grub_putchar ('\r');
-
- /* If SECTION is the first section, print the prompt, otherwise,
- print `<'. */
- if (section == 0)
- {
- grub_printf ("%s", prompt);
- len -= plen;
- pos += plen;
- }
- else
- {
- grub_putchar ('<');
- len--;
- pos++;
- }
- }
-
- /* Compute the index to start writing BUF and the resulting position
- on the screen. */
- if (section == 0)
- {
- int offset = 0;
-
- if (! full)
- offset = xpos - plen;
-
- start = 0;
- xpos = lpos + plen;
- start += offset;
- }
- else
- {
- int offset = 0;
-
- if (! full)
- offset = xpos - 1;
-
- start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN)
- + CMDLINE_WIDTH - plen - CMDLINE_MARGIN);
- xpos = lpos + 1 - start;
- start += offset;
- }
-
- /* Print BUF. If ECHO_CHAR is not zero, put it instead. */
- for (i = start; i < start + len && i < llen; i++)
- {
- if (! echo_char)
- grub_putchar (buf[i]);
- else
- grub_putchar (echo_char);
-
- pos++;
- }
-
- /* Fill up the rest of the line with spaces. */
- for (; i < start + len; i++)
- {
- grub_putchar (' ');
- pos++;
- }
-
- /* If the cursor is at the last position, put `>' or a space,
- depending on if there are more characters in BUF. */
- if (pos == CMDLINE_WIDTH)
- {
- if (start + len < llen)
- grub_putchar ('>');
- else
- grub_putchar (' ');
-
- pos++;
- }
-
- /* Back to XPOS. */
- if (current_term->flags & TERM_DUMB)
- {
- for (i = 0; i < pos - xpos; i++)
- grub_putchar ('\b');
- }
- else
- gotoxy (xpos, getxy () & 0xFF);
- }
-
- /* Initialize the command-line. */
- void cl_init (void)
- {
- /* Distinguish us from other lines and error messages! */
- grub_putchar ('\n');
-
- /* Print full line and set position here. */
- cl_refresh (1, 0);
- }
-
- /* Insert STR to BUF. */
- void cl_insert (const char *str)
- {
- int l = grub_strlen (str);
-
- if (llen + l < maxlen)
- {
- if (lpos == llen)
- grub_memmove (buf + lpos, str, l + 1);
- else
- {
- grub_memmove (buf + lpos + l, buf + lpos, llen - lpos + 1);
- grub_memmove (buf + lpos, str, l);
- }
-
- llen += l;
- lpos += l;
- if (xpos + l >= CMDLINE_WIDTH)
- cl_refresh (1, 0);
- else if (xpos + l + llen - lpos > CMDLINE_WIDTH)
- cl_refresh (0, CMDLINE_WIDTH - xpos);
- else
- cl_refresh (0, l + llen - lpos);
- }
- }
-
- /* Delete COUNT characters in BUF. */
- void cl_delete (int count)
- {
- grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1);
- llen -= count;
-
- if (xpos + llen + count - lpos > CMDLINE_WIDTH)
- cl_refresh (0, CMDLINE_WIDTH - xpos);
- else
- cl_refresh (0, llen + count - lpos);
- }
-
- plen = grub_strlen (prompt);
- llen = grub_strlen (cmdline);
-
- if (maxlen > MAX_CMDLINE)
- {
- maxlen = MAX_CMDLINE;
- if (llen >= MAX_CMDLINE)
- {
- llen = MAX_CMDLINE - 1;
- cmdline[MAX_CMDLINE] = 0;
- }
- }
- lpos = llen;
- grub_strcpy (buf, cmdline);
-
- cl_init ();
-
- while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
- {
- /* If READLINE is non-zero, handle readline-like key bindings. */
- if (readline)
- {
- switch (c)
- {
- case 9: /* TAB lists completions */
- {
- int i;
- /* POS points to the first space after a command. */
- int pos = 0;
- int ret;
- char *completion_buffer = (char *) COMPLETION_BUF;
- int equal_pos = -1;
- int is_filename;
-
- /* Find the first word. */
- while (buf[pos] == ' ')
- pos++;
- while (buf[pos] && buf[pos] != '=' && buf[pos] != ' ')
- pos++;
-
- is_filename = (lpos > pos);
-
- /* Find the position of the equal character after a
- command, and replace it with a space. */
- for (i = pos; buf[i] && buf[i] != ' '; i++)
- if (buf[i] == '=')
- {
- equal_pos = i;
- buf[i] = ' ';
- break;
- }
-
- /* Find the position of the first character in this
- word. */
- for (i = lpos; i > 0 && buf[i - 1] != ' '; i--)
- ;
-
- /* Invalidate the cache, because the user may exchange
- removable disks. */
- buf_drive = -1;
-
- /* Copy this word to COMPLETION_BUFFER and do the
- completion. */
- grub_memmove (completion_buffer, buf + i, lpos - i);
- completion_buffer[lpos - i] = 0;
- ret = print_completions (is_filename, 1);
- errnum = ERR_NONE;
-
- if (ret >= 0)
- {
- /* Found, so insert COMPLETION_BUFFER. */
- cl_insert (completion_buffer + lpos - i);
-
- if (ret > 0)
- {
- /* There are more than one candidates, so print
- the list. */
- grub_putchar ('\n');
- print_completions (is_filename, 0);
- errnum = ERR_NONE;
- }
- }
-
- /* Restore the command-line. */
- if (equal_pos >= 0)
- buf[equal_pos] = '=';
-
- if (ret)
- cl_init ();
- }
- break;
- case 1: /* C-a go to beginning of line */
- cl_backward (lpos);
- break;
- case 5: /* C-e go to end of line */
- cl_forward (llen - lpos);
- break;
- case 6: /* C-f forward one character */
- if (lpos < llen)
- cl_forward (1);
- break;
- case 2: /* C-b backward one character */
- if (lpos > 0)
- cl_backward (1);
- break;
- case 21: /* C-u kill to beginning of line */
- if (lpos == 0)
- break;
- /* Copy the string being deleted to KILL_BUF. */
- grub_memmove (kill_buf, buf, lpos);
- kill_buf[lpos] = 0;
- {
- /* XXX: Not very clever. */
-
- int count = lpos;
-
- cl_backward (lpos);
- cl_delete (count);
- }
- break;
- case 11: /* C-k kill to end of line */
- if (lpos == llen)
- break;
- /* Copy the string being deleted to KILL_BUF. */
- grub_memmove (kill_buf, buf + lpos, llen - lpos + 1);
- cl_delete (llen - lpos);
- break;
- case 25: /* C-y yank the kill buffer */
- cl_insert (kill_buf);
- break;
- case 16: /* C-p fetch the previous command */
- {
- char *p;
-
- if (history < 0)
- /* Save the working buffer. */
- grub_strcpy (cmdline, buf);
- else if (grub_strcmp (get_history (history), buf) != 0)
- /* If BUF is modified, add it into the history list. */
- add_history (buf, history);
-
- history++;
- p = get_history (history);
- if (! p)
- {
- history--;
- break;
- }
-
- grub_strcpy (buf, p);
- llen = grub_strlen (buf);
- lpos = llen;
- cl_refresh (1, 0);
- }
- break;
- case 14: /* C-n fetch the next command */
- {
- char *p;
-
- if (history < 0)
- {
- break;
- }
- else if (grub_strcmp (get_history (history), buf) != 0)
- /* If BUF is modified, add it into the history list. */
- add_history (buf, history);
-
- history--;
- p = get_history (history);
- if (! p)
- p = cmdline;
-
- grub_strcpy (buf, p);
- llen = grub_strlen (buf);
- lpos = llen;
- cl_refresh (1, 0);
- }
- break;
- }
- }
-
- /* ESC, C-d and C-h are always handled. Actually C-d is not
- functional if READLINE is zero, as the cursor cannot go
- backward, but that's ok. */
- switch (c)
- {
- case 27: /* ESC immediately return 1 */
- return 1;
- case 4: /* C-d delete character under cursor */
- if (lpos == llen)
- break;
- cl_delete (1);
- break;
- case 8: /* C-h backspace */
-# ifdef GRUB_UTIL
- case 127: /* also backspace */
-# endif
- if (lpos > 0)
- {
- cl_backward (1);
- cl_delete (1);
- }
- break;
- default: /* insert printable character into line */
- if (c >= ' ' && c <= '~')
- {
- char str[2];
-
- str[0] = c;
- str[1] = 0;
- cl_insert (str);
- }
- }
- }
-
- grub_putchar ('\n');
-
- /* If ECHO_CHAR is NUL, remove the leading spaces. */
- lpos = 0;
- if (! echo_char)
- while (buf[lpos] == ' ')
- lpos++;
-
- /* Copy the working buffer to CMDLINE. */
- grub_memmove (cmdline, buf + lpos, llen - lpos + 1);
-
- /* If the readline-like feature is turned on and CMDLINE is not
- empty, add it into the history list. */
- if (readline && lpos < llen)
- add_history (cmdline, 0);
-
- return 0;
-}
-
-/* Don't use this with a MAXLEN greater than 1600 or so! The problem
- is that GET_CMDLINE depends on the everything fitting on the screen
- at once. So, the whole screen is about 2000 characters, minus the
- PROMPT, and space for error and status lines, etc. MAXLEN must be
- at least 1, and PROMPT and CMDLINE must be valid strings (not NULL
- or zero-length).
-
- If ECHO_CHAR is nonzero, echo it instead of the typed character. */
-int
-get_cmdline (char *prompt, char *cmdline, int maxlen,
- int echo_char, int readline)
-{
- int old_cursor;
- int ret;
-
- old_cursor = setcursor (1);
-
- /* Because it is hard to deal with different conditions simultaneously,
- less functional cases are handled here. Assume that TERM_NO_ECHO
- implies TERM_NO_EDIT. */
- if (current_term->flags & (TERM_NO_ECHO | TERM_NO_EDIT))
- {
- char *p = cmdline;
- int c;
-
- /* Make sure that MAXLEN is not too large. */
- if (maxlen > MAX_CMDLINE)
- maxlen = MAX_CMDLINE;
-
- /* Print only the prompt. The contents of CMDLINE is simply discarded,
- even if it is not empty. */
- grub_printf ("%s", prompt);
-
- /* Gather characters until a newline is gotten. */
- while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
- {
- /* Return immediately if ESC is pressed. */
- if (c == 27)
- {
- setcursor (old_cursor);
- return 1;
- }
-
- /* Printable characters are added into CMDLINE. */
- if (c >= ' ' && c <= '~')
- {
- if (! (current_term->flags & TERM_NO_ECHO))
- grub_putchar (c);
-
- /* Preceding space characters must be ignored. */
- if (c != ' ' || p != cmdline)
- *p++ = c;
- }
- }
-
- *p = 0;
-
- if (! (current_term->flags & TERM_NO_ECHO))
- grub_putchar ('\n');
-
- setcursor (old_cursor);
- return 0;
- }
-
- /* Complicated features are left to real_get_cmdline. */
- ret = real_get_cmdline (prompt, cmdline, maxlen, echo_char, readline);
- setcursor (old_cursor);
- return ret;
-}
-
-int
-safe_parse_maxint (char **str_ptr, int *myint_ptr)
-{
- char *ptr = *str_ptr;
- int myint = 0;
- int mult = 10, found = 0;
-
- /*
- * Is this a hex number?
- */
- if (*ptr == '0' && tolower (*(ptr + 1)) == 'x')
- {
- ptr += 2;
- mult = 16;
- }
-
- while (1)
- {
- /* A bit tricky. This below makes use of the equivalence:
- (A >= B && A <= C) <=> ((A - B) <= (C - B))
- when C > B and A is unsigned. */
- unsigned int digit;
-
- digit = tolower (*ptr) - '0';
- if (digit > 9)
- {
- digit -= 'a' - '0';
- if (mult == 10 || digit > 5)
- break;
- digit += 10;
- }
-
- found = 1;
- if (myint > ((MAXINT - digit) / mult))
- {
- errnum = ERR_NUMBER_OVERFLOW;
- return 0;
- }
- myint = (myint * mult) + digit;
- ptr++;
- }
-
- if (!found)
- {
- errnum = ERR_NUMBER_PARSING;
- return 0;
- }
-
- *str_ptr = ptr;
- *myint_ptr = myint;
-
- return 1;
-}
-#endif /* STAGE1_5 */
-
-#if !defined(STAGE1_5) || defined(FSYS_FAT)
-int
-grub_tolower (int c)
-{
- if (c >= 'A' && c <= 'Z')
- return (c + ('a' - 'A'));
-
- return c;
-}
-#endif /* ! STAGE1_5 || FSYS_FAT */
-
-int
-grub_isspace (int c)
-{
- switch (c)
- {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- return 1;
- default:
- break;
- }
-
- return 0;
-}
-
-#if !defined(STAGE1_5) || defined(FSYS_ISO9660)
-int
-grub_memcmp (const char *s1, const char *s2, int n)
-{
- while (n)
- {
- if (*s1 < *s2)
- return -1;
- else if (*s1 > *s2)
- return 1;
- s1++;
- s2++;
- n--;
- }
-
- return 0;
-}
-#endif /* ! STAGE1_5 || FSYS_ISO9660 */
-
-#ifndef STAGE1_5
-int
-grub_strncat (char *s1, const char *s2, int n)
-{
- int i = -1;
-
- while (++i < n && s1[i] != 0);
-
- while (i < n && (s1[i++] = *(s2++)) != 0);
-
- s1[n - 1] = 0;
-
- if (i >= n)
- return 0;
-
- s1[i] = 0;
-
- return 1;
-}
-#endif /* ! STAGE1_5 */
-
-/* XXX: This below is an evil hack. Certainly, we should change the
- strategy to determine what should be defined and what shouldn't be
- defined for each image. For example, it would be better to create
- a static library supporting minimal standard C functions and link
- each image with the library. Complicated things should be left to
- computer, definitely. -okuji */
-#if !defined(STAGE1_5) || defined(FSYS_VSTAFS)
-int
-grub_strcmp (const char *s1, const char *s2)
-{
- while (*s1 || *s2)
- {
- if (*s1 < *s2)
- return -1;
- else if (*s1 > *s2)
- return 1;
- s1 ++;
- s2 ++;
- }
-
- return 0;
-}
-#endif /* ! STAGE1_5 || FSYS_VSTAFS */
-
-#ifndef STAGE1_5
-/* Wait for a keypress and return its code. */
-int
-getkey (void)
-{
- return current_term->getkey ();
-}
-
-/* Check if a key code is available. */
-int
-checkkey (void)
-{
- return current_term->checkkey ();
-}
-#endif /* ! STAGE1_5 */
-
-/* Display an ASCII character. */
-void
-grub_putchar (int c)
-{
- if (c == '\n')
- grub_putchar ('\r');
-#ifndef STAGE1_5
- else if (c == '\t' && current_term->getxy)
- {
- int n;
-
- n = 8 - ((current_term->getxy () >> 8) & 3);
- while (n--)
- grub_putchar (' ');
-
- return;
- }
-#endif /* ! STAGE1_5 */
-
-#ifdef STAGE1_5
-
- /* In Stage 1.5, only the normal console is supported. */
- console_putchar (c);
-
-#else /* ! STAGE1_5 */
-
- if (c == '\n')
- {
- /* Internal `more'-like feature. */
- if (count_lines >= 0)
- {
- count_lines++;
- if (count_lines >= max_lines - 2)
- {
- int tmp;
-
- /* It's important to disable the feature temporarily, because
- the following grub_printf call will print newlines. */
- count_lines = -1;
-
- if (current_term->setcolorstate)
- current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
-
- grub_printf ("\n[Hit return to continue]");
-
- if (current_term->setcolorstate)
- current_term->setcolorstate (COLOR_STATE_NORMAL);
-
- do
- {
- tmp = ASCII_CHAR (getkey ());
- }
- while (tmp != '\n' && tmp != '\r');
- grub_printf ("\r \r");
-
- /* Restart to count lines. */
- count_lines = 0;
- return;
- }
- }
- }
-
- current_term->putchar (c);
-
-#endif /* ! STAGE1_5 */
-}
-
-#ifndef STAGE1_5
-void
-gotoxy (int x, int y)
-{
- current_term->gotoxy (x, y);
-}
-
-int
-getxy (void)
-{
- return current_term->getxy ();
-}
-
-void
-cls (void)
-{
- /* If the terminal is dumb, there is no way to clean the terminal. */
- if (current_term->flags & TERM_DUMB)
- grub_putchar ('\n');
- else
- current_term->cls ();
-}
-
-int
-setcursor (int on)
-{
- if (current_term->setcursor)
- return current_term->setcursor (on);
-
- return 1;
-}
-#endif /* ! STAGE1_5 */
-
-int
-substring (const char *s1, const char *s2)
-{
- while (*s1 == *s2)
- {
- /* The strings match exactly. */
- if (! *(s1++))
- return 0;
- s2 ++;
- }
-
- /* S1 is a substring of S2. */
- if (*s1 == 0)
- return -1;
-
- /* S1 isn't a substring. */
- return 1;
-}
-
-#ifndef STAGE1_5
-/* Terminate the string STR with NUL. */
-int
-nul_terminate (char *str)
-{
- int ch;
-
- while (*str && ! grub_isspace (*str))
- str++;
-
- ch = *str;
- *str = 0;
- return ch;
-}
-
-char *
-grub_strstr (const char *s1, const char *s2)
-{
- while (*s1)
- {
- const char *ptr, *tmp;
-
- ptr = s1;
- tmp = s2;
-
- while (*tmp && *ptr == *tmp)
- ptr++, tmp++;
-
- if (tmp > s2 && ! *tmp)
- return (char *) s1;
-
- s1++;
- }
-
- return 0;
-}
-
-int
-grub_strlen (const char *str)
-{
- int len = 0;
-
- while (*str++)
- len++;
-
- return len;
-}
-#endif /* ! STAGE1_5 */
-
-int
-memcheck (int addr, int len)
-{
-#ifdef GRUB_UTIL
- auto int start_addr (void);
- auto int end_addr (void);
-
- auto int start_addr (void)
- {
- int ret;
-# if defined(HAVE_START_SYMBOL)
- asm volatile ("movl $start, %0" : "=a" (ret));
-# elif defined(HAVE_USCORE_START_SYMBOL)
- asm volatile ("movl $_start, %0" : "=a" (ret));
-# endif
- return ret;
- }
-
- auto int end_addr (void)
- {
- int ret;
-# if defined(HAVE_END_SYMBOL)
- asm volatile ("movl $end, %0" : "=a" (ret));
-# elif defined(HAVE_USCORE_END_SYMBOL)
- asm volatile ("movl $_end, %0" : "=a" (ret));
-# endif
- return ret;
- }
-
- if (start_addr () <= addr && end_addr () > addr + len)
- return ! errnum;
-#endif /* GRUB_UTIL */
-
- if ((addr < RAW_ADDR (0x1000))
- || (addr < RAW_ADDR (0x100000)
- && RAW_ADDR (mbi.mem_lower * 1024) < (addr + len))
- || (addr >= RAW_ADDR (0x100000)
- && RAW_ADDR (mbi.mem_upper * 1024) < ((addr - 0x100000) + len)))
- errnum = ERR_WONT_FIT;
-
- return ! errnum;
-}
-
-void *
-grub_memmove (void *to, const void *from, int len)
-{
- if (memcheck ((int) to, len))
- {
- /* This assembly code is stolen from
- linux-2.2.2/include/asm-i386/string.h. This is not very fast
- but compact. */
- int d0, d1, d2;
-
- if (to < from)
- {
- asm volatile ("cld\n\t"
- "rep\n\t"
- "movsb"
- : "=&c" (d0), "=&S" (d1), "=&D" (d2)
- : "0" (len),"1" (from),"2" (to)
- : "memory");
- }
- else
- {
- asm volatile ("std\n\t"
- "rep\n\t"
- "movsb\n\t"
- "cld"
- : "=&c" (d0), "=&S" (d1), "=&D" (d2)
- : "0" (len),
- "1" (len - 1 + (const char *) from),
- "2" (len - 1 + (char *) to)
- : "memory");
- }
- }
-
- return errnum ? NULL : to;
-}
-
-void *
-grub_memset (void *start, int c, int len)
-{
- char *p = start;
-
- if (memcheck ((int) start, len))
- {
- while (len -- > 0)
- *p ++ = c;
- }
-
- return errnum ? NULL : start;
-}
-
-#ifndef STAGE1_5
-char *
-grub_strcpy (char *dest, const char *src)
-{
- grub_memmove (dest, src, grub_strlen (src) + 1);
- return dest;
-}
-#endif /* ! STAGE1_5 */
-
-#ifndef GRUB_UTIL
-# undef memcpy
-/* GCC emits references to memcpy() for struct copies etc. */
-void *memcpy (void *dest, const void *src, int n) __attribute__ ((alias ("grub_memmove")));
-#endif