17c478bd9Sstevel@tonic-gate /* asmstub.c - a version of shared_src/asm.S that works under Unix */
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate  *  GRUB  --  GRand Unified Bootloader
47c478bd9Sstevel@tonic-gate  *  Copyright (C) 1999,2000,2001,2002,2004  Free Software Foundation, Inc.
57c478bd9Sstevel@tonic-gate  *
67c478bd9Sstevel@tonic-gate  *  This program is free software; you can redistribute it and/or modify
77c478bd9Sstevel@tonic-gate  *  it under the terms of the GNU General Public License as published by
87c478bd9Sstevel@tonic-gate  *  the Free Software Foundation; either version 2 of the License, or
97c478bd9Sstevel@tonic-gate  *  (at your option) any later version.
107c478bd9Sstevel@tonic-gate  *
117c478bd9Sstevel@tonic-gate  *  This program is distributed in the hope that it will be useful,
127c478bd9Sstevel@tonic-gate  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
137c478bd9Sstevel@tonic-gate  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
147c478bd9Sstevel@tonic-gate  *  GNU General Public License for more details.
157c478bd9Sstevel@tonic-gate  *
167c478bd9Sstevel@tonic-gate  *  You should have received a copy of the GNU General Public License
177c478bd9Sstevel@tonic-gate  *  along with this program; if not, write to the Free Software
187c478bd9Sstevel@tonic-gate  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
197c478bd9Sstevel@tonic-gate  */
20*9890706eSHans Rosenfeld /*
21*9890706eSHans Rosenfeld  * Copyright 2016 Nexenta Systems, Inc.
22*9890706eSHans Rosenfeld  */
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate /* Try to use glibc's transparant LFS support. */
257c478bd9Sstevel@tonic-gate #define _LARGEFILE_SOURCE	1
267c478bd9Sstevel@tonic-gate /* lseek becomes synonymous with lseek64.  */
277c478bd9Sstevel@tonic-gate #define _FILE_OFFSET_BITS	64
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /* Simulator entry point. */
307c478bd9Sstevel@tonic-gate int grub_stage2 (void);
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <string.h>
347c478bd9Sstevel@tonic-gate #include <ctype.h>
357c478bd9Sstevel@tonic-gate #include <assert.h>
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
387c478bd9Sstevel@tonic-gate #include <sys/stat.h>
397c478bd9Sstevel@tonic-gate #include <fcntl.h>
407c478bd9Sstevel@tonic-gate #include <time.h>
417c478bd9Sstevel@tonic-gate #include <errno.h>
427c478bd9Sstevel@tonic-gate #include <string.h>
437c478bd9Sstevel@tonic-gate #include <unistd.h>
447c478bd9Sstevel@tonic-gate #include <setjmp.h>
457c478bd9Sstevel@tonic-gate #include <sys/time.h>
467c478bd9Sstevel@tonic-gate #include <termios.h>
477c478bd9Sstevel@tonic-gate #include <signal.h>
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #ifdef __linux__
507c478bd9Sstevel@tonic-gate # include <sys/ioctl.h>		/* ioctl */
517c478bd9Sstevel@tonic-gate # if !defined(__GLIBC__) || \
527c478bd9Sstevel@tonic-gate 	((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
537c478bd9Sstevel@tonic-gate /* Maybe libc doesn't have large file support.  */
547c478bd9Sstevel@tonic-gate #  include <linux/unistd.h>	/* _llseek */
557c478bd9Sstevel@tonic-gate # endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
567c478bd9Sstevel@tonic-gate # ifndef BLKFLSBUF
577c478bd9Sstevel@tonic-gate #  define BLKFLSBUF	_IO (0x12,97)	/* flush buffer cache */
587c478bd9Sstevel@tonic-gate # endif /* ! BLKFLSBUF */
597c478bd9Sstevel@tonic-gate #endif /* __linux__ */
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate /* We want to prevent any circularararity in our stubs, as well as
627c478bd9Sstevel@tonic-gate    libc name clashes. */
637c478bd9Sstevel@tonic-gate #define WITHOUT_LIBC_STUBS 1
647c478bd9Sstevel@tonic-gate #include <shared.h>
657c478bd9Sstevel@tonic-gate #include <device.h>
667c478bd9Sstevel@tonic-gate #include <serial.h>
677c478bd9Sstevel@tonic-gate #include <term.h>
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /* Simulated memory sizes. */
70b1b8ab34Slling #define EXTENDED_MEMSIZE (64 * 1024 * 1024)	/* 64MB */
717c478bd9Sstevel@tonic-gate #define CONVENTIONAL_MEMSIZE (640 * 1024)	/* 640kB */
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate unsigned long install_partition = 0x20000;
747c478bd9Sstevel@tonic-gate unsigned long boot_drive = 0;
757c478bd9Sstevel@tonic-gate int saved_entryno = 0;
767c478bd9Sstevel@tonic-gate char version_string[] = VERSION;
777c478bd9Sstevel@tonic-gate char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */
787c478bd9Sstevel@tonic-gate unsigned long linux_text_len = 0;
797c478bd9Sstevel@tonic-gate char *linux_data_tmp_addr = 0;
807c478bd9Sstevel@tonic-gate char *linux_data_real_addr = 0;
817c478bd9Sstevel@tonic-gate unsigned short io_map[IO_MAP_SIZE];
827c478bd9Sstevel@tonic-gate struct apm_info apm_bios_info;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /* Emulation requirements. */
857c478bd9Sstevel@tonic-gate char *grub_scratch_mem = 0;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate struct geometry *disks = 0;
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate /* The map between BIOS drives and UNIX device file names.  */
907c478bd9Sstevel@tonic-gate char **device_map = 0;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /* The jump buffer for exiting correctly.  */
937c478bd9Sstevel@tonic-gate static jmp_buf env_for_exit;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /* The current color for console.  */
961b8adde7SWilliam Kucharski int console_current_color = A_NORMAL;
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /* The file descriptor for a serial device.  */
997c478bd9Sstevel@tonic-gate static int serial_fd = -1;
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate /* The file name of a serial device.  */
1027c478bd9Sstevel@tonic-gate static char *serial_device = 0;
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate #ifdef SIMULATE_SLOWNESS_OF_SERIAL
1057c478bd9Sstevel@tonic-gate /* The speed of a serial device.  */
1067c478bd9Sstevel@tonic-gate static unsigned int serial_speed;
1077c478bd9Sstevel@tonic-gate #endif /* SIMULATE_SLOWNESS_OF_SERIAL */
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate /* The main entry point into this mess. */
1107c478bd9Sstevel@tonic-gate int
grub_stage2(void)1117c478bd9Sstevel@tonic-gate grub_stage2 (void)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate   /* These need to be static, because they survive our stack transitions. */
1147c478bd9Sstevel@tonic-gate   static int status = 0;
1157c478bd9Sstevel@tonic-gate   static char *realstack;
1167c478bd9Sstevel@tonic-gate   char *scratch, *simstack;
1177c478bd9Sstevel@tonic-gate   int i;
1187c478bd9Sstevel@tonic-gate 
1191b8adde7SWilliam Kucharski   auto void doit (void);
1201b8adde7SWilliam Kucharski 
1217c478bd9Sstevel@tonic-gate   /* We need a nested function so that we get a clean stack frame,
1227c478bd9Sstevel@tonic-gate      regardless of how the code is optimized. */
1231b8adde7SWilliam Kucharski   void doit ()
1241b8adde7SWilliam Kucharski     {
1251b8adde7SWilliam Kucharski       /* Make sure our stack lives in the simulated memory area. */
1261b8adde7SWilliam Kucharski       asm volatile ("movl %%esp, %0\n\tmovl %1, %%esp\n"
1271b8adde7SWilliam Kucharski 		    : "=&r" (realstack) : "r" (simstack));
1281b8adde7SWilliam Kucharski 
1291b8adde7SWilliam Kucharski       /* Do a setjmp here for the stop command.  */
1301b8adde7SWilliam Kucharski       if (! setjmp (env_for_exit))
1311b8adde7SWilliam Kucharski 	{
1321b8adde7SWilliam Kucharski 	  /* Actually enter the generic stage2 code.  */
1331b8adde7SWilliam Kucharski 	  status = 0;
1341b8adde7SWilliam Kucharski 	  init_bios_info ();
1351b8adde7SWilliam Kucharski 	}
1361b8adde7SWilliam Kucharski       else
1371b8adde7SWilliam Kucharski 	{
1381b8adde7SWilliam Kucharski 	  /* If ERRNUM is non-zero, then set STATUS to non-zero.  */
1391b8adde7SWilliam Kucharski 	  if (errnum)
1401b8adde7SWilliam Kucharski 	    status = 1;
1411b8adde7SWilliam Kucharski 	}
1421b8adde7SWilliam Kucharski 
1431b8adde7SWilliam Kucharski       /* Replace our stack before we use any local variables. */
1441b8adde7SWilliam Kucharski       asm volatile ("movl %0, %%esp\n" : : "r" (realstack));
1451b8adde7SWilliam Kucharski     }
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate   assert (grub_scratch_mem == 0);
1487c478bd9Sstevel@tonic-gate   scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);
1497c478bd9Sstevel@tonic-gate   assert (scratch);
1507c478bd9Sstevel@tonic-gate   grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate   /* FIXME: simulate the memory holes using mprot, if available. */
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate   assert (disks == 0);
1557c478bd9Sstevel@tonic-gate   disks = malloc (NUM_DISKS * sizeof (*disks));
1567c478bd9Sstevel@tonic-gate   assert (disks);
1577c478bd9Sstevel@tonic-gate   /* Initialize DISKS.  */
1587c478bd9Sstevel@tonic-gate   for (i = 0; i < NUM_DISKS; i++)
1597c478bd9Sstevel@tonic-gate     disks[i].flags = -1;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate   if (! init_device_map (&device_map, device_map_file, floppy_disks))
1627c478bd9Sstevel@tonic-gate     return 1;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate   /* Check some invariants. */
1657c478bd9Sstevel@tonic-gate   assert ((SCRATCHSEG << 4) == SCRATCHADDR);
1667c478bd9Sstevel@tonic-gate   assert ((BUFFERSEG << 4) == BUFFERADDR);
1677c478bd9Sstevel@tonic-gate   assert (BUFFERADDR + BUFFERLEN == SCRATCHADDR);
1687c478bd9Sstevel@tonic-gate   assert (FSYS_BUF % 16 == 0);
1697c478bd9Sstevel@tonic-gate   assert (FSYS_BUF + FSYS_BUFLEN == BUFFERADDR);
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate #ifdef HAVE_LIBCURSES
1727c478bd9Sstevel@tonic-gate   /* Get into char-at-a-time mode. */
1737c478bd9Sstevel@tonic-gate   if (use_curses)
1747c478bd9Sstevel@tonic-gate     {
1757c478bd9Sstevel@tonic-gate       initscr ();
1767c478bd9Sstevel@tonic-gate       cbreak ();
1777c478bd9Sstevel@tonic-gate       noecho ();
1787c478bd9Sstevel@tonic-gate       nonl ();
1797c478bd9Sstevel@tonic-gate       scrollok (stdscr, TRUE);
1807c478bd9Sstevel@tonic-gate       keypad (stdscr, TRUE);
1817c478bd9Sstevel@tonic-gate       wtimeout (stdscr, 100);
1827c478bd9Sstevel@tonic-gate       signal (SIGWINCH, SIG_IGN);
1837c478bd9Sstevel@tonic-gate     }
1847c478bd9Sstevel@tonic-gate #endif
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate   /* Make sure that actual writing is done.  */
1877c478bd9Sstevel@tonic-gate   sync ();
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate   /* Set our stack, and go for it. */
1907c478bd9Sstevel@tonic-gate   simstack = (char *) PROTSTACKINIT;
1917c478bd9Sstevel@tonic-gate   doit ();
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate   /* I don't know if this is necessary really.  */
1947c478bd9Sstevel@tonic-gate   sync ();
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate #ifdef HAVE_LIBCURSES
1977c478bd9Sstevel@tonic-gate   if (use_curses)
1987c478bd9Sstevel@tonic-gate     endwin ();
1997c478bd9Sstevel@tonic-gate #endif
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate   /* Close off the file descriptors we used. */
2027c478bd9Sstevel@tonic-gate   for (i = 0; i < NUM_DISKS; i ++)
2037c478bd9Sstevel@tonic-gate     if (disks[i].flags != -1)
2047c478bd9Sstevel@tonic-gate       {
2057c478bd9Sstevel@tonic-gate #ifdef __linux__
2067c478bd9Sstevel@tonic-gate 	/* In Linux, invalidate the buffer cache. In other OSes, reboot
2077c478bd9Sstevel@tonic-gate 	   is one of the solutions...  */
2087c478bd9Sstevel@tonic-gate 	ioctl (disks[i].flags, BLKFLSBUF, 0);
2097c478bd9Sstevel@tonic-gate #elif defined(__sun)
2107c478bd9Sstevel@tonic-gate 	/* FIXME */
2117c478bd9Sstevel@tonic-gate #else
2127c478bd9Sstevel@tonic-gate # warning "In your operating system, the buffer cache will not be flushed."
2137c478bd9Sstevel@tonic-gate #endif
2147c478bd9Sstevel@tonic-gate 	close (disks[i].flags);
2157c478bd9Sstevel@tonic-gate       }
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate   if (serial_fd >= 0)
2187c478bd9Sstevel@tonic-gate     close (serial_fd);
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate   /* Release memory. */
2217c478bd9Sstevel@tonic-gate   restore_device_map (device_map);
2227c478bd9Sstevel@tonic-gate   device_map = 0;
2237c478bd9Sstevel@tonic-gate   free (disks);
2247c478bd9Sstevel@tonic-gate   disks = 0;
2257c478bd9Sstevel@tonic-gate   free (scratch);
2267c478bd9Sstevel@tonic-gate   grub_scratch_mem = 0;
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate   if (serial_device)
2297c478bd9Sstevel@tonic-gate     free (serial_device);
2307c478bd9Sstevel@tonic-gate   serial_device = 0;
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate   /* Ahh... at last we're ready to return to caller. */
2337c478bd9Sstevel@tonic-gate   return status;
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate /* Assign DRIVE to a device name DEVICE.  */
2377c478bd9Sstevel@tonic-gate void
assign_device_name(int drive,const char * device)2387c478bd9Sstevel@tonic-gate assign_device_name (int drive, const char *device)
2397c478bd9Sstevel@tonic-gate {
2407c478bd9Sstevel@tonic-gate   /* If DRIVE is already assigned, free it.  */
2417c478bd9Sstevel@tonic-gate   if (device_map[drive])
2427c478bd9Sstevel@tonic-gate     free (device_map[drive]);
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate   /* If the old one is already opened, close it.  */
2457c478bd9Sstevel@tonic-gate   if (disks[drive].flags != -1)
2467c478bd9Sstevel@tonic-gate     {
2477c478bd9Sstevel@tonic-gate       close (disks[drive].flags);
2487c478bd9Sstevel@tonic-gate       disks[drive].flags = -1;
2497c478bd9Sstevel@tonic-gate     }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate   /* Assign DRIVE to DEVICE.  */
2527c478bd9Sstevel@tonic-gate   if (! device)
2537c478bd9Sstevel@tonic-gate     device_map[drive] = 0;
2547c478bd9Sstevel@tonic-gate   else
2557c478bd9Sstevel@tonic-gate     device_map[drive] = strdup (device);
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate void
stop(void)2597c478bd9Sstevel@tonic-gate stop (void)
2607c478bd9Sstevel@tonic-gate {
2617c478bd9Sstevel@tonic-gate #ifdef HAVE_LIBCURSES
2627c478bd9Sstevel@tonic-gate   if (use_curses)
2637c478bd9Sstevel@tonic-gate     endwin ();
2647c478bd9Sstevel@tonic-gate #endif
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate   /* Jump to doit.  */
2677c478bd9Sstevel@tonic-gate   longjmp (env_for_exit, 1);
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate void
grub_reboot(void)2717c478bd9Sstevel@tonic-gate grub_reboot (void)
2727c478bd9Sstevel@tonic-gate {
2737c478bd9Sstevel@tonic-gate   stop ();
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate void
grub_halt(int no_apm)2777c478bd9Sstevel@tonic-gate grub_halt (int no_apm)
2787c478bd9Sstevel@tonic-gate {
2797c478bd9Sstevel@tonic-gate   stop ();
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate /* calls for direct boot-loader chaining */
2837c478bd9Sstevel@tonic-gate void
chain_stage1(unsigned long segment,unsigned long offset,unsigned long part_table_addr)2847c478bd9Sstevel@tonic-gate chain_stage1 (unsigned long segment, unsigned long offset,
2857c478bd9Sstevel@tonic-gate 	      unsigned long part_table_addr)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate   stop ();
2887c478bd9Sstevel@tonic-gate }
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate void
chain_stage2(unsigned long segment,unsigned long offset,int second_sector)2927c478bd9Sstevel@tonic-gate chain_stage2 (unsigned long segment, unsigned long offset, int second_sector)
2937c478bd9Sstevel@tonic-gate {
2947c478bd9Sstevel@tonic-gate   stop ();
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate /* do some funky stuff, then boot linux */
2997c478bd9Sstevel@tonic-gate void
linux_boot(void)3007c478bd9Sstevel@tonic-gate linux_boot (void)
3017c478bd9Sstevel@tonic-gate {
3027c478bd9Sstevel@tonic-gate   stop ();
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate /* For bzImage kernels. */
3077c478bd9Sstevel@tonic-gate void
big_linux_boot(void)3087c478bd9Sstevel@tonic-gate big_linux_boot (void)
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate   stop ();
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate /* booting a multiboot executable */
3157c478bd9Sstevel@tonic-gate void
multi_boot(int start,int mb_info)3167c478bd9Sstevel@tonic-gate multi_boot (int start, int mb_info)
3177c478bd9Sstevel@tonic-gate {
3187c478bd9Sstevel@tonic-gate   stop ();
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate /* sets it to linear or wired A20 operation */
3227c478bd9Sstevel@tonic-gate void
gateA20(int linear)3237c478bd9Sstevel@tonic-gate gateA20 (int linear)
3247c478bd9Sstevel@tonic-gate {
3257c478bd9Sstevel@tonic-gate   /* Nothing to do in the simulator. */
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate /* Set up the int15 handler.  */
3297c478bd9Sstevel@tonic-gate void
set_int15_handler(void)3307c478bd9Sstevel@tonic-gate set_int15_handler (void)
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate   /* Nothing to do in the simulator.  */
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate /* Restore the original int15 handler.  */
3367c478bd9Sstevel@tonic-gate void
unset_int15_handler(void)3377c478bd9Sstevel@tonic-gate unset_int15_handler (void)
3387c478bd9Sstevel@tonic-gate {
3397c478bd9Sstevel@tonic-gate   /* Nothing to do in the simulator.  */
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate /* The key map.  */
3437c478bd9Sstevel@tonic-gate unsigned short bios_key_map[KEY_MAP_SIZE + 1];
3447c478bd9Sstevel@tonic-gate unsigned short ascii_key_map[KEY_MAP_SIZE + 1];
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate /* Copy MAP to the drive map and set up the int13 handler.  */
3477c478bd9Sstevel@tonic-gate void
set_int13_handler(unsigned short * map)3487c478bd9Sstevel@tonic-gate set_int13_handler (unsigned short *map)
3497c478bd9Sstevel@tonic-gate {
3507c478bd9Sstevel@tonic-gate   /* Nothing to do in the simulator.  */
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate int
get_code_end(void)3547c478bd9Sstevel@tonic-gate get_code_end (void)
3557c478bd9Sstevel@tonic-gate {
3567c478bd9Sstevel@tonic-gate   /* Just return a little area for simulation. */
3577c478bd9Sstevel@tonic-gate   return BOOTSEC_LOCATION + (60 * 1024);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate /* memory probe routines */
3627c478bd9Sstevel@tonic-gate int
get_memsize(int type)3637c478bd9Sstevel@tonic-gate get_memsize (int type)
3647c478bd9Sstevel@tonic-gate {
3657c478bd9Sstevel@tonic-gate   if (! type)
3667c478bd9Sstevel@tonic-gate     return CONVENTIONAL_MEMSIZE >> 10;
3677c478bd9Sstevel@tonic-gate   else
3687c478bd9Sstevel@tonic-gate     return EXTENDED_MEMSIZE >> 10;
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate /* get_eisamemsize() :  return packed EISA memory map, lower 16 bits is
3737c478bd9Sstevel@tonic-gate  *		memory between 1M and 16M in 1K parts, upper 16 bits is
3747c478bd9Sstevel@tonic-gate  *		memory above 16M in 64K parts.  If error, return -1.
3757c478bd9Sstevel@tonic-gate  */
3767c478bd9Sstevel@tonic-gate int
get_eisamemsize(void)3777c478bd9Sstevel@tonic-gate get_eisamemsize (void)
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate   return (EXTENDED_MEMSIZE >> 10);
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate #define MMAR_DESC_TYPE_AVAILABLE 1 /* available to OS */
3847c478bd9Sstevel@tonic-gate #define MMAR_DESC_TYPE_RESERVED 2 /* not available */
3857c478bd9Sstevel@tonic-gate #define MMAR_DESC_TYPE_ACPI_RECLAIM 3 /* usable by OS after reading ACPI */
3867c478bd9Sstevel@tonic-gate #define MMAR_DESC_TYPE_ACPI_NVS 4 /* required to save between NVS sessions */
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate #define MMAR_DESC_LENGTH	20
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate /* Fetch the next entry in the memory map and return the continuation
3917c478bd9Sstevel@tonic-gate    value.  DESC is a pointer to the descriptor buffer, and CONT is the
3927c478bd9Sstevel@tonic-gate    previous continuation value (0 to get the first entry in the
3937c478bd9Sstevel@tonic-gate    map).  */
3947c478bd9Sstevel@tonic-gate int
get_mmap_entry(struct mmar_desc * desc,int cont)3957c478bd9Sstevel@tonic-gate get_mmap_entry (struct mmar_desc *desc, int cont)
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate   /* Record the memory map statically.  */
3987c478bd9Sstevel@tonic-gate   static struct mmar_desc desc_table[] =
3997c478bd9Sstevel@tonic-gate   {
4007c478bd9Sstevel@tonic-gate     /* The conventional memory.  */
4017c478bd9Sstevel@tonic-gate     {
4027c478bd9Sstevel@tonic-gate       MMAR_DESC_LENGTH,
4037c478bd9Sstevel@tonic-gate       0,
4047c478bd9Sstevel@tonic-gate       CONVENTIONAL_MEMSIZE,
4057c478bd9Sstevel@tonic-gate       MMAR_DESC_TYPE_AVAILABLE
4067c478bd9Sstevel@tonic-gate     },
4077c478bd9Sstevel@tonic-gate     /* BIOS RAM and ROM (such as video memory).  */
4087c478bd9Sstevel@tonic-gate     {
4097c478bd9Sstevel@tonic-gate       MMAR_DESC_LENGTH,
4107c478bd9Sstevel@tonic-gate       CONVENTIONAL_MEMSIZE,
4117c478bd9Sstevel@tonic-gate       0x100000 - CONVENTIONAL_MEMSIZE,
4127c478bd9Sstevel@tonic-gate       MMAR_DESC_TYPE_RESERVED
4137c478bd9Sstevel@tonic-gate     },
4147c478bd9Sstevel@tonic-gate     /* The extended memory.  */
4157c478bd9Sstevel@tonic-gate     {
4167c478bd9Sstevel@tonic-gate       MMAR_DESC_LENGTH,
4177c478bd9Sstevel@tonic-gate       0x100000,
4187c478bd9Sstevel@tonic-gate       EXTENDED_MEMSIZE,
4197c478bd9Sstevel@tonic-gate       MMAR_DESC_TYPE_AVAILABLE
4207c478bd9Sstevel@tonic-gate     }
4217c478bd9Sstevel@tonic-gate   };
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate   int num = sizeof (desc_table) / sizeof (*desc_table);
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate   if (cont < 0 || cont >= num)
4267c478bd9Sstevel@tonic-gate     {
4277c478bd9Sstevel@tonic-gate       /* Should not happen.  */
4287c478bd9Sstevel@tonic-gate       desc->desc_len = 0;
4297c478bd9Sstevel@tonic-gate     }
4307c478bd9Sstevel@tonic-gate   else
4317c478bd9Sstevel@tonic-gate     {
4327c478bd9Sstevel@tonic-gate       /* Copy the entry.  */
4337c478bd9Sstevel@tonic-gate       *desc = desc_table[cont++];
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate       /* If the next entry exists, return the index.  */
4367c478bd9Sstevel@tonic-gate       if (cont < num)
4377c478bd9Sstevel@tonic-gate 	return cont;
4387c478bd9Sstevel@tonic-gate     }
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate   return 0;
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate /* Track the int13 handler.  */
4447c478bd9Sstevel@tonic-gate void
track_int13(int drive)4457c478bd9Sstevel@tonic-gate track_int13 (int drive)
4467c478bd9Sstevel@tonic-gate {
4477c478bd9Sstevel@tonic-gate   /* Nothing to do in the simulator.  */
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate /* Get the ROM configuration table.  */
4517c478bd9Sstevel@tonic-gate unsigned long
get_rom_config_table(void)4527c478bd9Sstevel@tonic-gate get_rom_config_table (void)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate   return 0;
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate /* Get APM BIOS information.  */
4587c478bd9Sstevel@tonic-gate void
get_apm_info(void)4597c478bd9Sstevel@tonic-gate get_apm_info (void)
4607c478bd9Sstevel@tonic-gate {
4617c478bd9Sstevel@tonic-gate   /* Nothing to do in the simulator.  */
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate /* Get VBE controller information.  */
4657c478bd9Sstevel@tonic-gate int
get_vbe_controller_info(struct vbe_controller * controller)4667c478bd9Sstevel@tonic-gate get_vbe_controller_info (struct vbe_controller *controller)
4677c478bd9Sstevel@tonic-gate {
4687c478bd9Sstevel@tonic-gate   /* Always fails.  */
4697c478bd9Sstevel@tonic-gate   return 0;
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate /* Get VBE mode information.  */
4737c478bd9Sstevel@tonic-gate int
get_vbe_mode_info(int mode_number,struct vbe_mode * mode)4747c478bd9Sstevel@tonic-gate get_vbe_mode_info (int mode_number, struct vbe_mode *mode)
4757c478bd9Sstevel@tonic-gate {
4767c478bd9Sstevel@tonic-gate   /* Always fails.  */
4777c478bd9Sstevel@tonic-gate   return 0;
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate /* Set VBE mode.  */
4817c478bd9Sstevel@tonic-gate int
set_vbe_mode(int mode_number)4827c478bd9Sstevel@tonic-gate set_vbe_mode (int mode_number)
4837c478bd9Sstevel@tonic-gate {
4847c478bd9Sstevel@tonic-gate   /* Always fails.  */
4857c478bd9Sstevel@tonic-gate   return 0;
4867c478bd9Sstevel@tonic-gate }
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate /* low-level timing info */
4897c478bd9Sstevel@tonic-gate int
getrtsecs(void)4907c478bd9Sstevel@tonic-gate getrtsecs (void)
4917c478bd9Sstevel@tonic-gate {
4927c478bd9Sstevel@tonic-gate   /* FIXME: exact value is not important, so just return time_t for now. */
4937c478bd9Sstevel@tonic-gate   return time (0);
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate int
currticks(void)4977c478bd9Sstevel@tonic-gate currticks (void)
4987c478bd9Sstevel@tonic-gate {
4997c478bd9Sstevel@tonic-gate   struct timeval tv;
5007c478bd9Sstevel@tonic-gate   long csecs;
5017c478bd9Sstevel@tonic-gate   int ticks_per_csec, ticks_per_usec;
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate   /* Note: 18.2 ticks/sec.  */
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate   /* Get current time.  */
5067c478bd9Sstevel@tonic-gate   gettimeofday (&tv, 0);
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate   /* Compute centiseconds.  */
5097c478bd9Sstevel@tonic-gate   csecs = tv.tv_sec / 10;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate   /* Ticks per centisecond.  */
5127c478bd9Sstevel@tonic-gate   ticks_per_csec = csecs * 182;
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate   /* Ticks per microsecond.  */
5157c478bd9Sstevel@tonic-gate   ticks_per_usec = (((tv.tv_sec - csecs * 10) * 1000000 + tv.tv_usec)
5167c478bd9Sstevel@tonic-gate 		    * 182 / 10000000);
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate   /* Sum them.  */
5197c478bd9Sstevel@tonic-gate   return ticks_per_csec + ticks_per_usec;
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate /* displays an ASCII character.  IBM displays will translate some
5237c478bd9Sstevel@tonic-gate    characters to special graphical ones */
5247c478bd9Sstevel@tonic-gate void
console_putchar(int c)5257c478bd9Sstevel@tonic-gate console_putchar (int c)
5267c478bd9Sstevel@tonic-gate {
5277c478bd9Sstevel@tonic-gate   /* Curses doesn't have VGA fonts.  */
5287c478bd9Sstevel@tonic-gate   switch (c)
5297c478bd9Sstevel@tonic-gate     {
5307c478bd9Sstevel@tonic-gate     case DISP_UL:
5317c478bd9Sstevel@tonic-gate       c = ACS_ULCORNER;
5327c478bd9Sstevel@tonic-gate       break;
5337c478bd9Sstevel@tonic-gate     case DISP_UR:
5347c478bd9Sstevel@tonic-gate       c = ACS_URCORNER;
5357c478bd9Sstevel@tonic-gate       break;
5367c478bd9Sstevel@tonic-gate     case DISP_LL:
5377c478bd9Sstevel@tonic-gate       c = ACS_LLCORNER;
5387c478bd9Sstevel@tonic-gate       break;
5397c478bd9Sstevel@tonic-gate     case DISP_LR:
5407c478bd9Sstevel@tonic-gate       c = ACS_LRCORNER;
5417c478bd9Sstevel@tonic-gate       break;
5427c478bd9Sstevel@tonic-gate     case DISP_HORIZ:
5437c478bd9Sstevel@tonic-gate       c = ACS_HLINE;
5447c478bd9Sstevel@tonic-gate       break;
5457c478bd9Sstevel@tonic-gate     case DISP_VERT:
5467c478bd9Sstevel@tonic-gate       c = ACS_VLINE;
5477c478bd9Sstevel@tonic-gate       break;
5487c478bd9Sstevel@tonic-gate     case DISP_LEFT:
5497c478bd9Sstevel@tonic-gate       c = ACS_LARROW;
5507c478bd9Sstevel@tonic-gate       break;
5517c478bd9Sstevel@tonic-gate     case DISP_RIGHT:
5527c478bd9Sstevel@tonic-gate       c = ACS_RARROW;
5537c478bd9Sstevel@tonic-gate       break;
5547c478bd9Sstevel@tonic-gate     case DISP_UP:
5557c478bd9Sstevel@tonic-gate       c = ACS_UARROW;
5567c478bd9Sstevel@tonic-gate       break;
5577c478bd9Sstevel@tonic-gate     case DISP_DOWN:
5587c478bd9Sstevel@tonic-gate       c = ACS_DARROW;
5597c478bd9Sstevel@tonic-gate       break;
5607c478bd9Sstevel@tonic-gate     default:
5617c478bd9Sstevel@tonic-gate       break;
5627c478bd9Sstevel@tonic-gate     }
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate #ifdef HAVE_LIBCURSES
5657c478bd9Sstevel@tonic-gate   if (use_curses)
5667c478bd9Sstevel@tonic-gate     {
5677c478bd9Sstevel@tonic-gate       /* In ncurses, a newline is treated badly, so we emulate it in our
5687c478bd9Sstevel@tonic-gate 	 own way.  */
5697c478bd9Sstevel@tonic-gate       if (c == '\n')
5707c478bd9Sstevel@tonic-gate 	{
5717c478bd9Sstevel@tonic-gate 	  int x, y;
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	  getyx (stdscr, y, x);
5747c478bd9Sstevel@tonic-gate 	  if (y + 1 == LINES)
5757c478bd9Sstevel@tonic-gate 	    scroll (stdscr);
5767c478bd9Sstevel@tonic-gate 	  else
5777c478bd9Sstevel@tonic-gate 	    move (y + 1, x);
5787c478bd9Sstevel@tonic-gate 	}
5797c478bd9Sstevel@tonic-gate       else if (isprint (c))
5807c478bd9Sstevel@tonic-gate 	{
5817c478bd9Sstevel@tonic-gate 	  int x, y;
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	  getyx (stdscr, y, x);
5847c478bd9Sstevel@tonic-gate 	  if (x + 1 == COLS)
5857c478bd9Sstevel@tonic-gate 	    {
5867c478bd9Sstevel@tonic-gate 	      console_putchar ('\r');
5877c478bd9Sstevel@tonic-gate 	      console_putchar ('\n');
5887c478bd9Sstevel@tonic-gate 	    }
5897c478bd9Sstevel@tonic-gate 	  addch (c | console_current_color);
5907c478bd9Sstevel@tonic-gate 	}
5917c478bd9Sstevel@tonic-gate       else
5927c478bd9Sstevel@tonic-gate 	{
5937c478bd9Sstevel@tonic-gate 	  addch (c);
5947c478bd9Sstevel@tonic-gate 	}
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate #ifdef REFRESH_IMMEDIATELY
5977c478bd9Sstevel@tonic-gate       refresh ();
5987c478bd9Sstevel@tonic-gate #endif
5997c478bd9Sstevel@tonic-gate     }
6007c478bd9Sstevel@tonic-gate   else
6017c478bd9Sstevel@tonic-gate #endif
6027c478bd9Sstevel@tonic-gate     {
6037c478bd9Sstevel@tonic-gate       /* CR is not used in Unix.  */
6047c478bd9Sstevel@tonic-gate       if (c != '\r')
6057c478bd9Sstevel@tonic-gate 	putchar (c);
6067c478bd9Sstevel@tonic-gate     }
6077c478bd9Sstevel@tonic-gate }
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate /* The store for ungetch simulation. This is necessary, because
6107c478bd9Sstevel@tonic-gate    ncurses-1.9.9g is still used in the world and its ungetch is
6117c478bd9Sstevel@tonic-gate    completely broken.  */
6127c478bd9Sstevel@tonic-gate #ifdef HAVE_LIBCURSES
6137c478bd9Sstevel@tonic-gate static int save_char = ERR;
6147c478bd9Sstevel@tonic-gate #endif
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate static int
console_translate_key(int c)6177c478bd9Sstevel@tonic-gate console_translate_key (int c)
6187c478bd9Sstevel@tonic-gate {
6197c478bd9Sstevel@tonic-gate   switch (c)
6207c478bd9Sstevel@tonic-gate     {
6217c478bd9Sstevel@tonic-gate     case KEY_LEFT:
6227c478bd9Sstevel@tonic-gate       return 2;
6237c478bd9Sstevel@tonic-gate     case KEY_RIGHT:
6247c478bd9Sstevel@tonic-gate       return 6;
6257c478bd9Sstevel@tonic-gate     case KEY_UP:
6267c478bd9Sstevel@tonic-gate       return 16;
6277c478bd9Sstevel@tonic-gate     case KEY_DOWN:
6287c478bd9Sstevel@tonic-gate       return 14;
6297c478bd9Sstevel@tonic-gate     case KEY_DC:
6307c478bd9Sstevel@tonic-gate       return 4;
6317c478bd9Sstevel@tonic-gate     case KEY_BACKSPACE:
6327c478bd9Sstevel@tonic-gate       return 8;
6337c478bd9Sstevel@tonic-gate     case KEY_HOME:
6347c478bd9Sstevel@tonic-gate       return 1;
6357c478bd9Sstevel@tonic-gate     case KEY_END:
6367c478bd9Sstevel@tonic-gate       return 5;
6377c478bd9Sstevel@tonic-gate     case KEY_PPAGE:
6387c478bd9Sstevel@tonic-gate       return 7;
6397c478bd9Sstevel@tonic-gate     case KEY_NPAGE:
6407c478bd9Sstevel@tonic-gate       return 3;
6417c478bd9Sstevel@tonic-gate     default:
6427c478bd9Sstevel@tonic-gate       break;
6437c478bd9Sstevel@tonic-gate     }
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate   return c;
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate /* like 'getkey', but doesn't wait, returns -1 if nothing available */
6497c478bd9Sstevel@tonic-gate int
console_checkkey(void)6507c478bd9Sstevel@tonic-gate console_checkkey (void)
6517c478bd9Sstevel@tonic-gate {
6527c478bd9Sstevel@tonic-gate #ifdef HAVE_LIBCURSES
6537c478bd9Sstevel@tonic-gate   if (use_curses)
6547c478bd9Sstevel@tonic-gate     {
6557c478bd9Sstevel@tonic-gate       int c;
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate       /* Check for SAVE_CHAR. This should not be true, because this
6587c478bd9Sstevel@tonic-gate 	 means checkkey is called twice continuously.  */
6597c478bd9Sstevel@tonic-gate       if (save_char != ERR)
6607c478bd9Sstevel@tonic-gate 	return save_char;
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate       c = getch ();
6637c478bd9Sstevel@tonic-gate       /* If C is not ERR, then put it back in the input queue.  */
6647c478bd9Sstevel@tonic-gate       if (c != ERR)
6657c478bd9Sstevel@tonic-gate 	save_char = c;
6667c478bd9Sstevel@tonic-gate       return console_translate_key (c);
6677c478bd9Sstevel@tonic-gate     }
6687c478bd9Sstevel@tonic-gate #endif
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate   /* Just pretend they hit the space bar, then read the real key when
6717c478bd9Sstevel@tonic-gate      they call getkey. */
6727c478bd9Sstevel@tonic-gate   return ' ';
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate /* returns packed BIOS/ASCII code */
6767c478bd9Sstevel@tonic-gate int
console_getkey(void)6777c478bd9Sstevel@tonic-gate console_getkey (void)
6787c478bd9Sstevel@tonic-gate {
6797c478bd9Sstevel@tonic-gate   int c;
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate #ifdef HAVE_LIBCURSES
6827c478bd9Sstevel@tonic-gate   if (use_curses)
6837c478bd9Sstevel@tonic-gate     {
6847c478bd9Sstevel@tonic-gate       /* If checkkey has already got a character, then return it.  */
6857c478bd9Sstevel@tonic-gate       if (save_char != ERR)
6867c478bd9Sstevel@tonic-gate 	{
6877c478bd9Sstevel@tonic-gate 	  c = save_char;
6887c478bd9Sstevel@tonic-gate 	  save_char = ERR;
6897c478bd9Sstevel@tonic-gate 	  return console_translate_key (c);
6907c478bd9Sstevel@tonic-gate 	}
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate       wtimeout (stdscr, -1);
6937c478bd9Sstevel@tonic-gate       c = getch ();
6947c478bd9Sstevel@tonic-gate       wtimeout (stdscr, 100);
6957c478bd9Sstevel@tonic-gate     }
6967c478bd9Sstevel@tonic-gate   else
6977c478bd9Sstevel@tonic-gate #endif
6987c478bd9Sstevel@tonic-gate     c = getchar ();
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate   /* Quit if we get EOF. */
7017c478bd9Sstevel@tonic-gate   if (c == -1)
7027c478bd9Sstevel@tonic-gate     stop ();
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate   return console_translate_key (c);
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate /* returns packed values, LSB+1 is x, LSB is y */
7087c478bd9Sstevel@tonic-gate int
console_getxy(void)7097c478bd9Sstevel@tonic-gate console_getxy (void)
7107c478bd9Sstevel@tonic-gate {
7117c478bd9Sstevel@tonic-gate   int y, x;
7127c478bd9Sstevel@tonic-gate #ifdef HAVE_LIBCURSES
7137c478bd9Sstevel@tonic-gate   if (use_curses)
7147c478bd9Sstevel@tonic-gate     getyx (stdscr, y, x);
7157c478bd9Sstevel@tonic-gate   else
7167c478bd9Sstevel@tonic-gate #endif
7177c478bd9Sstevel@tonic-gate   y = x = 0;
7187c478bd9Sstevel@tonic-gate   return (x << 8) | (y & 0xff);
7197c478bd9Sstevel@tonic-gate }
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate void
console_gotoxy(int x,int y)7227c478bd9Sstevel@tonic-gate console_gotoxy (int x, int y)
7237c478bd9Sstevel@tonic-gate {
7247c478bd9Sstevel@tonic-gate #ifdef HAVE_LIBCURSES
7257c478bd9Sstevel@tonic-gate   if (use_curses)
7267c478bd9Sstevel@tonic-gate     move (y, x);
7277c478bd9Sstevel@tonic-gate #endif
7287c478bd9Sstevel@tonic-gate }
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate /* low-level character I/O */
7317c478bd9Sstevel@tonic-gate void
console_cls(void)7327c478bd9Sstevel@tonic-gate console_cls (void)
7337c478bd9Sstevel@tonic-gate {
7347c478bd9Sstevel@tonic-gate #ifdef HAVE_LIBCURSES
7357c478bd9Sstevel@tonic-gate   if (use_curses)
7367c478bd9Sstevel@tonic-gate     clear ();
7377c478bd9Sstevel@tonic-gate #endif
7387c478bd9Sstevel@tonic-gate }
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate void
console_setcolorstate(color_state state)7417c478bd9Sstevel@tonic-gate console_setcolorstate (color_state state)
7427c478bd9Sstevel@tonic-gate {
7437c478bd9Sstevel@tonic-gate   console_current_color =
7447c478bd9Sstevel@tonic-gate     (state == COLOR_STATE_HIGHLIGHT) ? A_REVERSE : A_NORMAL;
7457c478bd9Sstevel@tonic-gate }
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate void
console_setcolor(int normal_color,int highlight_color)7487c478bd9Sstevel@tonic-gate console_setcolor (int normal_color, int highlight_color)
7497c478bd9Sstevel@tonic-gate {
7507c478bd9Sstevel@tonic-gate   /* Nothing to do.  */
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate int
console_setcursor(int on)7547c478bd9Sstevel@tonic-gate console_setcursor (int on)
7557c478bd9Sstevel@tonic-gate {
7567c478bd9Sstevel@tonic-gate   return 1;
7577c478bd9Sstevel@tonic-gate }
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate /* Low-level disk I/O.  Our stubbed version just returns a file
7607c478bd9Sstevel@tonic-gate    descriptor, not the actual geometry. */
7617c478bd9Sstevel@tonic-gate int
get_diskinfo(int drive,struct geometry * geometry)7627c478bd9Sstevel@tonic-gate get_diskinfo (int drive, struct geometry *geometry)
7637c478bd9Sstevel@tonic-gate {
7647c478bd9Sstevel@tonic-gate   /* FIXME: this function is truly horrid.  We try opening the device,
7657c478bd9Sstevel@tonic-gate      then severely abuse the GEOMETRY->flags field to pass a file
7667c478bd9Sstevel@tonic-gate      descriptor to biosdisk.  Thank God nobody's looking at this comment,
7677c478bd9Sstevel@tonic-gate      or my reputation would be ruined. --Gord */
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate   /* See if we have a cached device. */
7707c478bd9Sstevel@tonic-gate   if (disks[drive].flags == -1)
7717c478bd9Sstevel@tonic-gate     {
7727c478bd9Sstevel@tonic-gate       /* The unpartitioned device name: /dev/XdX */
7737c478bd9Sstevel@tonic-gate       char *devname = device_map[drive];
7747c478bd9Sstevel@tonic-gate       char buf[512];
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate       if (! devname)
7777c478bd9Sstevel@tonic-gate 	return -1;
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate       if (verbose)
7807c478bd9Sstevel@tonic-gate 	grub_printf ("Attempt to open drive 0x%x (%s)\n",
7817c478bd9Sstevel@tonic-gate 		     drive, devname);
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate       /* Open read/write, or read-only if that failed. */
7847c478bd9Sstevel@tonic-gate       if (! read_only)
7857c478bd9Sstevel@tonic-gate 	disks[drive].flags = open (devname, O_RDWR);
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate       if (disks[drive].flags == -1)
7887c478bd9Sstevel@tonic-gate 	{
7897c478bd9Sstevel@tonic-gate 	  if (read_only || errno == EACCES || errno == EROFS || errno == EPERM)
7907c478bd9Sstevel@tonic-gate 	    {
7917c478bd9Sstevel@tonic-gate 	      disks[drive].flags = open (devname, O_RDONLY);
7927c478bd9Sstevel@tonic-gate 	      if (disks[drive].flags == -1)
7937c478bd9Sstevel@tonic-gate 		{
7947c478bd9Sstevel@tonic-gate 		  assign_device_name (drive, 0);
7957c478bd9Sstevel@tonic-gate 		  return -1;
7967c478bd9Sstevel@tonic-gate 		}
7977c478bd9Sstevel@tonic-gate 	    }
7987c478bd9Sstevel@tonic-gate 	  else
7997c478bd9Sstevel@tonic-gate 	    {
8007c478bd9Sstevel@tonic-gate 	      assign_device_name (drive, 0);
8017c478bd9Sstevel@tonic-gate 	      return -1;
8027c478bd9Sstevel@tonic-gate 	    }
8037c478bd9Sstevel@tonic-gate 	}
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate       /* Attempt to read the first sector.  */
8067c478bd9Sstevel@tonic-gate       if (read (disks[drive].flags, buf, 512) != 512)
8077c478bd9Sstevel@tonic-gate 	{
8087c478bd9Sstevel@tonic-gate 	  close (disks[drive].flags);
8097c478bd9Sstevel@tonic-gate 	  disks[drive].flags = -1;
8107c478bd9Sstevel@tonic-gate 	  assign_device_name (drive, 0);
8117c478bd9Sstevel@tonic-gate 	  return -1;
8127c478bd9Sstevel@tonic-gate 	}
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate       if (disks[drive].flags != -1)
8157c478bd9Sstevel@tonic-gate 	get_drive_geometry (&disks[drive], device_map, drive);
8167c478bd9Sstevel@tonic-gate     }
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate   if (disks[drive].flags == -1)
8197c478bd9Sstevel@tonic-gate     return -1;
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate #ifdef __linux__
8227c478bd9Sstevel@tonic-gate   /* In Linux, invalidate the buffer cache, so that left overs
8237c478bd9Sstevel@tonic-gate      from other program in the cache are flushed and seen by us */
8247c478bd9Sstevel@tonic-gate   ioctl (disks[drive].flags, BLKFLSBUF, 0);
8257c478bd9Sstevel@tonic-gate #endif
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate   *geometry = disks[drive];
8287c478bd9Sstevel@tonic-gate   return 0;
8297c478bd9Sstevel@tonic-gate }
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate /* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
8327c478bd9Sstevel@tonic-gate    error occurs, otherwise return LEN.  */
8337c478bd9Sstevel@tonic-gate static int
nread(int fd,char * buf,size_t len)8347c478bd9Sstevel@tonic-gate nread (int fd, char *buf, size_t len)
8357c478bd9Sstevel@tonic-gate {
8367c478bd9Sstevel@tonic-gate   int size = len;
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate   while (len)
8397c478bd9Sstevel@tonic-gate     {
8407c478bd9Sstevel@tonic-gate       int ret = read (fd, buf, len);
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate       if (ret <= 0)
8437c478bd9Sstevel@tonic-gate 	{
8447c478bd9Sstevel@tonic-gate 	  if (errno == EINTR)
8457c478bd9Sstevel@tonic-gate 	    continue;
8467c478bd9Sstevel@tonic-gate 	  else
8477c478bd9Sstevel@tonic-gate 	    return ret;
8487c478bd9Sstevel@tonic-gate 	}
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate       len -= ret;
8517c478bd9Sstevel@tonic-gate       buf += ret;
8527c478bd9Sstevel@tonic-gate     }
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate   return size;
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate /* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
8587c478bd9Sstevel@tonic-gate    error occurs, otherwise return LEN.  */
8597c478bd9Sstevel@tonic-gate static int
nwrite(int fd,char * buf,size_t len)8607c478bd9Sstevel@tonic-gate nwrite (int fd, char *buf, size_t len)
8617c478bd9Sstevel@tonic-gate {
8627c478bd9Sstevel@tonic-gate   int size = len;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate   while (len)
8657c478bd9Sstevel@tonic-gate     {
8667c478bd9Sstevel@tonic-gate       int ret = write (fd, buf, len);
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate       if (ret <= 0)
8697c478bd9Sstevel@tonic-gate 	{
8707c478bd9Sstevel@tonic-gate 	  if (errno == EINTR)
8717c478bd9Sstevel@tonic-gate 	    continue;
8727c478bd9Sstevel@tonic-gate 	  else
8737c478bd9Sstevel@tonic-gate 	    return ret;
8747c478bd9Sstevel@tonic-gate 	}
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate       len -= ret;
8777c478bd9Sstevel@tonic-gate       buf += ret;
8787c478bd9Sstevel@tonic-gate     }
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate   return size;
8817c478bd9Sstevel@tonic-gate }
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate /* Dump BUF in the format of hexadecimal numbers.  */
8847c478bd9Sstevel@tonic-gate static void
hex_dump(void * buf,size_t size)8857c478bd9Sstevel@tonic-gate hex_dump (void *buf, size_t size)
8867c478bd9Sstevel@tonic-gate {
8877c478bd9Sstevel@tonic-gate   /* FIXME: How to determine which length is readable?  */
8887c478bd9Sstevel@tonic-gate #define MAX_COLUMN	70
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate   /* use unsigned char for numerical computations */
8917c478bd9Sstevel@tonic-gate   unsigned char *ptr = buf;
8927c478bd9Sstevel@tonic-gate   /* count the width of the line */
8937c478bd9Sstevel@tonic-gate   int column = 0;
8947c478bd9Sstevel@tonic-gate   /* how many bytes written */
8957c478bd9Sstevel@tonic-gate   int count = 0;
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate   while (size > 0)
8987c478bd9Sstevel@tonic-gate     {
8997c478bd9Sstevel@tonic-gate       /* high 4 bits */
9007c478bd9Sstevel@tonic-gate       int hi = *ptr >> 4;
9017c478bd9Sstevel@tonic-gate       /* low 4 bits */
9027c478bd9Sstevel@tonic-gate       int low = *ptr & 0xf;
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate       /* grub_printf does not handle prefix number, such as %2x, so
9057c478bd9Sstevel@tonic-gate 	 format the number by hand...  */
9067c478bd9Sstevel@tonic-gate       grub_printf ("%x%x", hi, low);
9077c478bd9Sstevel@tonic-gate       column += 2;
9087c478bd9Sstevel@tonic-gate       count++;
9097c478bd9Sstevel@tonic-gate       ptr++;
9107c478bd9Sstevel@tonic-gate       size--;
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate       /* Insert space or newline with the interval 4 bytes.  */
9137c478bd9Sstevel@tonic-gate       if (size != 0 && (count % 4) == 0)
9147c478bd9Sstevel@tonic-gate 	{
9157c478bd9Sstevel@tonic-gate 	  if (column < MAX_COLUMN)
9167c478bd9Sstevel@tonic-gate 	    {
9177c478bd9Sstevel@tonic-gate 	      grub_printf (" ");
9187c478bd9Sstevel@tonic-gate 	      column++;
9197c478bd9Sstevel@tonic-gate 	    }
9207c478bd9Sstevel@tonic-gate 	  else
9217c478bd9Sstevel@tonic-gate 	    {
9227c478bd9Sstevel@tonic-gate 	      grub_printf ("\n");
9237c478bd9Sstevel@tonic-gate 	      column = 0;
9247c478bd9Sstevel@tonic-gate 	    }
9257c478bd9Sstevel@tonic-gate 	}
9267c478bd9Sstevel@tonic-gate     }
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate   /* Add a newline at the end for readability.  */
9297c478bd9Sstevel@tonic-gate   grub_printf ("\n");
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate int
biosdisk(int subfunc,int drive,struct geometry * geometry,unsigned long long sector,int nsec,int segment)9337c478bd9Sstevel@tonic-gate biosdisk (int subfunc, int drive, struct geometry *geometry,
934*9890706eSHans Rosenfeld 	  unsigned long long sector, int nsec, int segment)
9357c478bd9Sstevel@tonic-gate {
9367c478bd9Sstevel@tonic-gate   char *buf;
9377c478bd9Sstevel@tonic-gate   int fd = geometry->flags;
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate   /* Get the file pointer from the geometry, and make sure it matches. */
9407c478bd9Sstevel@tonic-gate   if (fd == -1 || fd != disks[drive].flags)
9417c478bd9Sstevel@tonic-gate     return BIOSDISK_ERROR_GEOMETRY;
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate   /* Seek to the specified location. */
9447c478bd9Sstevel@tonic-gate #if defined(__linux__) && (!defined(__GLIBC__) || \
9457c478bd9Sstevel@tonic-gate 	((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
9467c478bd9Sstevel@tonic-gate   /* Maybe libc doesn't have large file support.  */
9477c478bd9Sstevel@tonic-gate   {
9487c478bd9Sstevel@tonic-gate     loff_t offset, result;
9497c478bd9Sstevel@tonic-gate     static int _llseek (uint filedes, ulong hi, ulong lo,
9507c478bd9Sstevel@tonic-gate 			loff_t *res, uint wh);
9517c478bd9Sstevel@tonic-gate     _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
9527c478bd9Sstevel@tonic-gate 	       loff_t *, res, uint, wh);
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate     offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
9557c478bd9Sstevel@tonic-gate     if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
9567c478bd9Sstevel@tonic-gate       return -1;
9577c478bd9Sstevel@tonic-gate   }
9587c478bd9Sstevel@tonic-gate #else
9597c478bd9Sstevel@tonic-gate   {
9607c478bd9Sstevel@tonic-gate     off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate     if (lseek (fd, offset, SEEK_SET) != offset)
9637c478bd9Sstevel@tonic-gate       return -1;
9647c478bd9Sstevel@tonic-gate   }
9657c478bd9Sstevel@tonic-gate #endif
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate   buf = (char *) (segment << 4);
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate   switch (subfunc)
9707c478bd9Sstevel@tonic-gate     {
9717c478bd9Sstevel@tonic-gate     case BIOSDISK_READ:
9727c478bd9Sstevel@tonic-gate #ifdef __linux__
9737c478bd9Sstevel@tonic-gate       if (sector == 0 && nsec > 1)
9747c478bd9Sstevel@tonic-gate 	{
9757c478bd9Sstevel@tonic-gate 	  /* Work around a bug in linux's ez remapping.  Linux remaps all
9767c478bd9Sstevel@tonic-gate 	     sectors that are read together with the MBR in one read.  It
9777c478bd9Sstevel@tonic-gate 	     should only remap the MBR, so we split the read in two
9787c478bd9Sstevel@tonic-gate 	     parts. -jochen  */
9797c478bd9Sstevel@tonic-gate 	  if (nread (fd, buf, SECTOR_SIZE) != SECTOR_SIZE)
9807c478bd9Sstevel@tonic-gate 	    return -1;
9817c478bd9Sstevel@tonic-gate 	  buf += SECTOR_SIZE;
9827c478bd9Sstevel@tonic-gate 	  nsec--;
9837c478bd9Sstevel@tonic-gate 	}
9847c478bd9Sstevel@tonic-gate #endif
9857c478bd9Sstevel@tonic-gate       if (nread (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
9867c478bd9Sstevel@tonic-gate 	return -1;
9877c478bd9Sstevel@tonic-gate       break;
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate     case BIOSDISK_WRITE:
9907c478bd9Sstevel@tonic-gate       if (verbose)
9917c478bd9Sstevel@tonic-gate 	{
992342440ecSPrasad Singamsetty 	  grub_printf ("Write %d sectors starting from %u sector"
9937c478bd9Sstevel@tonic-gate 		       " to drive 0x%x (%s)\n",
9947c478bd9Sstevel@tonic-gate 		       nsec, sector, drive, device_map[drive]);
9957c478bd9Sstevel@tonic-gate 	  hex_dump (buf, nsec * SECTOR_SIZE);
9967c478bd9Sstevel@tonic-gate 	}
9977c478bd9Sstevel@tonic-gate       if (! read_only)
9987c478bd9Sstevel@tonic-gate 	if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
9997c478bd9Sstevel@tonic-gate 	  return -1;
10007c478bd9Sstevel@tonic-gate       break;
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate     default:
10037c478bd9Sstevel@tonic-gate       grub_printf ("unknown subfunc %d\n", subfunc);
10047c478bd9Sstevel@tonic-gate       break;
10057c478bd9Sstevel@tonic-gate     }
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate   return 0;
10087c478bd9Sstevel@tonic-gate }
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate void
stop_floppy(void)10127c478bd9Sstevel@tonic-gate stop_floppy (void)
10137c478bd9Sstevel@tonic-gate {
10147c478bd9Sstevel@tonic-gate   /* NOTUSED */
10157c478bd9Sstevel@tonic-gate }
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate /* Fetch a key from a serial device.  */
10187c478bd9Sstevel@tonic-gate int
serial_hw_fetch(void)10197c478bd9Sstevel@tonic-gate serial_hw_fetch (void)
10207c478bd9Sstevel@tonic-gate {
10217c478bd9Sstevel@tonic-gate   fd_set fds;
10227c478bd9Sstevel@tonic-gate   struct timeval to;
10237c478bd9Sstevel@tonic-gate   char c;
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate   /* Wait only for the serial device.  */
10267c478bd9Sstevel@tonic-gate   FD_ZERO (&fds);
10277c478bd9Sstevel@tonic-gate   FD_SET (serial_fd, &fds);
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate   to.tv_sec = 0;
10307c478bd9Sstevel@tonic-gate   to.tv_usec = 0;
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate   if (select (serial_fd + 1, &fds, 0, 0, &to) > 0)
10337c478bd9Sstevel@tonic-gate     {
10347c478bd9Sstevel@tonic-gate       if (nread (serial_fd, &c, 1) != 1)
10357c478bd9Sstevel@tonic-gate 	stop ();
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate       return c;
10387c478bd9Sstevel@tonic-gate     }
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate   return -1;
10417c478bd9Sstevel@tonic-gate }
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate /* Put a character to a serial device.  */
10447c478bd9Sstevel@tonic-gate void
serial_hw_put(int c)10457c478bd9Sstevel@tonic-gate serial_hw_put (int c)
10467c478bd9Sstevel@tonic-gate {
10477c478bd9Sstevel@tonic-gate   char ch = (char) c;
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate   if (nwrite (serial_fd, &ch, 1) != 1)
10507c478bd9Sstevel@tonic-gate     stop ();
10517c478bd9Sstevel@tonic-gate }
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate void
serial_hw_delay(void)10547c478bd9Sstevel@tonic-gate serial_hw_delay (void)
10557c478bd9Sstevel@tonic-gate {
10567c478bd9Sstevel@tonic-gate #ifdef SIMULATE_SLOWNESS_OF_SERIAL
10577c478bd9Sstevel@tonic-gate   struct timeval otv, tv;
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate   gettimeofday (&otv, 0);
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate   while (1)
10627c478bd9Sstevel@tonic-gate     {
10637c478bd9Sstevel@tonic-gate       long delta;
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate       gettimeofday (&tv, 0);
10667c478bd9Sstevel@tonic-gate       delta = tv.tv_usec - otv.tv_usec;
10677c478bd9Sstevel@tonic-gate       if (delta < 0)
10687c478bd9Sstevel@tonic-gate 	delta += 1000000;
10697c478bd9Sstevel@tonic-gate 
10707c478bd9Sstevel@tonic-gate       if (delta >= 1000000 / (serial_speed >> 3))
10717c478bd9Sstevel@tonic-gate 	break;
10727c478bd9Sstevel@tonic-gate     }
10737c478bd9Sstevel@tonic-gate #endif /* SIMULATE_SLOWNESS_OF_SERIAL */
10747c478bd9Sstevel@tonic-gate }
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate static speed_t
get_termios_speed(int speed)10777c478bd9Sstevel@tonic-gate get_termios_speed (int speed)
10787c478bd9Sstevel@tonic-gate {
10797c478bd9Sstevel@tonic-gate   switch (speed)
10807c478bd9Sstevel@tonic-gate     {
10817c478bd9Sstevel@tonic-gate     case 2400: return B2400;
10827c478bd9Sstevel@tonic-gate     case 4800: return B4800;
10837c478bd9Sstevel@tonic-gate     case 9600: return B9600;
10847c478bd9Sstevel@tonic-gate     case 19200: return B19200;
10857c478bd9Sstevel@tonic-gate     case 38400: return B38400;
10867c478bd9Sstevel@tonic-gate #ifdef B57600
10877c478bd9Sstevel@tonic-gate     case 57600: return B57600;
10887c478bd9Sstevel@tonic-gate #endif
10897c478bd9Sstevel@tonic-gate #ifdef B115200
10907c478bd9Sstevel@tonic-gate     case 115200: return B115200;
10917c478bd9Sstevel@tonic-gate #endif
10927c478bd9Sstevel@tonic-gate     }
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate   return B0;
10957c478bd9Sstevel@tonic-gate }
10967c478bd9Sstevel@tonic-gate 
10977c478bd9Sstevel@tonic-gate /* Get the port number of the unit UNIT. In the grub shell, this doesn't
10987c478bd9Sstevel@tonic-gate    make sense.  */
10997c478bd9Sstevel@tonic-gate unsigned short
serial_hw_get_port(int unit)11007c478bd9Sstevel@tonic-gate serial_hw_get_port (int unit)
11017c478bd9Sstevel@tonic-gate {
11027c478bd9Sstevel@tonic-gate   return 0;
11037c478bd9Sstevel@tonic-gate }
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate /* Initialize a serial device. In the grub shell, PORT is unused.  */
11067c478bd9Sstevel@tonic-gate int
serial_hw_init(unsigned short port,unsigned int speed,int word_len,int parity,int stop_bit_len)11077c478bd9Sstevel@tonic-gate serial_hw_init (unsigned short port, unsigned int speed,
11087c478bd9Sstevel@tonic-gate 		int word_len, int parity, int stop_bit_len)
11097c478bd9Sstevel@tonic-gate {
11107c478bd9Sstevel@tonic-gate   struct termios termios;
11117c478bd9Sstevel@tonic-gate   speed_t termios_speed;
11127c478bd9Sstevel@tonic-gate   int i;
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate   /* Check if the file name is specified.  */
11157c478bd9Sstevel@tonic-gate   if (! serial_device)
11167c478bd9Sstevel@tonic-gate     return 0;
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate   /* If a serial device is already opened, close it first.  */
11197c478bd9Sstevel@tonic-gate   if (serial_fd >= 0)
11207c478bd9Sstevel@tonic-gate     close (serial_fd);
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate   /* Open the device file.  */
11237c478bd9Sstevel@tonic-gate   serial_fd = open (serial_device,
11247c478bd9Sstevel@tonic-gate 		    O_RDWR | O_NOCTTY
11257c478bd9Sstevel@tonic-gate #if defined(O_SYNC)
11267c478bd9Sstevel@tonic-gate 		    /* O_SYNC is used in Linux (and some others?).  */
11277c478bd9Sstevel@tonic-gate 		    | O_SYNC
11287c478bd9Sstevel@tonic-gate #elif defined(O_FSYNC)
11297c478bd9Sstevel@tonic-gate 		    /* O_FSYNC is used in FreeBSD.  */
11307c478bd9Sstevel@tonic-gate 		    | O_FSYNC
11317c478bd9Sstevel@tonic-gate #endif
11327c478bd9Sstevel@tonic-gate 		    );
11337c478bd9Sstevel@tonic-gate   if (serial_fd < 0)
11347c478bd9Sstevel@tonic-gate     return 0;
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate   /* Get the termios parameters.  */
11377c478bd9Sstevel@tonic-gate   if (tcgetattr (serial_fd, &termios))
11387c478bd9Sstevel@tonic-gate     goto fail;
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate   /* Raw mode.  */
11417c478bd9Sstevel@tonic-gate #if defined(__sun)
11427c478bd9Sstevel@tonic-gate   termios.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
11437c478bd9Sstevel@tonic-gate   termios.c_oflag &= ~OPOST;
11447c478bd9Sstevel@tonic-gate   termios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
11457c478bd9Sstevel@tonic-gate   termios.c_cflag &= ~(CSIZE|PARENB);
11467c478bd9Sstevel@tonic-gate   termios.c_cflag |= CS8;
11477c478bd9Sstevel@tonic-gate #else
11487c478bd9Sstevel@tonic-gate   cfmakeraw (&termios);
11497c478bd9Sstevel@tonic-gate #endif
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate   /* Set the speed.  */
11527c478bd9Sstevel@tonic-gate   termios_speed = get_termios_speed (speed);
11537c478bd9Sstevel@tonic-gate   if (termios_speed == B0)
11547c478bd9Sstevel@tonic-gate     goto fail;
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate   cfsetispeed (&termios, termios_speed);
11577c478bd9Sstevel@tonic-gate   cfsetospeed (&termios, termios_speed);
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate   /* Set the word length.  */
11607c478bd9Sstevel@tonic-gate   termios.c_cflag &= ~CSIZE;
11617c478bd9Sstevel@tonic-gate   switch (word_len)
11627c478bd9Sstevel@tonic-gate     {
11637c478bd9Sstevel@tonic-gate     case UART_5BITS_WORD:
11647c478bd9Sstevel@tonic-gate       termios.c_cflag |= CS5;
11657c478bd9Sstevel@tonic-gate       break;
11667c478bd9Sstevel@tonic-gate     case UART_6BITS_WORD:
11677c478bd9Sstevel@tonic-gate       termios.c_cflag |= CS6;
11687c478bd9Sstevel@tonic-gate       break;
11697c478bd9Sstevel@tonic-gate     case UART_7BITS_WORD:
11707c478bd9Sstevel@tonic-gate       termios.c_cflag |= CS7;
11717c478bd9Sstevel@tonic-gate       break;
11727c478bd9Sstevel@tonic-gate     case UART_8BITS_WORD:
11737c478bd9Sstevel@tonic-gate       termios.c_cflag |= CS8;
11747c478bd9Sstevel@tonic-gate       break;
11757c478bd9Sstevel@tonic-gate     default:
11767c478bd9Sstevel@tonic-gate       goto fail;
11777c478bd9Sstevel@tonic-gate     }
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate   /* Set the parity.  */
11807c478bd9Sstevel@tonic-gate   switch (parity)
11817c478bd9Sstevel@tonic-gate     {
11827c478bd9Sstevel@tonic-gate     case UART_NO_PARITY:
11837c478bd9Sstevel@tonic-gate       termios.c_cflag &= ~PARENB;
11847c478bd9Sstevel@tonic-gate       break;
11857c478bd9Sstevel@tonic-gate     case UART_ODD_PARITY:
11867c478bd9Sstevel@tonic-gate       termios.c_cflag |= PARENB;
11877c478bd9Sstevel@tonic-gate       termios.c_cflag |= PARODD;
11887c478bd9Sstevel@tonic-gate       break;
11897c478bd9Sstevel@tonic-gate     case UART_EVEN_PARITY:
11907c478bd9Sstevel@tonic-gate       termios.c_cflag |= PARENB;
11917c478bd9Sstevel@tonic-gate       termios.c_cflag &= ~PARODD;
11927c478bd9Sstevel@tonic-gate       break;
11937c478bd9Sstevel@tonic-gate     default:
11947c478bd9Sstevel@tonic-gate       goto fail;
11957c478bd9Sstevel@tonic-gate     }
11967c478bd9Sstevel@tonic-gate 
11977c478bd9Sstevel@tonic-gate   /* Set the length of stop bit.  */
11987c478bd9Sstevel@tonic-gate   switch (stop_bit_len)
11997c478bd9Sstevel@tonic-gate     {
12007c478bd9Sstevel@tonic-gate     case UART_1_STOP_BIT:
12017c478bd9Sstevel@tonic-gate       termios.c_cflag &= ~CSTOPB;
12027c478bd9Sstevel@tonic-gate       break;
12037c478bd9Sstevel@tonic-gate     case UART_2_STOP_BITS:
12047c478bd9Sstevel@tonic-gate       termios.c_cflag |= CSTOPB;
12057c478bd9Sstevel@tonic-gate       break;
12067c478bd9Sstevel@tonic-gate     default:
12077c478bd9Sstevel@tonic-gate       goto fail;
12087c478bd9Sstevel@tonic-gate     }
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate   /* Set the parameters.  */
12117c478bd9Sstevel@tonic-gate   if (tcsetattr (serial_fd, TCSANOW, &termios))
12127c478bd9Sstevel@tonic-gate     goto fail;
12137c478bd9Sstevel@tonic-gate 
12147c478bd9Sstevel@tonic-gate #ifdef SIMULATE_SLOWNESS_OF_SERIAL
12157c478bd9Sstevel@tonic-gate   serial_speed = speed;
12167c478bd9Sstevel@tonic-gate #endif /* SIMUATE_SLOWNESS_OF_SERIAL */
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate   /* Get rid of the flag TERM_NEED_INIT from the serial terminal.  */
12197c478bd9Sstevel@tonic-gate   for (i = 0; term_table[i].name; i++)
12207c478bd9Sstevel@tonic-gate     {
12217c478bd9Sstevel@tonic-gate       if (strcmp (term_table[i].name, "serial") == 0)
12227c478bd9Sstevel@tonic-gate 	{
12237c478bd9Sstevel@tonic-gate 	  term_table[i].flags &= ~(TERM_NEED_INIT);
12247c478bd9Sstevel@tonic-gate 	  break;
12257c478bd9Sstevel@tonic-gate 	}
12267c478bd9Sstevel@tonic-gate     }
12277c478bd9Sstevel@tonic-gate 
12287c478bd9Sstevel@tonic-gate   return 1;
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate  fail:
12317c478bd9Sstevel@tonic-gate   close (serial_fd);
12327c478bd9Sstevel@tonic-gate   serial_fd = -1;
12337c478bd9Sstevel@tonic-gate   return 0;
12347c478bd9Sstevel@tonic-gate }
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate /* Set the file name of a serial device (or a pty device). This is a
12377c478bd9Sstevel@tonic-gate    function specific to the grub shell.  */
12387c478bd9Sstevel@tonic-gate void
serial_set_device(const char * device)12397c478bd9Sstevel@tonic-gate serial_set_device (const char *device)
12407c478bd9Sstevel@tonic-gate {
12417c478bd9Sstevel@tonic-gate   if (serial_device)
12427c478bd9Sstevel@tonic-gate     free (serial_device);
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate   serial_device = strdup (device);
12457c478bd9Sstevel@tonic-gate }
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate /* There is no difference between console and hercules in the grub shell.  */
12487c478bd9Sstevel@tonic-gate void
hercules_putchar(int c)12497c478bd9Sstevel@tonic-gate hercules_putchar (int c)
12507c478bd9Sstevel@tonic-gate {
12517c478bd9Sstevel@tonic-gate   console_putchar (c);
12527c478bd9Sstevel@tonic-gate }
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate int
hercules_getxy(void)12557c478bd9Sstevel@tonic-gate hercules_getxy (void)
12567c478bd9Sstevel@tonic-gate {
12577c478bd9Sstevel@tonic-gate   return console_getxy ();
12587c478bd9Sstevel@tonic-gate }
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate void
hercules_gotoxy(int x,int y)12617c478bd9Sstevel@tonic-gate hercules_gotoxy (int x, int y)
12627c478bd9Sstevel@tonic-gate {
12637c478bd9Sstevel@tonic-gate   console_gotoxy (x, y);
12647c478bd9Sstevel@tonic-gate }
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate void
hercules_cls(void)12677c478bd9Sstevel@tonic-gate hercules_cls (void)
12687c478bd9Sstevel@tonic-gate {
12697c478bd9Sstevel@tonic-gate   console_cls ();
12707c478bd9Sstevel@tonic-gate }
12717c478bd9Sstevel@tonic-gate 
12727c478bd9Sstevel@tonic-gate void
hercules_setcolorstate(color_state state)12737c478bd9Sstevel@tonic-gate hercules_setcolorstate (color_state state)
12747c478bd9Sstevel@tonic-gate {
12757c478bd9Sstevel@tonic-gate   console_setcolorstate (state);
12767c478bd9Sstevel@tonic-gate }
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate void
hercules_setcolor(int normal_color,int highlight_color)12797c478bd9Sstevel@tonic-gate hercules_setcolor (int normal_color, int highlight_color)
12807c478bd9Sstevel@tonic-gate {
12817c478bd9Sstevel@tonic-gate   console_setcolor (normal_color, highlight_color);
12827c478bd9Sstevel@tonic-gate }
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate int
hercules_setcursor(int on)12857c478bd9Sstevel@tonic-gate hercules_setcursor (int on)
12867c478bd9Sstevel@tonic-gate {
12877c478bd9Sstevel@tonic-gate   return 1;
12887c478bd9Sstevel@tonic-gate }
1289ae115bc7Smrj 
amd64_cpuid_supported(void)1290ae115bc7Smrj uint32_t amd64_cpuid_supported(void)
1291ae115bc7Smrj {
1292ae115bc7Smrj   /* Nothing to do in the simulator. */
1293ae115bc7Smrj 	return (1);
1294ae115bc7Smrj }
1295ae115bc7Smrj 
amd64_cpuid_insn(uint32_t i,void * r)1296ae115bc7Smrj void amd64_cpuid_insn(uint32_t i, void * r)
1297ae115bc7Smrj {
1298ae115bc7Smrj   /* Nothing to do in the simulator. */
1299ae115bc7Smrj }
1300ae115bc7Smrj 
amd64_rdmsr(uint32_t i,uint64_t * p)1301ae115bc7Smrj void amd64_rdmsr(uint32_t i, uint64_t * p)
1302ae115bc7Smrj {
1303ae115bc7Smrj   /* Nothing to do in the simulator. */
1304ae115bc7Smrj }
1305ae115bc7Smrj 
amd64_wrmsr(uint32_t i,const uint64_t * p)1306ae115bc7Smrj void amd64_wrmsr(uint32_t i, const uint64_t * p)
1307ae115bc7Smrj {
1308ae115bc7Smrj   /* Nothing to do in the simulator. */
1309ae115bc7Smrj }
1310ae115bc7Smrj 
get_target_operating_mode(void)1311ae115bc7Smrj int get_target_operating_mode(void)
1312ae115bc7Smrj {
1313ae115bc7Smrj   /* Nothing to do in the simulator. */
1314ae115bc7Smrj 	return (1);
1315ae115bc7Smrj }
1316