Home | History | Annotate | Download | only in grub
      1 /* asmstub.c - a version of shared_src/asm.S that works under Unix */
      2 /*
      3  *  GRUB  --  GRand Unified Bootloader
      4  *  Copyright (C) 1999,2000,2001,2002,2004  Free Software Foundation, Inc.
      5  *
      6  *  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
      8  *  the Free Software Foundation; either version 2 of the License, or
      9  *  (at your option) any later version.
     10  *
     11  *  This program 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 this program; if not, write to the Free Software
     18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     19  */
     20 
     21 /* Try to use glibc's transparant LFS support. */
     22 #define _LARGEFILE_SOURCE	1
     23 /* lseek becomes synonymous with lseek64.  */
     24 #define _FILE_OFFSET_BITS	64
     25 
     26 /* Simulator entry point. */
     27 int grub_stage2 (void);
     28 
     29 #include <stdlib.h>
     30 #include <string.h>
     31 #include <ctype.h>
     32 #include <assert.h>
     33 #include <stdio.h>
     34 #include <sys/types.h>
     35 #include <sys/stat.h>
     36 #include <fcntl.h>
     37 #include <time.h>
     38 #include <errno.h>
     39 #include <string.h>
     40 #include <unistd.h>
     41 #include <setjmp.h>
     42 #include <sys/time.h>
     43 #include <termios.h>
     44 #include <signal.h>
     45 
     46 #ifdef __linux__
     47 # include <sys/ioctl.h>		/* ioctl */
     48 # if !defined(__GLIBC__) || \
     49 	((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
     50 /* Maybe libc doesn't have large file support.  */
     51 #  include <linux/unistd.h>	/* _llseek */
     52 # endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
     53 # ifndef BLKFLSBUF
     54 #  define BLKFLSBUF	_IO (0x12,97)	/* flush buffer cache */
     55 # endif /* ! BLKFLSBUF */
     56 #endif /* __linux__ */
     57 
     58 /* We want to prevent any circularararity in our stubs, as well as
     59    libc name clashes. */
     60 #define WITHOUT_LIBC_STUBS 1
     61 #include <shared.h>
     62 #include <device.h>
     63 #include <serial.h>
     64 #include <term.h>
     65 
     66 /* Simulated memory sizes. */
     67 #define EXTENDED_MEMSIZE (3 * 1024 * 1024)	/* 3MB */
     68 #define CONVENTIONAL_MEMSIZE (640 * 1024)	/* 640kB */
     69 
     70 unsigned long install_partition = 0x20000;
     71 unsigned long boot_drive = 0;
     72 int saved_entryno = 0;
     73 char version_string[] = VERSION;
     74 char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */
     75 unsigned long linux_text_len = 0;
     76 char *linux_data_tmp_addr = 0;
     77 char *linux_data_real_addr = 0;
     78 unsigned short io_map[IO_MAP_SIZE];
     79 struct apm_info apm_bios_info;
     80 
     81 /* Emulation requirements. */
     82 char *grub_scratch_mem = 0;
     83 
     84 struct geometry *disks = 0;
     85 
     86 /* The map between BIOS drives and UNIX device file names.  */
     87 char **device_map = 0;
     88 
     89 /* The jump buffer for exiting correctly.  */
     90 static jmp_buf env_for_exit;
     91 
     92 /* The current color for console.  */
     93 int console_current_color = A_NORMAL;
     94 
     95 /* The file descriptor for a serial device.  */
     96 static int serial_fd = -1;
     97 
     98 /* The file name of a serial device.  */
     99 static char *serial_device = 0;
    100 
    101 #ifdef SIMULATE_SLOWNESS_OF_SERIAL
    102 /* The speed of a serial device.  */
    103 static unsigned int serial_speed;
    104 #endif /* SIMULATE_SLOWNESS_OF_SERIAL */
    105 
    106 /* The main entry point into this mess. */
    107 int
    108 grub_stage2 (void)
    109 {
    110   /* These need to be static, because they survive our stack transitions. */
    111   static int status = 0;
    112   static char *realstack;
    113   char *scratch, *simstack;
    114   int i;
    115 
    116   auto void doit (void);
    117 
    118   /* We need a nested function so that we get a clean stack frame,
    119      regardless of how the code is optimized. */
    120   void doit (void)
    121     {
    122       /* Make sure our stack lives in the simulated memory area. */
    123       asm volatile ("movl %%esp, %0\n\tmovl %1, %%esp\n"
    124 		    : "=&r" (realstack) : "r" (simstack));
    125 
    126       /* Do a setjmp here for the stop command.  */
    127       if (! setjmp (env_for_exit))
    128 	{
    129 	  /* Actually enter the generic stage2 code.  */
    130 	  status = 0;
    131 	  init_bios_info ();
    132 	}
    133       else
    134 	{
    135 	  /* If ERRNUM is non-zero, then set STATUS to non-zero.  */
    136 	  if (errnum)
    137 	    status = 1;
    138 	}
    139 
    140       /* Replace our stack before we use any local variables. */
    141       asm volatile ("movl %0, %%esp\n" : : "r" (realstack));
    142     }
    143 
    144   assert (grub_scratch_mem == 0);
    145   scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);
    146   assert (scratch);
    147   grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);
    148 
    149   /* FIXME: simulate the memory holes using mprot, if available. */
    150 
    151   assert (disks == 0);
    152   disks = malloc (NUM_DISKS * sizeof (*disks));
    153   assert (disks);
    154   /* Initialize DISKS.  */
    155   for (i = 0; i < NUM_DISKS; i++)
    156     disks[i].flags = -1;
    157 
    158   if (! init_device_map (&device_map, device_map_file, floppy_disks))
    159     return 1;
    160 
    161   /* Check some invariants. */
    162   assert ((SCRATCHSEG << 4) == SCRATCHADDR);
    163   assert ((BUFFERSEG << 4) == BUFFERADDR);
    164   assert (BUFFERADDR + BUFFERLEN == SCRATCHADDR);
    165   assert (FSYS_BUF % 16 == 0);
    166   assert (FSYS_BUF + FSYS_BUFLEN == BUFFERADDR);
    167 
    168 #ifdef HAVE_LIBCURSES
    169   /* Get into char-at-a-time mode. */
    170   if (use_curses)
    171     {
    172       initscr ();
    173       cbreak ();
    174       noecho ();
    175       nonl ();
    176       scrollok (stdscr, TRUE);
    177       keypad (stdscr, TRUE);
    178       wtimeout (stdscr, 100);
    179       signal (SIGWINCH, SIG_IGN);
    180     }
    181 #endif
    182 
    183   /* Make sure that actual writing is done.  */
    184   sync ();
    185 
    186   /* Set our stack, and go for it. */
    187   simstack = (char *) PROTSTACKINIT;
    188   doit ();
    189 
    190   /* I don't know if this is necessary really.  */
    191   sync ();
    192 
    193 #ifdef HAVE_LIBCURSES
    194   if (use_curses)
    195     endwin ();
    196 #endif
    197 
    198   /* Close off the file descriptors we used. */
    199   for (i = 0; i < NUM_DISKS; i ++)
    200     if (disks[i].flags != -1)
    201       {
    202 #ifdef __linux__
    203 	/* In Linux, invalidate the buffer cache. In other OSes, reboot
    204 	   is one of the solutions...  */
    205 	ioctl (disks[i].flags, BLKFLSBUF, 0);
    206 #else
    207 # warning "In your operating system, the buffer cache will not be flushed."
    208 #endif
    209 	close (disks[i].flags);
    210       }
    211 
    212   if (serial_fd >= 0)
    213     close (serial_fd);
    214 
    215   /* Release memory. */
    216   restore_device_map (device_map);
    217   device_map = 0;
    218   free (disks);
    219   disks = 0;
    220   free (scratch);
    221   grub_scratch_mem = 0;
    222 
    223   if (serial_device)
    224     free (serial_device);
    225   serial_device = 0;
    226 
    227   /* Ahh... at last we're ready to return to caller. */
    228   return status;
    229 }
    230 
    231 /* Assign DRIVE to a device name DEVICE.  */
    232 void
    233 assign_device_name (int drive, const char *device)
    234 {
    235   /* If DRIVE is already assigned, free it.  */
    236   if (device_map[drive])
    237     free (device_map[drive]);
    238 
    239   /* If the old one is already opened, close it.  */
    240   if (disks[drive].flags != -1)
    241     {
    242       close (disks[drive].flags);
    243       disks[drive].flags = -1;
    244     }
    245 
    246   /* Assign DRIVE to DEVICE.  */
    247   if (! device)
    248     device_map[drive] = 0;
    249   else
    250     device_map[drive] = strdup (device);
    251 }
    252 
    253 void
    254 stop (void)
    255 {
    256 #ifdef HAVE_LIBCURSES
    257   if (use_curses)
    258     endwin ();
    259 #endif
    260 
    261   /* Jump to doit.  */
    262   longjmp (env_for_exit, 1);
    263 }
    264 
    265 void
    266 grub_reboot (void)
    267 {
    268   stop ();
    269 }
    270 
    271 void
    272 grub_halt (int no_apm)
    273 {
    274   stop ();
    275 }
    276 
    277 /* calls for direct boot-loader chaining */
    278 void
    279 chain_stage1 (unsigned long segment, unsigned long offset,
    280 	      unsigned long part_table_addr)
    281 {
    282   stop ();
    283 }
    284 
    285 
    286 void
    287 chain_stage2 (unsigned long segment, unsigned long offset, int second_sector)
    288 {
    289   stop ();
    290 }
    291 
    292 
    293 /* do some funky stuff, then boot linux */
    294 void
    295 linux_boot (void)
    296 {
    297   stop ();
    298 }
    299 
    300 
    301 /* For bzImage kernels. */
    302 void
    303 big_linux_boot (void)
    304 {
    305   stop ();
    306 }
    307 
    308 
    309 /* booting a multiboot executable */
    310 void
    311 multi_boot (int start, int mb_info)
    312 {
    313   stop ();
    314 }
    315 
    316 /* sets it to linear or wired A20 operation */
    317 void
    318 gateA20 (int linear)
    319 {
    320   /* Nothing to do in the simulator. */
    321 }
    322 
    323 /* Set up the int15 handler.  */
    324 void
    325 set_int15_handler (void)
    326 {
    327   /* Nothing to do in the simulator.  */
    328 }
    329 
    330 /* Restore the original int15 handler.  */
    331 void
    332 unset_int15_handler (void)
    333 {
    334   /* Nothing to do in the simulator.  */
    335 }
    336 
    337 /* The key map.  */
    338 unsigned short bios_key_map[KEY_MAP_SIZE + 1];
    339 unsigned short ascii_key_map[KEY_MAP_SIZE + 1];
    340 
    341 /* Copy MAP to the drive map and set up the int13 handler.  */
    342 void
    343 set_int13_handler (unsigned short *map)
    344 {
    345   /* Nothing to do in the simulator.  */
    346 }
    347 
    348 int
    349 get_code_end (void)
    350 {
    351   /* Just return a little area for simulation. */
    352   return BOOTSEC_LOCATION + (60 * 1024);
    353 }
    354 
    355 
    356 /* memory probe routines */
    357 int
    358 get_memsize (int type)
    359 {
    360   if (! type)
    361     return CONVENTIONAL_MEMSIZE >> 10;
    362   else
    363     return EXTENDED_MEMSIZE >> 10;
    364 }
    365 
    366 
    367 /* get_eisamemsize() :  return packed EISA memory map, lower 16 bits is
    368  *		memory between 1M and 16M in 1K parts, upper 16 bits is
    369  *		memory above 16M in 64K parts.  If error, return -1.
    370  */
    371 int
    372 get_eisamemsize (void)
    373 {
    374   return (EXTENDED_MEMSIZE >> 10);
    375 }
    376 
    377 
    378 #define MMAR_DESC_TYPE_AVAILABLE 1 /* available to OS */
    379 #define MMAR_DESC_TYPE_RESERVED 2 /* not available */
    380 #define MMAR_DESC_TYPE_ACPI_RECLAIM 3 /* usable by OS after reading ACPI */
    381 #define MMAR_DESC_TYPE_ACPI_NVS 4 /* required to save between NVS sessions */
    382 
    383 #define MMAR_DESC_LENGTH	20
    384 
    385 /* Fetch the next entry in the memory map and return the continuation
    386    value.  DESC is a pointer to the descriptor buffer, and CONT is the
    387    previous continuation value (0 to get the first entry in the
    388    map).  */
    389 int
    390 get_mmap_entry (struct mmar_desc *desc, int cont)
    391 {
    392   /* Record the memory map statically.  */
    393   static struct mmar_desc desc_table[] =
    394   {
    395     /* The conventional memory.  */
    396     {
    397       MMAR_DESC_LENGTH,
    398       0,
    399       CONVENTIONAL_MEMSIZE,
    400       MMAR_DESC_TYPE_AVAILABLE
    401     },
    402     /* BIOS RAM and ROM (such as video memory).  */
    403     {
    404       MMAR_DESC_LENGTH,
    405       CONVENTIONAL_MEMSIZE,
    406       0x100000 - CONVENTIONAL_MEMSIZE,
    407       MMAR_DESC_TYPE_RESERVED
    408     },
    409     /* The extended memory.  */
    410     {
    411       MMAR_DESC_LENGTH,
    412       0x100000,
    413       EXTENDED_MEMSIZE,
    414       MMAR_DESC_TYPE_AVAILABLE
    415     }
    416   };
    417 
    418   int num = sizeof (desc_table) / sizeof (*desc_table);
    419 
    420   if (cont < 0 || cont >= num)
    421     {
    422       /* Should not happen.  */
    423       desc->desc_len = 0;
    424     }
    425   else
    426     {
    427       /* Copy the entry.  */
    428       *desc = desc_table[cont++];
    429 
    430       /* If the next entry exists, return the index.  */
    431       if (cont < num)
    432 	return cont;
    433     }
    434 
    435   return 0;
    436 }
    437 
    438 /* Track the int13 handler.  */
    439 void
    440 track_int13 (int drive)
    441 {
    442   /* Nothing to do in the simulator.  */
    443 }
    444 
    445 /* Get the ROM configuration table.  */
    446 unsigned long
    447 get_rom_config_table (void)
    448 {
    449   return 0;
    450 }
    451 
    452 /* Get APM BIOS information.  */
    453 void
    454 get_apm_info (void)
    455 {
    456   /* Nothing to do in the simulator.  */
    457 }
    458 
    459 /* Get VBE controller information.  */
    460 int
    461 get_vbe_controller_info (struct vbe_controller *controller)
    462 {
    463   /* Always fails.  */
    464   return 0;
    465 }
    466 
    467 /* Get VBE mode information.  */
    468 int
    469 get_vbe_mode_info (int mode_number, struct vbe_mode *mode)
    470 {
    471   /* Always fails.  */
    472   return 0;
    473 }
    474 
    475 /* Set VBE mode.  */
    476 int
    477 set_vbe_mode (int mode_number)
    478 {
    479   /* Always fails.  */
    480   return 0;
    481 }
    482 
    483 /* low-level timing info */
    484 int
    485 getrtsecs (void)
    486 {
    487   /* FIXME: exact value is not important, so just return time_t for now. */
    488   return time (0);
    489 }
    490 
    491 int
    492 currticks (void)
    493 {
    494   struct timeval tv;
    495   long csecs;
    496   int ticks_per_csec, ticks_per_usec;
    497 
    498   /* Note: 18.2 ticks/sec.  */
    499 
    500   /* Get current time.  */
    501   gettimeofday (&tv, 0);
    502 
    503   /* Compute centiseconds.  */
    504   csecs = tv.tv_sec / 10;
    505 
    506   /* Ticks per centisecond.  */
    507   ticks_per_csec = csecs * 182;
    508 
    509   /* Ticks per microsecond.  */
    510   ticks_per_usec = (((tv.tv_sec - csecs * 10) * 1000000 + tv.tv_usec)
    511 		    * 182 / 10000000);
    512 
    513   /* Sum them.  */
    514   return ticks_per_csec + ticks_per_usec;
    515 }
    516 
    517 /* displays an ASCII character.  IBM displays will translate some
    518    characters to special graphical ones */
    519 void
    520 console_putchar (int c)
    521 {
    522   /* Curses doesn't have VGA fonts.  */
    523   switch (c)
    524     {
    525     case DISP_UL:
    526       c = ACS_ULCORNER;
    527       break;
    528     case DISP_UR:
    529       c = ACS_URCORNER;
    530       break;
    531     case DISP_LL:
    532       c = ACS_LLCORNER;
    533       break;
    534     case DISP_LR:
    535       c = ACS_LRCORNER;
    536       break;
    537     case DISP_HORIZ:
    538       c = ACS_HLINE;
    539       break;
    540     case DISP_VERT:
    541       c = ACS_VLINE;
    542       break;
    543     case DISP_LEFT:
    544       c = ACS_LARROW;
    545       break;
    546     case DISP_RIGHT:
    547       c = ACS_RARROW;
    548       break;
    549     case DISP_UP:
    550       c = ACS_UARROW;
    551       break;
    552     case DISP_DOWN:
    553       c = ACS_DARROW;
    554       break;
    555     default:
    556       break;
    557     }
    558 
    559 #ifdef HAVE_LIBCURSES
    560   if (use_curses)
    561     {
    562       /* In ncurses, a newline is treated badly, so we emulate it in our
    563 	 own way.  */
    564       if (c == '\n')
    565 	{
    566 	  int x, y;
    567 
    568 	  getyx (stdscr, y, x);
    569 	  if (y + 1 == LINES)
    570 	    scroll (stdscr);
    571 	  else
    572 	    move (y + 1, x);
    573 	}
    574       else if (isprint (c))
    575 	{
    576 	  int x, y;
    577 
    578 	  getyx (stdscr, y, x);
    579 	  if (x + 1 == COLS)
    580 	    {
    581 	      console_putchar ('\r');
    582 	      console_putchar ('\n');
    583 	    }
    584 	  addch (c | console_current_color);
    585 	}
    586       else
    587 	{
    588 	  addch (c);
    589 	}
    590 
    591 #ifdef REFRESH_IMMEDIATELY
    592       refresh ();
    593 #endif
    594     }
    595   else
    596 #endif
    597     {
    598       /* CR is not used in Unix.  */
    599       if (c != '\r')
    600 	putchar (c);
    601     }
    602 }
    603 
    604 /* The store for ungetch simulation. This is necessary, because
    605    ncurses-1.9.9g is still used in the world and its ungetch is
    606    completely broken.  */
    607 #ifdef HAVE_LIBCURSES
    608 static int save_char = ERR;
    609 #endif
    610 
    611 static int
    612 console_translate_key (int c)
    613 {
    614   switch (c)
    615     {
    616     case KEY_LEFT:
    617       return 2;
    618     case KEY_RIGHT:
    619       return 6;
    620     case KEY_UP:
    621       return 16;
    622     case KEY_DOWN:
    623       return 14;
    624     case KEY_DC:
    625       return 4;
    626     case KEY_BACKSPACE:
    627       return 8;
    628     case KEY_HOME:
    629       return 1;
    630     case KEY_END:
    631       return 5;
    632     case KEY_PPAGE:
    633       return 7;
    634     case KEY_NPAGE:
    635       return 3;
    636     default:
    637       break;
    638     }
    639 
    640   return c;
    641 }
    642 
    643 /* like 'getkey', but doesn't wait, returns -1 if nothing available */
    644 int
    645 console_checkkey (void)
    646 {
    647 #ifdef HAVE_LIBCURSES
    648   if (use_curses)
    649     {
    650       int c;
    651 
    652       /* Check for SAVE_CHAR. This should not be true, because this
    653 	 means checkkey is called twice continuously.  */
    654       if (save_char != ERR)
    655 	return save_char;
    656 
    657       c = getch ();
    658       /* If C is not ERR, then put it back in the input queue.  */
    659       if (c != ERR)
    660 	save_char = c;
    661       return console_translate_key (c);
    662     }
    663 #endif
    664 
    665   /* Just pretend they hit the space bar, then read the real key when
    666      they call getkey. */
    667   return ' ';
    668 }
    669 
    670 /* returns packed BIOS/ASCII code */
    671 int
    672 console_getkey (void)
    673 {
    674   int c;
    675 
    676 #ifdef HAVE_LIBCURSES
    677   if (use_curses)
    678     {
    679       /* If checkkey has already got a character, then return it.  */
    680       if (save_char != ERR)
    681 	{
    682 	  c = save_char;
    683 	  save_char = ERR;
    684 	  return console_translate_key (c);
    685 	}
    686 
    687       wtimeout (stdscr, -1);
    688       c = getch ();
    689       wtimeout (stdscr, 100);
    690     }
    691   else
    692 #endif
    693     c = getchar ();
    694 
    695   /* Quit if we get EOF. */
    696   if (c == -1)
    697     stop ();
    698 
    699   return console_translate_key (c);
    700 }
    701 
    702 /* returns packed values, LSB+1 is x, LSB is y */
    703 int
    704 console_getxy (void)
    705 {
    706   int y, x;
    707 #ifdef HAVE_LIBCURSES
    708   if (use_curses)
    709     getyx (stdscr, y, x);
    710   else
    711 #endif
    712   y = x = 0;
    713   return (x << 8) | (y & 0xff);
    714 }
    715 
    716 void
    717 console_gotoxy (int x, int y)
    718 {
    719 #ifdef HAVE_LIBCURSES
    720   if (use_curses)
    721     move (y, x);
    722 #endif
    723 }
    724 
    725 /* low-level character I/O */
    726 void
    727 console_cls (void)
    728 {
    729 #ifdef HAVE_LIBCURSES
    730   if (use_curses)
    731     clear ();
    732 #endif
    733 }
    734 
    735 void
    736 console_setcolorstate (color_state state)
    737 {
    738   console_current_color =
    739     (state == COLOR_STATE_HIGHLIGHT) ? A_REVERSE : A_NORMAL;
    740 }
    741 
    742 void
    743 console_setcolor (int normal_color, int highlight_color)
    744 {
    745   /* Nothing to do.  */
    746 }
    747 
    748 int
    749 console_setcursor (int on)
    750 {
    751   return 1;
    752 }
    753 
    754 /* Low-level disk I/O.  Our stubbed version just returns a file
    755    descriptor, not the actual geometry. */
    756 int
    757 get_diskinfo (int drive, struct geometry *geometry)
    758 {
    759   /* FIXME: this function is truly horrid.  We try opening the device,
    760      then severely abuse the GEOMETRY->flags field to pass a file
    761      descriptor to biosdisk.  Thank God nobody's looking at this comment,
    762      or my reputation would be ruined. --Gord */
    763 
    764   /* See if we have a cached device. */
    765   if (disks[drive].flags == -1)
    766     {
    767       /* The unpartitioned device name: /dev/XdX */
    768       char *devname = device_map[drive];
    769       char buf[512];
    770 
    771       if (! devname)
    772 	return -1;
    773 
    774       if (verbose)
    775 	grub_printf ("Attempt to open drive 0x%x (%s)\n",
    776 		     drive, devname);
    777 
    778       /* Open read/write, or read-only if that failed. */
    779       if (! read_only)
    780 	disks[drive].flags = open (devname, O_RDWR);
    781 
    782       if (disks[drive].flags == -1)
    783 	{
    784 	  if (read_only || errno == EACCES || errno == EROFS || errno == EPERM)
    785 	    {
    786 	      disks[drive].flags = open (devname, O_RDONLY);
    787 	      if (disks[drive].flags == -1)
    788 		{
    789 		  assign_device_name (drive, 0);
    790 		  return -1;
    791 		}
    792 	    }
    793 	  else
    794 	    {
    795 	      assign_device_name (drive, 0);
    796 	      return -1;
    797 	    }
    798 	}
    799 
    800       /* Attempt to read the first sector.  */
    801       if (read (disks[drive].flags, buf, 512) != 512)
    802 	{
    803 	  close (disks[drive].flags);
    804 	  disks[drive].flags = -1;
    805 	  assign_device_name (drive, 0);
    806 	  return -1;
    807 	}
    808 
    809       if (disks[drive].flags != -1)
    810 	get_drive_geometry (&disks[drive], device_map, drive);
    811     }
    812 
    813   if (disks[drive].flags == -1)
    814     return -1;
    815 
    816 #ifdef __linux__
    817   /* In Linux, invalidate the buffer cache, so that left overs
    818      from other program in the cache are flushed and seen by us */
    819   ioctl (disks[drive].flags, BLKFLSBUF, 0);
    820 #endif
    821 
    822   *geometry = disks[drive];
    823   return 0;
    824 }
    825 
    826 /* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
    827    error occurs, otherwise return LEN.  */
    828 static int
    829 nread (int fd, char *buf, size_t len)
    830 {
    831   int size = len;
    832 
    833   while (len)
    834     {
    835       int ret = read (fd, buf, len);
    836 
    837       if (ret <= 0)
    838 	{
    839 	  if (errno == EINTR)
    840 	    continue;
    841 	  else
    842 	    return ret;
    843 	}
    844 
    845       len -= ret;
    846       buf += ret;
    847     }
    848 
    849   return size;
    850 }
    851 
    852 /* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
    853    error occurs, otherwise return LEN.  */
    854 static int
    855 nwrite (int fd, char *buf, size_t len)
    856 {
    857   int size = len;
    858 
    859   while (len)
    860     {
    861       int ret = write (fd, buf, len);
    862 
    863       if (ret <= 0)
    864 	{
    865 	  if (errno == EINTR)
    866 	    continue;
    867 	  else
    868 	    return ret;
    869 	}
    870 
    871       len -= ret;
    872       buf += ret;
    873     }
    874 
    875   return size;
    876 }
    877 
    878 /* Dump BUF in the format of hexadecimal numbers.  */
    879 static void
    880 hex_dump (void *buf, size_t size)
    881 {
    882   /* FIXME: How to determine which length is readable?  */
    883 #define MAX_COLUMN	70
    884 
    885   /* use unsigned char for numerical computations */
    886   unsigned char *ptr = buf;
    887   /* count the width of the line */
    888   int column = 0;
    889   /* how many bytes written */
    890   int count = 0;
    891 
    892   while (size > 0)
    893     {
    894       /* high 4 bits */
    895       int hi = *ptr >> 4;
    896       /* low 4 bits */
    897       int low = *ptr & 0xf;
    898 
    899       /* grub_printf does not handle prefix number, such as %2x, so
    900 	 format the number by hand...  */
    901       grub_printf ("%x%x", hi, low);
    902       column += 2;
    903       count++;
    904       ptr++;
    905       size--;
    906 
    907       /* Insert space or newline with the interval 4 bytes.  */
    908       if (size != 0 && (count % 4) == 0)
    909 	{
    910 	  if (column < MAX_COLUMN)
    911 	    {
    912 	      grub_printf (" ");
    913 	      column++;
    914 	    }
    915 	  else
    916 	    {
    917 	      grub_printf ("\n");
    918 	      column = 0;
    919 	    }
    920 	}
    921     }
    922 
    923   /* Add a newline at the end for readability.  */
    924   grub_printf ("\n");
    925 }
    926 
    927 int
    928 biosdisk (int subfunc, int drive, struct geometry *geometry,
    929 	  int sector, int nsec, int segment)
    930 {
    931   char *buf;
    932   int fd = geometry->flags;
    933 
    934   /* Get the file pointer from the geometry, and make sure it matches. */
    935   if (fd == -1 || fd != disks[drive].flags)
    936     return BIOSDISK_ERROR_GEOMETRY;
    937 
    938   /* Seek to the specified location. */
    939 #if defined(__linux__) && (!defined(__GLIBC__) || \
    940 	((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
    941   /* Maybe libc doesn't have large file support.  */
    942   {
    943     loff_t offset, result;
    944     static int _llseek (uint filedes, ulong hi, ulong lo,
    945 			loff_t *res, uint wh);
    946     _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
    947 	       loff_t *, res, uint, wh);
    948 
    949     offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
    950     if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
    951       return -1;
    952   }
    953 #else
    954   {
    955     off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
    956 
    957     if (lseek (fd, offset, SEEK_SET) != offset)
    958       return -1;
    959   }
    960 #endif
    961 
    962   buf = (char *) (segment << 4);
    963 
    964   switch (subfunc)
    965     {
    966     case BIOSDISK_READ:
    967 #ifdef __linux__
    968       if (sector == 0 && nsec > 1)
    969 	{
    970 	  /* Work around a bug in linux's ez remapping.  Linux remaps all
    971 	     sectors that are read together with the MBR in one read.  It
    972 	     should only remap the MBR, so we split the read in two
    973 	     parts. -jochen  */
    974 	  if (nread (fd, buf, SECTOR_SIZE) != SECTOR_SIZE)
    975 	    return -1;
    976 	  buf += SECTOR_SIZE;
    977 	  nsec--;
    978 	}
    979 #endif
    980       if (nread (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
    981 	return -1;
    982       break;
    983 
    984     case BIOSDISK_WRITE:
    985       if (verbose)
    986 	{
    987 	  grub_printf ("Write %d sectors starting from %d sector"
    988 		       " to drive 0x%x (%s)\n",
    989 		       nsec, sector, drive, device_map[drive]);
    990 	  hex_dump (buf, nsec * SECTOR_SIZE);
    991 	}
    992       if (! read_only)
    993 	if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
    994 	  return -1;
    995       break;
    996 
    997     default:
    998       grub_printf ("unknown subfunc %d\n", subfunc);
    999       break;
   1000     }
   1001 
   1002   return 0;
   1003 }
   1004 
   1005 
   1006 void
   1007 stop_floppy (void)
   1008 {
   1009   /* NOTUSED */
   1010 }
   1011 
   1012 /* Fetch a key from a serial device.  */
   1013 int
   1014 serial_hw_fetch (void)
   1015 {
   1016   fd_set fds;
   1017   struct timeval to;
   1018   char c;
   1019 
   1020   /* Wait only for the serial device.  */
   1021   FD_ZERO (&fds);
   1022   FD_SET (serial_fd, &fds);
   1023 
   1024   to.tv_sec = 0;
   1025   to.tv_usec = 0;
   1026 
   1027   if (select (serial_fd + 1, &fds, 0, 0, &to) > 0)
   1028     {
   1029       if (nread (serial_fd, &c, 1) != 1)
   1030 	stop ();
   1031 
   1032       return c;
   1033     }
   1034 
   1035   return -1;
   1036 }
   1037 
   1038 /* Put a character to a serial device.  */
   1039 void
   1040 serial_hw_put (int c)
   1041 {
   1042   char ch = (char) c;
   1043 
   1044   if (nwrite (serial_fd, &ch, 1) != 1)
   1045     stop ();
   1046 }
   1047 
   1048 void
   1049 serial_hw_delay (void)
   1050 {
   1051 #ifdef SIMULATE_SLOWNESS_OF_SERIAL
   1052   struct timeval otv, tv;
   1053 
   1054   gettimeofday (&otv, 0);
   1055 
   1056   while (1)
   1057     {
   1058       long delta;
   1059 
   1060       gettimeofday (&tv, 0);
   1061       delta = tv.tv_usec - otv.tv_usec;
   1062       if (delta < 0)
   1063 	delta += 1000000;
   1064 
   1065       if (delta >= 1000000 / (serial_speed >> 3))
   1066 	break;
   1067     }
   1068 #endif /* SIMULATE_SLOWNESS_OF_SERIAL */
   1069 }
   1070 
   1071 static speed_t
   1072 get_termios_speed (int speed)
   1073 {
   1074   switch (speed)
   1075     {
   1076     case 2400: return B2400;
   1077     case 4800: return B4800;
   1078     case 9600: return B9600;
   1079     case 19200: return B19200;
   1080     case 38400: return B38400;
   1081 #ifdef B57600
   1082     case 57600: return B57600;
   1083 #endif
   1084 #ifdef B115200
   1085     case 115200: return B115200;
   1086 #endif
   1087     }
   1088 
   1089   return B0;
   1090 }
   1091 
   1092 /* Get the port number of the unit UNIT. In the grub shell, this doesn't
   1093    make sense.  */
   1094 unsigned short
   1095 serial_hw_get_port (int unit)
   1096 {
   1097   return 0;
   1098 }
   1099 
   1100 /* Initialize a serial device. In the grub shell, PORT is unused.  */
   1101 int
   1102 serial_hw_init (unsigned short port, unsigned int speed,
   1103 		int word_len, int parity, int stop_bit_len)
   1104 {
   1105   struct termios termios;
   1106   speed_t termios_speed;
   1107   int i;
   1108 
   1109   /* Check if the file name is specified.  */
   1110   if (! serial_device)
   1111     return 0;
   1112 
   1113   /* If a serial device is already opened, close it first.  */
   1114   if (serial_fd >= 0)
   1115     close (serial_fd);
   1116 
   1117   /* Open the device file.  */
   1118   serial_fd = open (serial_device,
   1119 		    O_RDWR | O_NOCTTY
   1120 #if defined(O_SYNC)
   1121 		    /* O_SYNC is used in Linux (and some others?).  */
   1122 		    | O_SYNC
   1123 #elif defined(O_FSYNC)
   1124 		    /* O_FSYNC is used in FreeBSD.  */
   1125 		    | O_FSYNC
   1126 #endif
   1127 		    );
   1128   if (serial_fd < 0)
   1129     return 0;
   1130 
   1131   /* Get the termios parameters.  */
   1132   if (tcgetattr (serial_fd, &termios))
   1133     goto fail;
   1134 
   1135   /* Raw mode.  */
   1136   cfmakeraw (&termios);
   1137 
   1138   /* Set the speed.  */
   1139   termios_speed = get_termios_speed (speed);
   1140   if (termios_speed == B0)
   1141     goto fail;
   1142 
   1143   cfsetispeed (&termios, termios_speed);
   1144   cfsetospeed (&termios, termios_speed);
   1145 
   1146   /* Set the word length.  */
   1147   termios.c_cflag &= ~CSIZE;
   1148   switch (word_len)
   1149     {
   1150     case UART_5BITS_WORD:
   1151       termios.c_cflag |= CS5;
   1152       break;
   1153     case UART_6BITS_WORD:
   1154       termios.c_cflag |= CS6;
   1155       break;
   1156     case UART_7BITS_WORD:
   1157       termios.c_cflag |= CS7;
   1158       break;
   1159     case UART_8BITS_WORD:
   1160       termios.c_cflag |= CS8;
   1161       break;
   1162     default:
   1163       goto fail;
   1164     }
   1165 
   1166   /* Set the parity.  */
   1167   switch (parity)
   1168     {
   1169     case UART_NO_PARITY:
   1170       termios.c_cflag &= ~PARENB;
   1171       break;
   1172     case UART_ODD_PARITY:
   1173       termios.c_cflag |= PARENB;
   1174       termios.c_cflag |= PARODD;
   1175       break;
   1176     case UART_EVEN_PARITY:
   1177       termios.c_cflag |= PARENB;
   1178       termios.c_cflag &= ~PARODD;
   1179       break;
   1180     default:
   1181       goto fail;
   1182     }
   1183 
   1184   /* Set the length of stop bit.  */
   1185   switch (stop_bit_len)
   1186     {
   1187     case UART_1_STOP_BIT:
   1188       termios.c_cflag &= ~CSTOPB;
   1189       break;
   1190     case UART_2_STOP_BITS:
   1191       termios.c_cflag |= CSTOPB;
   1192       break;
   1193     default:
   1194       goto fail;
   1195     }
   1196 
   1197   /* Set the parameters.  */
   1198   if (tcsetattr (serial_fd, TCSANOW, &termios))
   1199     goto fail;
   1200 
   1201 #ifdef SIMULATE_SLOWNESS_OF_SERIAL
   1202   serial_speed = speed;
   1203 #endif /* SIMUATE_SLOWNESS_OF_SERIAL */
   1204 
   1205   /* Get rid of the flag TERM_NEED_INIT from the serial terminal.  */
   1206   for (i = 0; term_table[i].name; i++)
   1207     {
   1208       if (strcmp (term_table[i].name, "serial") == 0)
   1209 	{
   1210 	  term_table[i].flags &= ~(TERM_NEED_INIT);
   1211 	  break;
   1212 	}
   1213     }
   1214 
   1215   return 1;
   1216 
   1217  fail:
   1218   close (serial_fd);
   1219   serial_fd = -1;
   1220   return 0;
   1221 }
   1222 
   1223 /* Set the file name of a serial device (or a pty device). This is a
   1224    function specific to the grub shell.  */
   1225 void
   1226 serial_set_device (const char *device)
   1227 {
   1228   if (serial_device)
   1229     free (serial_device);
   1230 
   1231   serial_device = strdup (device);
   1232 }
   1233 
   1234 /* There is no difference between console and hercules in the grub shell.  */
   1235 void
   1236 hercules_putchar (int c)
   1237 {
   1238   console_putchar (c);
   1239 }
   1240 
   1241 int
   1242 hercules_getxy (void)
   1243 {
   1244   return console_getxy ();
   1245 }
   1246 
   1247 void
   1248 hercules_gotoxy (int x, int y)
   1249 {
   1250   console_gotoxy (x, y);
   1251 }
   1252 
   1253 void
   1254 hercules_cls (void)
   1255 {
   1256   console_cls ();
   1257 }
   1258 
   1259 void
   1260 hercules_setcolorstate (color_state state)
   1261 {
   1262   console_setcolorstate (state);
   1263 }
   1264 
   1265 void
   1266 hercules_setcolor (int normal_color, int highlight_color)
   1267 {
   1268   console_setcolor (normal_color, highlight_color);
   1269 }
   1270 
   1271 int
   1272 hercules_setcursor (int on)
   1273 {
   1274   return 1;
   1275 }
   1276