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

📄 builtins.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 5 页
字号:
/* builtins.c - the GRUB builtin commands *//* *  GRUB  --  GRand Unified Bootloader *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* Include stdio.h before shared.h, because we can't define   WITHOUT_LIBC_STUBS here.  */#ifdef GRUB_UTIL# include <stdio.h>#endif#include <shared.h>#include <filesys.h>#include <term.h>#ifdef SUPPORT_NETBOOT# define GRUB	1# include <etherboot.h>#endif#ifdef SUPPORT_SERIAL# include <serial.h># include <terminfo.h>#endif#ifdef GRUB_UTIL# include <device.h>#else /* ! GRUB_UTIL */# include <apic.h># include <smp-imps.h>#endif /* ! GRUB_UTIL */#ifdef USE_MD5_PASSWORDS# include <md5.h>#endif/* The type of kernel loaded.  */kernel_t kernel_type;/* The boot device.  */static int bootdev;/* True when the debug mode is turned on, and false   when it is turned off.  */int debug = 0;/* The default entry.  */int default_entry = 0;/* The fallback entry.  */int fallback_entry = -1;/* The number of current entry.  */int current_entryno;/* The address for Multiboot command-line buffer.  */static char *mb_cmdline;/* The password.  */char *password;/* The password type.  */password_t password_type;/* The flag for indicating that the user is authoritative.  */int auth = 0;/* The timeout.  */int grub_timeout = -1;/* Whether to show the menu or not.  */int show_menu = 1;/* The BIOS drive map.  */static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1];/* Prototypes for allowing straightfoward calling of builtins functions   inside other functions.  */static int configfile_func (char *arg, int flags);/* Initialize the data for builtins.  */voidinit_builtins (void){  kernel_type = KERNEL_TYPE_NONE;  /* BSD and chainloading evil hacks!  */  bootdev = set_bootdev (0);  mb_cmdline = (char *) MB_CMDLINE_BUF;}/* Initialize the data for the configuration file.  */voidinit_config (void){  default_entry = 0;  password = 0;  fallback_entry = -1;  grub_timeout = -1;}/* Check a password for correctness.  Returns 0 if password was   correct, and a value != 0 for error, similarly to strcmp. */intcheck_password (char *entered, char* expected, password_t type){  switch (type)    {    case PASSWORD_PLAIN:      return strcmp (entered, expected);#ifdef USE_MD5_PASSWORDS    case PASSWORD_MD5:      return check_md5_password (entered, expected);#endif    default:       /* unsupported password type: be secure */      return 1;    }}/* Print which sector is read when loading a file.  */static voiddisk_read_print_func (int sector, int offset, int length){  grub_printf ("[%d,%d,%d]", sector, offset, length);}/* blocklist */static intblocklist_func (char *arg, int flags){  char *dummy = (char *) RAW_ADDR (0x100000);  int start_sector;  int num_sectors = 0;  int num_entries = 0;  int last_length = 0;  /* Collect contiguous blocks into one entry as many as possible,     and print the blocklist notation on the screen.  */  static void disk_read_blocklist_func (int sector, int offset, int length)    {      if (num_sectors > 0)	{	  if (start_sector + num_sectors == sector	      && offset == 0 && last_length == SECTOR_SIZE)	    {	      num_sectors++;	      last_length = length;	      return;	    }	  else	    {	      if (last_length == SECTOR_SIZE)		grub_printf ("%s%d+%d", num_entries ? "," : "",			     start_sector - part_start, num_sectors);	      else if (num_sectors > 1)		grub_printf ("%s%d+%d,%d[0-%d]", num_entries ? "," : "",			     start_sector - part_start, num_sectors-1,			     start_sector + num_sectors-1 - part_start, 			     last_length);	      else		grub_printf ("%s%d[0-%d]", num_entries ? "," : "",			     start_sector - part_start, last_length);	      num_entries++;	      num_sectors = 0;	    }	}      if (offset > 0)	{	  grub_printf("%s%d[%d-%d]", num_entries ? "," : "",		      sector-part_start, offset, offset+length);	  num_entries++;	}      else	{	  start_sector = sector;	  num_sectors = 1;	  last_length = length;	}    }  /* Open the file.  */  if (! grub_open (arg))    return 1;  /* Print the device name.  */  grub_printf ("(%cd%d",	       (current_drive & 0x80) ? 'h' : 'f',	       current_drive & ~0x80);    if ((current_partition & 0xFF0000) != 0xFF0000)    grub_printf (",%d", (current_partition >> 16) & 0xFF);    if ((current_partition & 0x00FF00) != 0x00FF00)    grub_printf (",%c", 'a' + ((current_partition >> 8) & 0xFF));    grub_printf (")");  /* Read in the whole file to DUMMY.  */  disk_read_hook = disk_read_blocklist_func;  if (! grub_read (dummy, -1))    goto fail;  /* The last entry may not be printed yet.  Don't check if it is a   * full sector, since it doesn't matter if we read too much. */  if (num_sectors > 0)    grub_printf ("%s%d+%d", num_entries ? "," : "",		 start_sector - part_start, num_sectors);  grub_printf ("\n");   fail:  disk_read_hook = 0;  grub_close ();  return errnum;}static struct builtin builtin_blocklist ={  "blocklist",  blocklist_func,  BUILTIN_CMDLINE | BUILTIN_HELP_LIST,  "blocklist FILE",  "Print the blocklist notation of the file FILE."};/* boot */static intboot_func (char *arg, int flags){  /* Clear the int15 handler if we can boot the kernel successfully.     This assumes that the boot code never fails only if KERNEL_TYPE is     not KERNEL_TYPE_NONE. Is this assumption is bad?  */  if (kernel_type != KERNEL_TYPE_NONE)    unset_int15_handler ();#ifdef SUPPORT_NETBOOT  /* Shut down the networking.  */  cleanup_net ();#endif    switch (kernel_type)    {    case KERNEL_TYPE_FREEBSD:    case KERNEL_TYPE_NETBSD:      /* *BSD */      bsd_boot (kernel_type, bootdev, (char *) mbi.cmdline);      break;    case KERNEL_TYPE_LINUX:      /* Linux */      linux_boot ();      break;    case KERNEL_TYPE_BIG_LINUX:      /* Big Linux */      big_linux_boot ();      break;    case KERNEL_TYPE_CHAINLOADER:      /* Chainloader */            /* Check if we should set the int13 handler.  */      if (bios_drive_map[0] != 0)	{	  int i;	  	  /* Search for SAVED_DRIVE.  */	  for (i = 0; i < DRIVE_MAP_SIZE; i++)	    {	      if (! bios_drive_map[i])		break;	      else if ((bios_drive_map[i] & 0xFF) == saved_drive)		{		  /* Exchage SAVED_DRIVE with the mapped drive.  */		  saved_drive = (bios_drive_map[i] >> 8) & 0xFF;		  break;		}	    }	  	  /* Set the handler. This is somewhat dangerous.  */	  set_int13_handler (bios_drive_map);	}            gateA20 (0);      boot_drive = saved_drive;      chain_stage1 (0, BOOTSEC_LOCATION, boot_part_addr);      break;    case KERNEL_TYPE_MULTIBOOT:      /* Multiboot */      multi_boot ((int) entry_addr, (int) &mbi);      break;    default:      errnum = ERR_BOOT_COMMAND;      return 1;    }  return 0;}static struct builtin builtin_boot ={  "boot",  boot_func,  BUILTIN_CMDLINE | BUILTIN_HELP_LIST,  "boot",  "Boot the OS/chain-loader which has been loaded."};#ifdef SUPPORT_NETBOOT/* bootp */static intbootp_func (char *arg, int flags){  int with_configfile = 0;  if (grub_memcmp (arg, "--with-configfile", sizeof ("--with-configfile") - 1)      == 0)    {      with_configfile = 1;      arg = skip_to (0, arg);    }    if (! bootp ())    {      if (errnum == ERR_NONE)	errnum = ERR_DEV_VALUES;      return 1;    }  /* Notify the configuration.  */  print_network_configuration ();  /* XXX: this can cause an endless loop, but there is no easy way to     detect such a loop unfortunately.  */  if (with_configfile)    configfile_func (config_file, flags);    return 0;}static struct builtin builtin_bootp ={  "bootp",  bootp_func,  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,  "bootp [--with-configfile]",  "Initialize a network device via BOOTP. If the option `--with-configfile'"  " is given, try to load a configuration file specified by the 150 vendor"  " tag."};#endif /* SUPPORT_NETBOOT *//* cat */static intcat_func (char *arg, int flags){  char c;  if (! grub_open (arg))    return 1;  while (grub_read (&c, 1))    {      /* Because running "cat" with a binary file can confuse the terminal,	 print only some characters as they are.  */      if (grub_isspace (c) || (c >= ' ' && c <= '~'))	grub_putchar (c);      else	grub_putchar ('?');    }    grub_close ();  return 0;}static struct builtin builtin_cat ={  "cat",  cat_func,  BUILTIN_CMDLINE | BUILTIN_HELP_LIST,  "cat FILE",  "Print the contents of the file FILE."};/* chainloader */static intchainloader_func (char *arg, int flags){  int force = 0;  char *file = arg;  /* If the option `--force' is specified?  */  if (substring ("--force", arg) <= 0)    {      force = 1;      file = skip_to (0, arg);    }  /* Open the file.  */  if (! grub_open (file))    {      kernel_type = KERNEL_TYPE_NONE;      return 1;    }  /* Read the first block.  */  if (grub_read ((char *) BOOTSEC_LOCATION, SECTOR_SIZE) != SECTOR_SIZE)    {      grub_close ();      kernel_type = KERNEL_TYPE_NONE;      /* This below happens, if a file whose size is less than 512 bytes	 is loaded.  */      if (errnum == ERR_NONE)	errnum = ERR_EXEC_FORMAT;            return 1;    }  /* If not loading it forcibly, check for the signature.  */  if (! force      && (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET))	  != BOOTSEC_SIGNATURE))    {      grub_close ();      errnum = ERR_EXEC_FORMAT;      kernel_type = KERNEL_TYPE_NONE;      return 1;    }  grub_close ();  kernel_type = KERNEL_TYPE_CHAINLOADER;  /* XXX: Windows evil hack. For now, only the first five letters are     checked.  */  if (IS_PC_SLICE_TYPE_FAT (current_slice)      && ! grub_memcmp ((char *) BOOTSEC_LOCATION + BOOTSEC_BPB_SYSTEM_ID,			"MSWIN", 5))    *((unsigned long *) (BOOTSEC_LOCATION + BOOTSEC_BPB_HIDDEN_SECTORS))      = part_start;  errnum = ERR_NONE;    return 0;}static struct builtin builtin_chainloader ={  "chainloader",  chainloader_func,  BUILTIN_CMDLINE | BUILTIN_HELP_LIST,  "chainloader [--force] FILE",  "Load the chain-loader FILE. If --force is specified, then load it"  " forcibly, whether the boot loader signature is present or not."};/* This function could be used to debug new filesystem code. Put a file   in the new filesystem and the same file in a well-tested filesystem.   Then, run "cmp" with the files. If no output is obtained, probably   the code is good, otherwise investigate what's wrong...  *//* cmp FILE1 FILE2 */static intcmp_func (char *arg, int flags){  /* The filenames.  */  char *file1, *file2;  /* The addresses.  */  char *addr1, *addr2;  int i;  /* The size of the file.  */  int size;  /* Get the filenames from ARG.  */  file1 = arg;  file2 = skip_to (0, arg);  if (! *file1 || ! *file2)    {      errnum = ERR_BAD_ARGUMENT;      return 1;    }  /* Terminate the filenames for convenience.  */  nul_terminate (file1);  nul_terminate (file2);  /* Read the whole data from FILE1.  */  addr1 = (char *) RAW_ADDR (0x100000);  if (! grub_open (file1))    return 1;    /* Get the size.  */  size = filemax;  if (grub_read (addr1, -1) != size)    {      grub_close ();      return 1;    }    grub_close ();  /* Read the whole data from FILE2.  */  addr2 = addr1 + size;  if (! grub_open (file2))    return 1;  /* Check if the size of FILE2 is equal to the one of FILE2.  */  if (size != filemax)    {      grub_printf ("Differ in size: 0x%x [%s], 0x%x [%s]\n",		   size, file1, filemax, file2);      grub_close ();      return 0;    }    if (! grub_read (addr2, -1))    {      grub_close ();      return 1;    }    grub_close ();  /* Now compare ADDR1 with ADDR2.  */  for (i = 0; i < size; i++)    {      if (addr1[i] != addr2[i])	grub_printf ("Differ at the offset %d: 0x%x [%s], 0x%x [%s]\n",		     i, (unsigned) addr1[i], file1,		     (unsigned) addr2[i], file2);    }    return 0;}static struct builtin builtin_cmp ={  "cmp",  cmp_func,  BUILTIN_CMDLINE,  "cmp FILE1 FILE2",  "Compare the file FILE1 with the FILE2 and inform the different values"  " if any."};/* color *//* Set new colors used for the menu interface. Support two methods to   specify a color name: a direct integer representation and a symbolic   color name. An example of the latter is "blink-light-gray/blue".  */static int

⌨️ 快捷键说明

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