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

📄 builtins.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 5 页
字号:
    default:      errnum = ERR_NEED_LX_KERNEL;      return 1;    }  return 0;}static struct builtin builtin_initrd ={  "initrd",  initrd_func,  BUILTIN_CMDLINE | BUILTIN_HELP_LIST,  "initrd FILE [ARG ...]",  "Load an initial ramdisk FILE for a Linux format boot image and set the"  " appropriate parameters in the Linux setup area in memory."};/* install */static intinstall_func (char *arg, int flags){  char *stage1_file, *dest_dev, *file, *addr;  char *stage1_buffer = (char *) RAW_ADDR (0x100000);  char *stage2_buffer = stage1_buffer + SECTOR_SIZE;  char *old_sect = stage2_buffer + SECTOR_SIZE;  char *stage2_first_buffer = old_sect + SECTOR_SIZE;  char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE;  /* XXX: Probably SECTOR_SIZE is reasonable.  */  char *config_filename = stage2_second_buffer + SECTOR_SIZE;  char *dummy = config_filename + SECTOR_SIZE;  int new_drive = GRUB_INVALID_DRIVE;  int dest_drive, dest_partition, dest_sector;  int src_drive, src_partition, src_part_start;  int i;  struct geometry dest_geom, src_geom;  int saved_sector;  int stage2_first_sector, stage2_second_sector;  char *ptr;  int installaddr, installlist;  /* Point to the location of the name of a configuration file in Stage 2.  */  char *config_file_location;  /* If FILE is a Stage 1.5?  */  int is_stage1_5 = 0;  /* Must call grub_close?  */  int is_open = 0;  /* If LBA is forced?  */  int is_force_lba = 0;  /* Was the last sector full? */  int last_length = SECTOR_SIZE;  #ifdef GRUB_UTIL  /* If the Stage 2 is in a partition mounted by an OS, this will store     the filename under the OS.  */  char *stage2_os_file = 0;#endif /* GRUB_UTIL */    /* Save the first sector of Stage2 in STAGE2_SECT.  */  static void disk_read_savesect_func (int sector, int offset, int length)    {      if (debug)	printf ("[%d]", sector);      /* ReiserFS has files which sometimes contain data not aligned         on sector boundaries.  Returning an error is better than         silently failing. */      if (offset != 0 || length != SECTOR_SIZE)	errnum = ERR_UNALIGNED;      saved_sector = sector;    }  /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and     INSTALLSECT.  */  static void disk_read_blocklist_func (int sector, int offset, int length)    {      if (debug)	printf("[%d]", sector);      if (offset != 0 || last_length != SECTOR_SIZE)	{	  /* We found a non-sector-aligned data block. */	  errnum = ERR_UNALIGNED;	  return;	}      last_length = length;      if (*((unsigned long *) (installlist - 4))	  + *((unsigned short *) installlist) != sector	  || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4)	{	  installlist -= 8;	  if (*((unsigned long *) (installlist - 8)))	    errnum = ERR_WONT_FIT;	  else	    {	      *((unsigned short *) (installlist + 2)) = (installaddr >> 4);	      *((unsigned long *) (installlist - 4)) = sector;	    }	}      *((unsigned short *) installlist) += 1;      installaddr += 512;    }  /* First, check the GNU-style long option.  */  while (1)    {      if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)	{	  is_force_lba = 1;	  arg = skip_to (0, arg);	}#ifdef GRUB_UTIL      else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)	{	  stage2_os_file = arg + sizeof ("--stage2=") - 1;	  arg = skip_to (0, arg);	  nul_terminate (stage2_os_file);	}#endif /* GRUB_UTIL */      else	break;    }    stage1_file = arg;  dest_dev = skip_to (0, stage1_file);  if (*dest_dev == 'd')    {      new_drive = 0;      dest_dev = skip_to (0, dest_dev);    }  file = skip_to (0, dest_dev);  addr = skip_to (0, file);  /* Get the installation address.  */  if (! safe_parse_maxint (&addr, &installaddr))    {      /* ADDR is not specified.  */      installaddr = 0;      ptr = addr;      errnum = 0;    }  else    ptr = skip_to (0, addr);#ifndef NO_DECOMPRESSION  /* Do not decompress Stage 1 or Stage 2.  */  no_decompression = 1;#endif  /* Read Stage 1.  */  is_open = grub_open (stage1_file);  if (! is_open      || ! grub_read (stage1_buffer, SECTOR_SIZE) == SECTOR_SIZE)    goto fail;  /* Read the old sector from DEST_DEV.  */  if (! set_device (dest_dev)      || ! open_partition ()      || ! devread (0, 0, SECTOR_SIZE, old_sect))    goto fail;  /* Store the information for the destination device.  */  dest_drive = current_drive;  dest_partition = current_partition;  dest_geom = buf_geom;  dest_sector = part_start;  /* Copy the possible DOS BPB, 59 bytes at byte offset 3.  */  grub_memmove (stage1_buffer + BOOTSEC_BPB_OFFSET,		old_sect + BOOTSEC_BPB_OFFSET,		BOOTSEC_BPB_LENGTH);  /* If for a hard disk, copy the possible MBR/extended part table.  */  if (dest_drive & 0x80)    grub_memmove (stage1_buffer + STAGE1_WINDOWS_NT_MAGIC,		  old_sect + STAGE1_WINDOWS_NT_MAGIC,		  STAGE1_PARTEND - STAGE1_WINDOWS_NT_MAGIC);  /* Check for the version and the signature of Stage 1.  */  if (*((short *)(stage1_buffer + STAGE1_VER_MAJ_OFFS)) != COMPAT_VERSION      || (*((unsigned short *) (stage1_buffer + BOOTSEC_SIG_OFFSET))	  != BOOTSEC_SIGNATURE))    {      errnum = ERR_BAD_VERSION;      goto fail;    }  /* This below is not true any longer. But should we leave this alone?  */    /* If DEST_DRIVE is a floppy, Stage 2 must have the iteration probe     routine.  */  if (! (dest_drive & 0x80)      && (*((unsigned char *) (stage1_buffer + BOOTSEC_PART_OFFSET)) == 0x80	  || stage1_buffer[BOOTSEC_PART_OFFSET] == 0))    {      errnum = ERR_BAD_VERSION;      goto fail;    }  grub_close ();    /* Open Stage 2.  */  is_open = grub_open (file);  if (! is_open)    goto fail;  src_drive = current_drive;  src_partition = current_partition;  src_part_start = part_start;  src_geom = buf_geom;    if (! new_drive)    new_drive = src_drive;  else if (src_drive != dest_drive)    grub_printf ("Warning: the option `d' was not used, but the Stage 1 will"		 " be installed on a\ndifferent drive than the drive where"		 " the Stage 2 resides.\n");  /* Set the boot drive.  */  *((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE)) = new_drive;  /* Set the "force LBA" flag.  */  *((unsigned char *) (stage1_buffer + STAGE1_FORCE_LBA)) = is_force_lba;  /* Set the boot drive mask. This is a workaround for buggy BIOSes which     don't pass boot drive correctly. Instead, they pass 0x00 even when     booted from 0x80.  */  *((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE_MASK))    = (dest_drive & BIOS_FLAG_FIXED_DISK);    /* Read the first sector of Stage 2.  */  disk_read_hook = disk_read_savesect_func;  if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE)    goto fail;  stage2_first_sector = saved_sector;    /* Read the second sector of Stage 2.  */  if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE)    goto fail;  stage2_second_sector = saved_sector;    /* Check for the version of Stage 2.  */  if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS))      != COMPAT_VERSION)    {      errnum = ERR_BAD_VERSION;      goto fail;    }  /* Check for the Stage 2 id.  */  if (stage2_second_buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2)    is_stage1_5 = 1;  /* If INSTALLADDR is not specified explicitly in the command-line,     determine it by the Stage 2 id.  */  if (! installaddr)    {      if (! is_stage1_5)	/* Stage 2.  */	installaddr = 0x8000;      else	/* Stage 1.5.  */	installaddr = 0x2000;    }  *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR))    = stage2_first_sector;  *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS))    = installaddr;  *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT))    = installaddr >> 4;  i = (int) stage2_first_buffer + SECTOR_SIZE - 4;  while (*((unsigned long *) i))    {      if (i < (int) stage2_first_buffer	  || (*((int *) (i - 4)) & 0x80000000)	  || *((unsigned short *) i) >= 0xA00	  || *((short *) (i + 2)) == 0)	{	  errnum = ERR_BAD_VERSION;	  goto fail;	}      *((int *) i) = 0;      *((int *) (i - 4)) = 0;      i -= 8;    }  installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4;  installaddr += SECTOR_SIZE;    /* Read the whole of Stage2 except for the first sector.  */  grub_seek (SECTOR_SIZE);  disk_read_hook = disk_read_blocklist_func;  if (! grub_read (dummy, -1))    goto fail;    disk_read_hook = 0;    /* Find a string for the configuration filename.  */  config_file_location = stage2_second_buffer + STAGE2_VER_STR_OFFS;  while (*(config_file_location++))    ;  /* Set the "force LBA" flag for Stage2.  */  *((unsigned char *) (stage2_second_buffer + STAGE2_FORCE_LBA))    = is_force_lba;    if (*ptr == 'p')    {      *((long *) (stage2_second_buffer + STAGE2_INSTALLPART))	= src_partition;      if (is_stage1_5)	{	  /* Reset the device information in FILE if it is a Stage 1.5.  */	  unsigned long device = 0xFFFFFFFF;	  grub_memmove (config_file_location, (char *) &device,			sizeof (device));	}      ptr = skip_to (0, ptr);    }  if (*ptr)    {      grub_strcpy (config_filename, ptr);      nul_terminate (config_filename);	      if (! is_stage1_5)	/* If it is a Stage 2, just copy PTR to CONFIG_FILE_LOCATION.  */	grub_strcpy (config_file_location, ptr);      else	{	  char *real_config;	  unsigned long device;	  /* Translate the external device syntax to the internal device	     syntax.  */	  if (! (real_config = set_device (ptr)))	    {	      /* The Stage 2 PTR does not contain the device name, so		 use the root device instead.  */	      errnum = ERR_NONE;	      current_drive = saved_drive;	      current_partition = saved_partition;	      real_config = ptr;	    }	  	  if (current_drive == src_drive)	    {	      /* If the drive where the Stage 2 resides is the same as		 the one where the Stage 1.5 resides, do not embed the		 drive number.  */	      current_drive = GRUB_INVALID_DRIVE;	    }	  device = (current_drive << 24) | current_partition;	  grub_memmove (config_file_location, (char *) &device,			sizeof (device));	  grub_strcpy (config_file_location + sizeof (device),		       real_config);	}      /* If a Stage 1.5 is used, then we need to modify the Stage2.  */      if (is_stage1_5)	{	  char *real_config_filename = skip_to (0, ptr);	  	  is_open = grub_open (config_filename);	  if (! is_open)	    goto fail;	  /* Skip the first sector.  */	  grub_seek (SECTOR_SIZE);	  	  disk_read_hook = disk_read_savesect_func;	  if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE)	    goto fail;	  	  disk_read_hook = 0;	  grub_close ();	  is_open = 0;	  	  /* Sanity check.  */	  if (*(stage2_buffer + STAGE2_STAGE2_ID) != STAGE2_ID_STAGE2)	    {	      errnum = ERR_BAD_VERSION;	      goto fail;	    }	  /* Set the "force LBA" flag for Stage2.  */	  *(stage2_buffer + STAGE2_FORCE_LBA) = is_force_lba;	  /* If REAL_CONFIG_FILENAME is specified, copy it to the Stage2.  */	  if (*real_config_filename)	    {	      /* Specified */	      char *location;	      	      /* Find a string for the configuration filename.  */	      location = stage2_buffer + STAGE2_VER_STR_OFFS;	      while (*(location++))		;	      	      /* Copy the name.  */	      grub_strcpy (location, real_config_filename);	    }	  	  /* Write it to the disk.  */	  buf_track = -1;#ifdef GRUB_UTIL	  /* In the grub shell, access the Stage 2 via the OS filesystem	     service, if possible.  */	  if (stage2_os_file)	    {	      FILE *fp;	      fp = fopen (stage2_os_file, "r+");	      if (! fp)		{		  errnum = ERR_FILE_NOT_FOUND;		  goto fail;		}	      if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0)		{		  fclose (fp);		  errnum = ERR_BAD_VERSION;		  goto fail;		}	      if (fwrite (stage2_buffer, 1, SECTOR_SIZE, fp)		  != SECTOR_SIZE)		{		  fclose (fp);		  errnum = ERR_WRITE;		  goto fail;		}	      fclose (fp);	    }	  else#endif /* GRUB_UTIL */	    {	      if (! devwrite (saved_sector - part_start, 1, stage2_buffer))		goto fail;	    }	}    }  /* Clear the cache.  */  buf_track = -1;  /* Write the modified sectors of Stage2 to the disk.  */#ifdef GRUB_UTIL  if (! is_stage1_5 && stage2_os_file)    {      FILE *fp;      fp = fopen (stage2_os_file, "r+");      if (! fp)	{	  errnum = ERR_FILE_NOT_FOUND;	  goto fail;	}      if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)	{	  fclose (fp);	  errnum = ERR_WRITE;	  goto fail;	}      if (fwrite (stage2_second_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)	{	  fclose (fp);	  errnum = ERR_WRITE;	  goto fail;	}      fclose (fp);    }  else#endif /* GRUB_UTIL */    {      /* The first.  */      current_drive = src_drive;      current_partition = src_partition;      if (! open_partition ())	goto fail;      if (! devwrite (stage2_first_sector - src_part_start, 1,		      stage2_first_buffer))	goto fail;      if (! devwrite (stage2_second_sector - src_part_start, 1,		      stage2_second_buffer))	goto fail;    }    /* Write the modified sector of Stage 1 to the disk.  */  current_drive = dest_drive;  current_partition = dest_partition;  if (! open_partition ())    goto fail;  devwrite (0, 1, stage1_buffer); fail:  if (is_open)    grub_close ();    disk_read_hook = 0;  #ifndef NO_DECOMPRESSION  no_decompression = 0;#endif  return errnum;}static struct builtin builtin_install ={  "install",  install_func,  BUILTIN_CMDLINE,  "install [--stage2=STAGE2_FILE] [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]",  "Install STAGE1 on DEVICE, and install a blocklist for loading STAGE2"  " as a Stage 2. If the option `d' is present, the Stage 1 will always"  " look for the disk where STAGE2 was installed, rather than using"  " the booting drive. The Stage 2 will be loaded at address ADDR, which"  " will be determined automatically if you don't specify it. If"  " the option `p' or CONFIG_FILE is present, then the first block"  " of Stage 2 is patched with new values of the partition and name"  " of the configuration file used by the true Stage 2 (for a Stage 1.5,"  " this is the name of the true Stage 2) at boot time. If STAGE2 is a Stage"  " 1.5 and REAL_CONFIG_FILE is present, then the Stage 2 CONFIG_FILE is"  " patched with the configuration filename REAL_CONFIG_FILE."  " If the option `--force-lba' is specified, disable some sanity checks"  " for LBA mode. If the option `--stage2' is specified, rewrite the Stage"  " 2 via your OS's filesystem instead of the raw device."};/* ioprobe */static intioprobe_func (char *arg, int flags){#ifdef GRUB_UTIL  

⌨️ 快捷键说明

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