1 |
/* asmstub.c - a version of shared_src/asm.S that works under Unix */ |
/* asmstub.c - a version of shared_src/asm.S that works under Unix */ |
2 |
/* |
/* |
3 |
* GRUB -- GRand Unified Bootloader |
* GRUB -- GRand Unified Bootloader |
4 |
* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. |
* Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. |
5 |
* |
* |
6 |
* This program is free software; you can redistribute it and/or modify |
* This program is free software; you can redistribute it and/or modify |
7 |
* it under the terms of the GNU General Public License as published by |
* it under the terms of the GNU General Public License as published by |
61 |
#include <shared.h> |
#include <shared.h> |
62 |
#include <device.h> |
#include <device.h> |
63 |
#include <serial.h> |
#include <serial.h> |
64 |
#include <hercules.h> |
#include <term.h> |
65 |
|
|
66 |
/* Simulated memory sizes. */ |
/* Simulated memory sizes. */ |
67 |
#define EXTENDED_MEMSIZE (3 * 1024 * 1024) /* 3MB */ |
#define EXTENDED_MEMSIZE (3 * 1024 * 1024) /* 3MB */ |
87 |
/* The jump buffer for exiting correctly. */ |
/* The jump buffer for exiting correctly. */ |
88 |
static jmp_buf env_for_exit; |
static jmp_buf env_for_exit; |
89 |
|
|
90 |
|
/* The current color for console. */ |
91 |
|
static int console_current_color = A_NORMAL; |
92 |
|
|
93 |
/* The file descriptor for a serial device. */ |
/* The file descriptor for a serial device. */ |
94 |
static int serial_fd = -1; |
static int serial_fd = -1; |
95 |
|
|
510 |
return ticks_per_csec + ticks_per_usec; |
return ticks_per_csec + ticks_per_usec; |
511 |
} |
} |
512 |
|
|
|
/* low-level character I/O */ |
|
|
void |
|
|
console_cls (void) |
|
|
{ |
|
|
#ifdef HAVE_LIBCURSES |
|
|
if (use_curses) |
|
|
clear (); |
|
|
#endif |
|
|
} |
|
|
|
|
|
|
|
|
/* returns packed values, LSB+1 is x, LSB is y */ |
|
|
int |
|
|
console_getxy (void) |
|
|
{ |
|
|
int y, x; |
|
|
#ifdef HAVE_LIBCURSES |
|
|
if (use_curses) |
|
|
getyx (stdscr, y, x); |
|
|
else |
|
|
#endif |
|
|
y = x = 0; |
|
|
return (x << 8) | (y & 0xff); |
|
|
} |
|
|
|
|
|
|
|
|
void |
|
|
console_gotoxy (int x, int y) |
|
|
{ |
|
|
#ifdef HAVE_LIBCURSES |
|
|
if (use_curses) |
|
|
move (y, x); |
|
|
#endif |
|
|
} |
|
|
|
|
513 |
/* displays an ASCII character. IBM displays will translate some |
/* displays an ASCII character. IBM displays will translate some |
514 |
characters to special graphical ones */ |
characters to special graphical ones */ |
515 |
void |
void |
516 |
console_putchar (int c) |
console_putchar (int c) |
517 |
{ |
{ |
518 |
|
/* Curses doesn't have VGA fonts. */ |
519 |
|
switch (c) |
520 |
|
{ |
521 |
|
case DISP_UL: |
522 |
|
c = ACS_ULCORNER; |
523 |
|
break; |
524 |
|
case DISP_UR: |
525 |
|
c = ACS_URCORNER; |
526 |
|
break; |
527 |
|
case DISP_LL: |
528 |
|
c = ACS_LLCORNER; |
529 |
|
break; |
530 |
|
case DISP_LR: |
531 |
|
c = ACS_LRCORNER; |
532 |
|
break; |
533 |
|
case DISP_HORIZ: |
534 |
|
c = ACS_HLINE; |
535 |
|
break; |
536 |
|
case DISP_VERT: |
537 |
|
c = ACS_VLINE; |
538 |
|
break; |
539 |
|
case DISP_LEFT: |
540 |
|
c = ACS_LARROW; |
541 |
|
break; |
542 |
|
case DISP_RIGHT: |
543 |
|
c = ACS_RARROW; |
544 |
|
break; |
545 |
|
case DISP_UP: |
546 |
|
c = ACS_UARROW; |
547 |
|
break; |
548 |
|
case DISP_DOWN: |
549 |
|
c = ACS_DARROW; |
550 |
|
break; |
551 |
|
default: |
552 |
|
break; |
553 |
|
} |
554 |
|
|
555 |
#ifdef HAVE_LIBCURSES |
#ifdef HAVE_LIBCURSES |
556 |
if (use_curses) |
if (use_curses) |
557 |
{ |
{ |
567 |
else |
else |
568 |
move (y + 1, x); |
move (y + 1, x); |
569 |
} |
} |
570 |
|
else if (isprint (c)) |
571 |
|
{ |
572 |
|
int x, y; |
573 |
|
|
574 |
|
getyx (stdscr, y, x); |
575 |
|
if (x + 1 == COLS) |
576 |
|
{ |
577 |
|
console_putchar ('\r'); |
578 |
|
console_putchar ('\n'); |
579 |
|
} |
580 |
|
addch (c | console_current_color); |
581 |
|
} |
582 |
else |
else |
583 |
{ |
{ |
584 |
addch (c); |
addch (c); |
585 |
|
} |
586 |
|
|
587 |
#ifdef REFRESH_IMMEDIATELY |
#ifdef REFRESH_IMMEDIATELY |
588 |
refresh (); |
refresh (); |
589 |
#endif |
#endif |
|
} |
|
590 |
} |
} |
591 |
else |
else |
592 |
#endif |
#endif |
597 |
} |
} |
598 |
} |
} |
599 |
|
|
|
|
|
600 |
/* The store for ungetch simulation. This is necessary, because |
/* The store for ungetch simulation. This is necessary, because |
601 |
ncurses-1.9.9g is still used in the world and its ungetch is |
ncurses-1.9.9g is still used in the world and its ungetch is |
602 |
completely broken. */ |
completely broken. */ |
604 |
static int save_char = ERR; |
static int save_char = ERR; |
605 |
#endif |
#endif |
606 |
|
|
607 |
|
static int |
608 |
|
console_translate_key (int c) |
609 |
|
{ |
610 |
|
switch (c) |
611 |
|
{ |
612 |
|
case KEY_LEFT: |
613 |
|
return 2; |
614 |
|
case KEY_RIGHT: |
615 |
|
return 6; |
616 |
|
case KEY_UP: |
617 |
|
return 16; |
618 |
|
case KEY_DOWN: |
619 |
|
return 14; |
620 |
|
case KEY_DC: |
621 |
|
return 4; |
622 |
|
case KEY_BACKSPACE: |
623 |
|
return 8; |
624 |
|
case KEY_HOME: |
625 |
|
return 1; |
626 |
|
case KEY_END: |
627 |
|
return 5; |
628 |
|
default: |
629 |
|
break; |
630 |
|
} |
631 |
|
|
632 |
|
return c; |
633 |
|
} |
634 |
|
|
635 |
|
/* like 'getkey', but doesn't wait, returns -1 if nothing available */ |
636 |
|
int |
637 |
|
console_checkkey (void) |
638 |
|
{ |
639 |
|
#ifdef HAVE_LIBCURSES |
640 |
|
if (use_curses) |
641 |
|
{ |
642 |
|
int c; |
643 |
|
|
644 |
|
/* Check for SAVE_CHAR. This should not be true, because this |
645 |
|
means checkkey is called twice continuously. */ |
646 |
|
if (save_char != ERR) |
647 |
|
return save_char; |
648 |
|
|
649 |
|
c = getch (); |
650 |
|
/* If C is not ERR, then put it back in the input queue. */ |
651 |
|
if (c != ERR) |
652 |
|
save_char = c; |
653 |
|
return console_translate_key (c); |
654 |
|
} |
655 |
|
#endif |
656 |
|
|
657 |
|
/* Just pretend they hit the space bar, then read the real key when |
658 |
|
they call getkey. */ |
659 |
|
return ' '; |
660 |
|
} |
661 |
|
|
662 |
/* returns packed BIOS/ASCII code */ |
/* returns packed BIOS/ASCII code */ |
663 |
int |
int |
664 |
console_getkey (void) |
console_getkey (void) |
673 |
{ |
{ |
674 |
c = save_char; |
c = save_char; |
675 |
save_char = ERR; |
save_char = ERR; |
676 |
return c; |
return console_translate_key (c); |
677 |
} |
} |
678 |
|
|
679 |
wtimeout (stdscr, -1); |
wtimeout (stdscr, -1); |
687 |
/* Quit if we get EOF. */ |
/* Quit if we get EOF. */ |
688 |
if (c == -1) |
if (c == -1) |
689 |
stop (); |
stop (); |
690 |
return c; |
|
691 |
|
return console_translate_key (c); |
692 |
} |
} |
693 |
|
|
694 |
|
/* returns packed values, LSB+1 is x, LSB is y */ |
|
/* like 'getkey', but doesn't wait, returns -1 if nothing available */ |
|
695 |
int |
int |
696 |
console_checkkey (void) |
console_getxy (void) |
697 |
{ |
{ |
698 |
|
int y, x; |
699 |
#ifdef HAVE_LIBCURSES |
#ifdef HAVE_LIBCURSES |
700 |
if (use_curses) |
if (use_curses) |
701 |
{ |
getyx (stdscr, y, x); |
702 |
int c; |
else |
|
|
|
|
/* Check for SAVE_CHAR. This should not be true, because this |
|
|
means checkkey is called twice continuously. */ |
|
|
if (save_char != ERR) |
|
|
return save_char; |
|
|
|
|
|
c = getch (); |
|
|
/* If C is not ERR, then put it back in the input queue. */ |
|
|
if (c != ERR) |
|
|
save_char = c; |
|
|
return c; |
|
|
} |
|
703 |
#endif |
#endif |
704 |
|
y = x = 0; |
705 |
/* Just pretend they hit the space bar, then read the real key when |
return (x << 8) | (y & 0xff); |
|
they call getkey. */ |
|
|
return ' '; |
|
706 |
} |
} |
707 |
|
|
708 |
|
void |
709 |
|
console_gotoxy (int x, int y) |
710 |
|
{ |
711 |
|
#ifdef HAVE_LIBCURSES |
712 |
|
if (use_curses) |
713 |
|
move (y, x); |
714 |
|
#endif |
715 |
|
} |
716 |
|
|
717 |
/* sets text mode character attribute at the cursor position */ |
/* low-level character I/O */ |
718 |
void |
void |
719 |
console_set_attrib (int attr) |
console_cls (void) |
720 |
{ |
{ |
721 |
#ifdef HAVE_LIBCURSES |
#ifdef HAVE_LIBCURSES |
722 |
if (use_curses) |
if (use_curses) |
723 |
{ |
clear (); |
|
/* FIXME: I don't know why, but chgat doesn't work as expected, so |
|
|
use this dirty way... - okuji */ |
|
|
chtype ch = inch (); |
|
|
addch ((ch & A_CHARTEXT) | attr); |
|
|
# if 0 |
|
|
chgat (1, attr, 0, NULL); |
|
|
# endif |
|
|
} |
|
724 |
#endif |
#endif |
725 |
} |
} |
726 |
|
|
727 |
|
void |
728 |
|
console_highlight (int state) |
729 |
|
{ |
730 |
|
console_current_color = state ? A_REVERSE : A_NORMAL; |
731 |
|
} |
732 |
|
|
733 |
|
void |
734 |
|
console_setcolor (int normal_color, int highlight_color) |
735 |
|
{ |
736 |
|
/* Nothing to do. */ |
737 |
|
} |
738 |
|
|
739 |
|
void |
740 |
|
console_nocursor (void) |
741 |
|
{ |
742 |
|
/* Nothing to do. */ |
743 |
|
} |
744 |
|
|
745 |
/* Low-level disk I/O. Our stubbed version just returns a file |
/* Low-level disk I/O. Our stubbed version just returns a file |
746 |
descriptor, not the actual geometry. */ |
descriptor, not the actual geometry. */ |
747 |
int |
int |
1000 |
/* NOTUSED */ |
/* NOTUSED */ |
1001 |
} |
} |
1002 |
|
|
1003 |
/* The serial version of getkey. */ |
/* Fetch a key from a serial device. */ |
|
int |
|
|
serial_getkey (void) |
|
|
{ |
|
|
char c; |
|
|
#ifdef SIMULATE_SLOWNESS_OF_SERIAL |
|
|
struct timeval otv, tv; |
|
|
|
|
|
gettimeofday (&otv, 0); |
|
|
#endif /* SIMULATE_SLOWNESS_OF_SERIAL */ |
|
|
|
|
|
if (nread (serial_fd, &c, 1) != 1) |
|
|
stop (); |
|
|
|
|
|
#ifdef SIMULATE_SLOWNESS_OF_SERIAL |
|
|
while (1) |
|
|
{ |
|
|
long delta; |
|
|
|
|
|
gettimeofday (&tv, 0); |
|
|
delta = tv.tv_usec - otv.tv_usec; |
|
|
if (delta < 0) |
|
|
delta += 1000000; |
|
|
|
|
|
if (delta >= 1000000 / (serial_speed >> 3)) |
|
|
break; |
|
|
} |
|
|
#endif /* SIMULATE_SLOWNESS_OF_SERIAL */ |
|
|
|
|
|
return c; |
|
|
} |
|
|
|
|
|
/* The serial version of checkkey. */ |
|
1004 |
int |
int |
1005 |
serial_checkkey (void) |
serial_hw_fetch (void) |
1006 |
{ |
{ |
1007 |
fd_set fds; |
fd_set fds; |
1008 |
struct timeval to; |
struct timeval to; |
1009 |
|
char c; |
1010 |
|
|
1011 |
/* Wait only for the serial device. */ |
/* Wait only for the serial device. */ |
1012 |
FD_ZERO (&fds); |
FD_ZERO (&fds); |
1013 |
FD_SET (serial_fd, &fds); |
FD_SET (serial_fd, &fds); |
1014 |
|
|
|
/* Set the timeout to 100ms. */ |
|
1015 |
to.tv_sec = 0; |
to.tv_sec = 0; |
1016 |
to.tv_usec = 100000; |
to.tv_usec = 0; |
1017 |
|
|
1018 |
return select (serial_fd + 1, &fds, 0, 0, &to) > 0 ? : -1; |
if (select (serial_fd + 1, &fds, 0, 0, &to) > 0) |
1019 |
|
{ |
1020 |
|
if (nread (serial_fd, &c, 1) != 1) |
1021 |
|
stop (); |
1022 |
|
|
1023 |
|
return c; |
1024 |
|
} |
1025 |
|
|
1026 |
|
return -1; |
1027 |
} |
} |
1028 |
|
|
1029 |
/* The serial version of grub_putchar. */ |
/* Put a character to a serial device. */ |
1030 |
void |
void |
1031 |
serial_putchar (int c) |
serial_hw_put (int c) |
1032 |
{ |
{ |
1033 |
char ch = (char) c; |
char ch = (char) c; |
|
#ifdef SIMULATE_SLOWNESS_OF_SERIAL |
|
|
struct timeval otv, tv; |
|
|
|
|
|
gettimeofday (&otv, 0); |
|
|
#endif /* SIMULATE_SLOWNESS_OF_SERIAL */ |
|
1034 |
|
|
1035 |
if (nwrite (serial_fd, &ch, 1) != 1) |
if (nwrite (serial_fd, &ch, 1) != 1) |
1036 |
stop (); |
stop (); |
1037 |
|
} |
1038 |
|
|
1039 |
|
void |
1040 |
|
serial_hw_delay (void) |
1041 |
|
{ |
1042 |
#ifdef SIMULATE_SLOWNESS_OF_SERIAL |
#ifdef SIMULATE_SLOWNESS_OF_SERIAL |
1043 |
|
struct timeval otv, tv; |
1044 |
|
|
1045 |
|
gettimeofday (&otv, 0); |
1046 |
|
|
1047 |
while (1) |
while (1) |
1048 |
{ |
{ |
1049 |
long delta; |
long delta; |
1083 |
/* Get the port number of the unit UNIT. In the grub shell, this doesn't |
/* Get the port number of the unit UNIT. In the grub shell, this doesn't |
1084 |
make sense. */ |
make sense. */ |
1085 |
unsigned short |
unsigned short |
1086 |
serial_get_port (int unit) |
serial_hw_get_port (int unit) |
1087 |
{ |
{ |
1088 |
return 0; |
return 0; |
1089 |
} |
} |
1090 |
|
|
|
/* Check if a serial port is set up. */ |
|
|
int |
|
|
serial_exists (void) |
|
|
{ |
|
|
return serial_fd >= 0; |
|
|
} |
|
|
|
|
1091 |
/* Initialize a serial device. In the grub shell, PORT is unused. */ |
/* Initialize a serial device. In the grub shell, PORT is unused. */ |
1092 |
int |
int |
1093 |
serial_init (unsigned short port, unsigned int speed, |
serial_hw_init (unsigned short port, unsigned int speed, |
1094 |
int word_len, int parity, int stop_bit_len) |
int word_len, int parity, int stop_bit_len) |
1095 |
{ |
{ |
1096 |
struct termios termios; |
struct termios termios; |
1097 |
speed_t termios_speed; |
speed_t termios_speed; |
1098 |
|
int i; |
1099 |
|
|
1100 |
/* Check if the file name is specified. */ |
/* Check if the file name is specified. */ |
1101 |
if (! serial_device) |
if (! serial_device) |
1192 |
#ifdef SIMULATE_SLOWNESS_OF_SERIAL |
#ifdef SIMULATE_SLOWNESS_OF_SERIAL |
1193 |
serial_speed = speed; |
serial_speed = speed; |
1194 |
#endif /* SIMUATE_SLOWNESS_OF_SERIAL */ |
#endif /* SIMUATE_SLOWNESS_OF_SERIAL */ |
1195 |
|
|
1196 |
|
/* Get rid of the flag TERM_NEED_INIT from the serial terminal. */ |
1197 |
|
for (i = 0; term_table[i].name; i++) |
1198 |
|
{ |
1199 |
|
if (strcmp (term_table[i].name, "serial") == 0) |
1200 |
|
{ |
1201 |
|
term_table[i].flags &= ~(TERM_NEED_INIT); |
1202 |
|
break; |
1203 |
|
} |
1204 |
|
} |
1205 |
|
|
1206 |
return 1; |
return 1; |
1207 |
|
|
1214 |
/* Set the file name of a serial device (or a pty device). This is a |
/* Set the file name of a serial device (or a pty device). This is a |
1215 |
function specific to the grub shell. */ |
function specific to the grub shell. */ |
1216 |
void |
void |
1217 |
set_serial_device (const char *device) |
serial_set_device (const char *device) |
1218 |
{ |
{ |
1219 |
if (serial_device) |
if (serial_device) |
1220 |
free (serial_device); |
free (serial_device); |
1224 |
|
|
1225 |
/* There is no difference between console and hercules in the grub shell. */ |
/* There is no difference between console and hercules in the grub shell. */ |
1226 |
void |
void |
1227 |
herc_cls (void) |
hercules_putchar (int c) |
1228 |
{ |
{ |
1229 |
console_cls (); |
console_putchar (c); |
1230 |
} |
} |
1231 |
|
|
1232 |
int |
int |
1233 |
herc_getxy (void) |
hercules_getxy (void) |
1234 |
{ |
{ |
1235 |
return console_getxy (); |
return console_getxy (); |
1236 |
} |
} |
1237 |
|
|
1238 |
void |
void |
1239 |
herc_gotoxy (int x, int y) |
hercules_gotoxy (int x, int y) |
1240 |
{ |
{ |
1241 |
console_gotoxy (x, y); |
console_gotoxy (x, y); |
1242 |
} |
} |
1243 |
|
|
1244 |
void |
void |
1245 |
herc_putchar (int c) |
hercules_cls (void) |
1246 |
{ |
{ |
1247 |
console_putchar (c); |
console_cls (); |
1248 |
|
} |
1249 |
|
|
1250 |
|
void |
1251 |
|
hercules_highlight (int state) |
1252 |
|
{ |
1253 |
|
console_highlight (state); |
1254 |
|
} |
1255 |
|
|
1256 |
|
void |
1257 |
|
hercules_setcolor (int normal_color, int highlight_color) |
1258 |
|
{ |
1259 |
|
console_setcolor (normal_color, highlight_color); |
1260 |
} |
} |
1261 |
|
|
1262 |
void |
void |
1263 |
herc_set_attrib (int attr) |
hercules_nocursor (void) |
1264 |
{ |
{ |
1265 |
console_set_attrib (attr); |
console_nocursor (); |
1266 |
} |
} |