⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asmstub.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 2 页
字号:
/* asmstub.c - a version of shared_src/asm.S that works under Unix *//* *  GRUB  --  GRand Unified Bootloader *  Copyright (C) 1999,2000,2001,2002,2004  Free Software Foundation, Inc. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* Try to use glibc's transparant LFS support. */#define _LARGEFILE_SOURCE	1/* lseek becomes synonymous with lseek64.  */#define _FILE_OFFSET_BITS	64/* Simulator entry point. */int grub_stage2 (void);#include <stdlib.h>#include <string.h>#include <ctype.h>#include <assert.h>#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <time.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <setjmp.h>#include <sys/time.h>#include <termios.h>#include <signal.h>#ifdef __linux__# include <sys/ioctl.h>		/* ioctl */# if !defined(__GLIBC__) || \	((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))/* Maybe libc doesn't have large file support.  */#  include <linux/unistd.h>	/* _llseek */# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */# ifndef BLKFLSBUF#  define BLKFLSBUF	_IO (0x12,97)	/* flush buffer cache */# endif /* ! BLKFLSBUF */#endif /* __linux__ *//* We want to prevent any circularararity in our stubs, as well as   libc name clashes. */#define WITHOUT_LIBC_STUBS 1#include <shared.h>#include <device.h>#include <serial.h>#include <term.h>/* Simulated memory sizes. */#define EXTENDED_MEMSIZE (3 * 1024 * 1024)	/* 3MB */#define CONVENTIONAL_MEMSIZE (640 * 1024)	/* 640kB */unsigned long install_partition = 0x20000;unsigned long boot_drive = 0;int saved_entryno = 0;char version_string[] = VERSION;char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */unsigned long linux_text_len = 0;char *linux_data_tmp_addr = 0;char *linux_data_real_addr = 0;unsigned short io_map[IO_MAP_SIZE];struct apm_info apm_bios_info;/* Emulation requirements. */char *grub_scratch_mem = 0;struct geometry *disks = 0;/* The map between BIOS drives and UNIX device file names.  */char **device_map = 0;/* The jump buffer for exiting correctly.  */static jmp_buf env_for_exit;/* The current color for console.  */static int console_current_color = A_NORMAL;/* The file descriptor for a serial device.  */static int serial_fd = -1;/* The file name of a serial device.  */static char *serial_device = 0;#ifdef SIMULATE_SLOWNESS_OF_SERIAL/* The speed of a serial device.  */static unsigned int serial_speed;#endif /* SIMULATE_SLOWNESS_OF_SERIAL *//* The main entry point into this mess. */intgrub_stage2 (void){  /* These need to be static, because they survive our stack transitions. */  static int status = 0;  static char *realstack;  char *scratch, *simstack;  int i;  /* We need a nested function so that we get a clean stack frame,     regardless of how the code is optimized. */  static volatile void doit ()  {    /* Make sure our stack lives in the simulated memory area. */    asm volatile ("movl %%esp, %0\n\tmovl %1, %%esp\n"		  : "=&r" (realstack) : "r" (simstack));    /* Do a setjmp here for the stop command.  */    if (! setjmp (env_for_exit))      {	/* Actually enter the generic stage2 code.  */	status = 0;	init_bios_info ();      }    else      {	/* If ERRNUM is non-zero, then set STATUS to non-zero.  */	if (errnum)	  status = 1;      }    /* Replace our stack before we use any local variables. */    asm volatile ("movl %0, %%esp\n" : : "r" (realstack));  }  assert (grub_scratch_mem == 0);  scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);  assert (scratch);  grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);  /* FIXME: simulate the memory holes using mprot, if available. */  assert (disks == 0);  disks = malloc (NUM_DISKS * sizeof (*disks));  assert (disks);  /* Initialize DISKS.  */  for (i = 0; i < NUM_DISKS; i++)    disks[i].flags = -1;  if (! init_device_map (&device_map, device_map_file, floppy_disks))    return 1;    /* Check some invariants. */  assert ((SCRATCHSEG << 4) == SCRATCHADDR);  assert ((BUFFERSEG << 4) == BUFFERADDR);  assert (BUFFERADDR + BUFFERLEN == SCRATCHADDR);  assert (FSYS_BUF % 16 == 0);  assert (FSYS_BUF + FSYS_BUFLEN == BUFFERADDR);#ifdef HAVE_LIBCURSES  /* Get into char-at-a-time mode. */  if (use_curses)    {      initscr ();      cbreak ();      noecho ();      nonl ();      scrollok (stdscr, TRUE);      keypad (stdscr, TRUE);      wtimeout (stdscr, 100);      signal (SIGWINCH, SIG_IGN);    }#endif  /* Make sure that actual writing is done.  */  sync ();  /* Set our stack, and go for it. */  simstack = (char *) PROTSTACKINIT;  doit ();  /* I don't know if this is necessary really.  */  sync ();#ifdef HAVE_LIBCURSES  if (use_curses)    endwin ();#endif  /* Close off the file descriptors we used. */  for (i = 0; i < NUM_DISKS; i ++)    if (disks[i].flags != -1)      {#ifdef __linux__	/* In Linux, invalidate the buffer cache. In other OSes, reboot	   is one of the solutions...  */	ioctl (disks[i].flags, BLKFLSBUF, 0);#else# warning "In your operating system, the buffer cache will not be flushed."#endif	close (disks[i].flags);      }  if (serial_fd >= 0)    close (serial_fd);    /* Release memory. */  restore_device_map (device_map);  device_map = 0;  free (disks);  disks = 0;  free (scratch);  grub_scratch_mem = 0;  if (serial_device)    free (serial_device);  serial_device = 0;    /* Ahh... at last we're ready to return to caller. */  return status;}/* Assign DRIVE to a device name DEVICE.  */voidassign_device_name (int drive, const char *device){  /* If DRIVE is already assigned, free it.  */  if (device_map[drive])    free (device_map[drive]);  /* If the old one is already opened, close it.  */  if (disks[drive].flags != -1)    {      close (disks[drive].flags);      disks[drive].flags = -1;    }  /* Assign DRIVE to DEVICE.  */  if (! device)    device_map[drive] = 0;  else    device_map[drive] = strdup (device);}voidstop (void){#ifdef HAVE_LIBCURSES  if (use_curses)    endwin ();#endif  /* Jump to doit.  */  longjmp (env_for_exit, 1);}voidgrub_reboot (void){  stop ();}voidgrub_halt (int no_apm){  stop ();}/* calls for direct boot-loader chaining */voidchain_stage1 (unsigned long segment, unsigned long offset,	      unsigned long part_table_addr){  stop ();}voidchain_stage2 (unsigned long segment, unsigned long offset, int second_sector){  stop ();}/* do some funky stuff, then boot linux */voidlinux_boot (void){  stop ();}/* For bzImage kernels. */voidbig_linux_boot (void){  stop ();}/* booting a multiboot executable */voidmulti_boot (int start, int mb_info){  stop ();}/* sets it to linear or wired A20 operation */voidgateA20 (int linear){  /* Nothing to do in the simulator. */}/* Set up the int15 handler.  */voidset_int15_handler (void){  /* Nothing to do in the simulator.  */}/* Restore the original int15 handler.  */voidunset_int15_handler (void){  /* Nothing to do in the simulator.  */}/* The key map.  */unsigned short bios_key_map[KEY_MAP_SIZE + 1];unsigned short ascii_key_map[KEY_MAP_SIZE + 1];/* Copy MAP to the drive map and set up the int13 handler.  */voidset_int13_handler (unsigned short *map){  /* Nothing to do in the simulator.  */}intget_code_end (void){  /* Just return a little area for simulation. */  return BOOTSEC_LOCATION + (60 * 1024);}/* memory probe routines */intget_memsize (int type){  if (! type)    return CONVENTIONAL_MEMSIZE >> 10;  else    return EXTENDED_MEMSIZE >> 10;}/* get_eisamemsize() :  return packed EISA memory map, lower 16 bits is *		memory between 1M and 16M in 1K parts, upper 16 bits is *		memory above 16M in 64K parts.  If error, return -1. */intget_eisamemsize (void){  return (EXTENDED_MEMSIZE >> 10);}#define MMAR_DESC_TYPE_AVAILABLE 1 /* available to OS */#define MMAR_DESC_TYPE_RESERVED 2 /* not available */#define MMAR_DESC_TYPE_ACPI_RECLAIM 3 /* usable by OS after reading ACPI */#define MMAR_DESC_TYPE_ACPI_NVS 4 /* required to save between NVS sessions */#define MMAR_DESC_LENGTH	20/* Fetch the next entry in the memory map and return the continuation   value.  DESC is a pointer to the descriptor buffer, and CONT is the   previous continuation value (0 to get the first entry in the   map).  */intget_mmap_entry (struct mmar_desc *desc, int cont){  /* Record the memory map statically.  */  static struct mmar_desc desc_table[] =  {    /* The conventional memory.  */    {      MMAR_DESC_LENGTH,      0,      CONVENTIONAL_MEMSIZE,      MMAR_DESC_TYPE_AVAILABLE    },    /* BIOS RAM and ROM (such as video memory).  */    {      MMAR_DESC_LENGTH,      CONVENTIONAL_MEMSIZE,      0x100000 - CONVENTIONAL_MEMSIZE,      MMAR_DESC_TYPE_RESERVED    },    /* The extended memory.  */    {      MMAR_DESC_LENGTH,      0x100000,      EXTENDED_MEMSIZE,      MMAR_DESC_TYPE_AVAILABLE    }  };    int num = sizeof (desc_table) / sizeof (*desc_table);  if (cont < 0 || cont >= num)    {      /* Should not happen.  */      desc->desc_len = 0;    }  else    {      /* Copy the entry.  */      *desc = desc_table[cont++];      /* If the next entry exists, return the index.  */      if (cont < num)	return cont;    }    return 0;}/* Track the int13 handler.  */voidtrack_int13 (int drive){  /* Nothing to do in the simulator.  */}/* Get the ROM configuration table.  */unsigned longget_rom_config_table (void){  return 0;}/* Get APM BIOS information.  */voidget_apm_info (void){  /* Nothing to do in the simulator.  */}/* Get VBE controller information.  */intget_vbe_controller_info (struct vbe_controller *controller){  /* Always fails.  */  return 0;}/* Get VBE mode information.  */intget_vbe_mode_info (int mode_number, struct vbe_mode *mode){  /* Always fails.  */  return 0;}/* Set VBE mode.  */intset_vbe_mode (int mode_number){  /* Always fails.  */  return 0;}/* low-level timing info */intgetrtsecs (void){  /* FIXME: exact value is not important, so just return time_t for now. */  return time (0);}intcurrticks (void){  struct timeval tv;  long csecs;  int ticks_per_csec, ticks_per_usec;  /* Note: 18.2 ticks/sec.  */  /* Get current time.  */  gettimeofday (&tv, 0);  /* Compute centiseconds.  */  csecs = tv.tv_sec / 10;  /* Ticks per centisecond.  */  ticks_per_csec = csecs * 182;  /* Ticks per microsecond.  */  ticks_per_usec = (((tv.tv_sec - csecs * 10) * 1000000 + tv.tv_usec)		    * 182 / 10000000);  /* Sum them.  */  return ticks_per_csec + ticks_per_usec;}/* displays an ASCII character.  IBM displays will translate some   characters to special graphical ones */voidconsole_putchar (int c){  /* Curses doesn't have VGA fonts.  */  switch (c)    {    case DISP_UL:      c = ACS_ULCORNER;      break;    case DISP_UR:      c = ACS_URCORNER;      break;    case DISP_LL:      c = ACS_LLCORNER;      break;    case DISP_LR:      c = ACS_LRCORNER;      break;    case DISP_HORIZ:      c = ACS_HLINE;      break;    case DISP_VERT:      c = ACS_VLINE;      break;    case DISP_LEFT:      c = ACS_LARROW;      break;    case DISP_RIGHT:      c = ACS_RARROW;      break;    case DISP_UP:      c = ACS_UARROW;      break;    case DISP_DOWN:      c = ACS_DARROW;      break;    default:      break;    }#ifdef HAVE_LIBCURSES  if (use_curses)    {      /* In ncurses, a newline is treated badly, so we emulate it in our	 own way.  */      if (c == '\n')	{	  int x, y;	  getyx (stdscr, y, x);	  if (y + 1 == LINES)	    scroll (stdscr);	  else	    move (y + 1, x);	}      else if (isprint (c))	{	  int x, y;	  getyx (stdscr, y, x);	  if (x + 1 == COLS)	    {	      console_putchar ('\r');	      console_putchar ('\n');	    }	  addch (c | console_current_color);	}      else	{	  addch (c);	}      #ifdef REFRESH_IMMEDIATELY      refresh ();#endif    }  else#endif    {      /* CR is not used in Unix.  */      if (c != '\r')	putchar (c);    }}/* The store for ungetch simulation. This is necessary, because   ncurses-1.9.9g is still used in the world and its ungetch is   completely broken.  */#ifdef HAVE_LIBCURSESstatic int save_char = ERR;#endifstatic intconsole_translate_key (int c){  switch (c)    {    case KEY_LEFT:      return 2;    case KEY_RIGHT:      return 6;    case KEY_UP:      return 16;    case KEY_DOWN:      return 14;    case KEY_DC:      return 4;    case KEY_BACKSPACE:      return 8;    case KEY_HOME:      return 1;    case KEY_END:      return 5;    case KEY_PPAGE:      return 7;    case KEY_NPAGE:      return 3;    default:      break;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -