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

📄 disk_io.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 3 页
字号:
	      errnum = ERR_BAD_PART_TABLE;	      return 0;	    }	  /* Read the BSD label.  */	  if (! rawread (drive, *start + BSD_LABEL_SECTOR,			 0, SECTOR_SIZE, buf))	    return 0;	  /* Check if it is valid.  */	  if (! BSD_LABEL_CHECK_MAG (buf))	    {	      errnum = ERR_BAD_PART_TABLE;	      return 0;	    }	  	  bsd_part_no = -1;	}      /* Search next valid BSD partition.  */      for (i = bsd_part_no + 1; i < BSD_LABEL_NPARTS (buf); i++)	{	  if (BSD_PART_TYPE (buf, i))	    {	      /* Note that *TYPE and *PARTITION were set		 for current PC slice.  */	      *type = (BSD_PART_TYPE (buf, i) << 8) | (*type & 0xFF);	      *start = BSD_PART_START (buf, i);	      *len = BSD_PART_LENGTH (buf, i);	      *partition = (*partition & 0xFF00FF) | (i << 8);#ifndef STAGE1_5	      /* XXX */	      if ((drive & 0x80) && BSD_LABEL_DTYPE (buf) == DTYPE_SCSI)		bsd_evil_hack = 4;#endif /* ! STAGE1_5 */	      	      return 1;	    }	}      errnum = ERR_NO_PART;      return 0;    }  /* Get next PC slice. Be careful of that this function may return     an empty PC slice (i.e. a partition whose type is zero) as well.  */  int next_pc_slice (void)    {      int pc_slice_no = (*partition & 0xFF0000) >> 16;      /* If this is the first time...  */      if (pc_slice_no == 0xFF)	{	  *offset = 0;	  *ext_offset = 0;	  *entry = -1;	  pc_slice_no = -1;	}      /* Read the MBR or the boot sector of the extended partition.  */      if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf))	return 0;      /* Check if it is valid.  */      if (! PC_MBR_CHECK_SIG (buf))	{	  errnum = ERR_BAD_PART_TABLE;	  return 0;	}      /* Increase the entry number.  */      (*entry)++;      /* If this is out of current partition table...  */      if (*entry == PC_SLICE_MAX)	{	  int i;	  /* Search the first extended partition in current table.  */	  for (i = 0; i < PC_SLICE_MAX; i++)	    {	      if (IS_PC_SLICE_TYPE_EXTENDED (PC_SLICE_TYPE (buf, i)))		{		  /* Found. Set the new offset and the entry number,		     and restart this function.  */		  *offset = *ext_offset + PC_SLICE_START (buf, i);		  if (! *ext_offset)		    *ext_offset = *offset;		  *entry = -1;		  return next_pc_slice ();		}	    }	  errnum = ERR_NO_PART;	  return 0;	}            *type = PC_SLICE_TYPE (buf, *entry);      *start = *offset + PC_SLICE_START (buf, *entry);      *len = PC_SLICE_LENGTH (buf, *entry);      /* The calculation of a PC slice number is complicated, because of	 the rather odd definition of extended partitions. Even worse,	 there is no guarantee that this is consistent with every	 operating systems. Uggh.  */      if (pc_slice_no < PC_SLICE_MAX	  || (! IS_PC_SLICE_TYPE_EXTENDED (*type)	      && *type != PC_SLICE_TYPE_NONE))	pc_slice_no++;            *partition = (pc_slice_no << 16) | 0xFFFF;      return 1;    }  /* Start the body of this function.  */  #ifndef STAGE1_5  if (current_drive == NETWORK_DRIVE)    return 0;#endif  /* If previous partition is a BSD partition or a PC slice which     contains BSD partitions...  */  if ((*partition != 0xFFFFFF && IS_PC_SLICE_TYPE_BSD (*type & 0xff))      || ! (drive & 0x80))    {      if (*type == PC_SLICE_TYPE_NONE)	*type = PC_SLICE_TYPE_FREEBSD;            /* Get next BSD partition, if any.  */      if (next_bsd_partition ())	return 1;      /* If the destination partition is a BSD partition and current	 BSD partition has any error, abort the operation.  */      if ((dest & 0xFF00) != 0xFF00	  && ((dest & 0xFF0000) == 0xFF0000	      || (dest & 0xFF0000) == (*partition & 0xFF0000)))	return 0;      /* Ignore the error.  */      errnum = ERR_NONE;    }	    return next_pc_slice ();}#ifndef STAGE1_5static unsigned long cur_part_offset;static unsigned long cur_part_addr;#endif/* Open a partition.  */intreal_open_partition (int flags){  unsigned long dest_partition = current_partition;  unsigned long part_offset;  unsigned long ext_offset;  int entry;  char buf[SECTOR_SIZE];  int bsd_part, pc_slice;  /* For simplicity.  */  auto int next (void);  int next (void)    {      int ret = next_partition (current_drive, dest_partition,				&current_partition, &current_slice,				&part_start, &part_length,				&part_offset, &entry, &ext_offset, buf);      bsd_part = (current_partition >> 8) & 0xFF;      pc_slice = current_partition >> 16;      return ret;    }  #ifndef STAGE1_5  /* network drive */  if (current_drive == NETWORK_DRIVE)    return 1;    if (! sane_partition ())    return 0;#endif  bsd_evil_hack = 0;  current_slice = 0;  part_start = 0;  /* Make sure that buf_geom is valid. */  if (buf_drive != current_drive)    {      if (get_diskinfo (current_drive, &buf_geom))	{	  errnum = ERR_NO_DISK;	  return 0;	}      buf_drive = current_drive;      buf_track = -1;    }  part_length = buf_geom.total_sectors;  /* If this is the whole disk, return here.  */  if (! flags && current_partition == 0xFFFFFF)    return 1;  if (flags)    dest_partition = 0xFFFFFF;  /* Initialize CURRENT_PARTITION for next_partition.  */  current_partition = 0xFFFFFF;    while (next ())    {#ifndef STAGE1_5    loop_start:            cur_part_offset = part_offset;      cur_part_addr = BOOT_PART_TABLE + (entry << 4);#endif /* ! STAGE1_5 */      /* If this is a valid partition...  */      if (current_slice)	{#ifndef STAGE1_5	  /* Display partition information.  */	  if (flags && ! IS_PC_SLICE_TYPE_EXTENDED (current_slice))	    {	      if (! do_completion)		{		  if (current_drive & 0x80)		    grub_printf ("   Partition num: %d, ",				 current_partition >> 16);		  if (! IS_PC_SLICE_TYPE_BSD (current_slice))		    check_and_print_mount ();		  else		    {		      int got_part = 0;		      int saved_slice = current_slice;		      		      while (next ())			{			  if (bsd_part == 0xFF)			    break;			  			  if (! got_part)			    {			      grub_printf ("[BSD sub-partitions immediately follow]\n");			      got_part = 1;			    }			  			  grub_printf ("     BSD Partition num: \'%c\', ",				       bsd_part + 'a');			  check_and_print_mount ();			}		      if (! got_part)			grub_printf (" No BSD sub-partition found, partition type 0x%x\n",				     saved_slice);		      		      if (errnum)			{			  errnum = ERR_NONE;			  break;			}		      		      goto loop_start;		    }		}	      else		{		  if (bsd_part != 0xFF)		    {		      char str[16];		      		      if (! (current_drive & 0x80)			  || (dest_partition >> 16) == pc_slice)			grub_sprintf (str, "%c)", bsd_part + 'a');		      else			grub_sprintf (str, "%d,%c)",				      pc_slice, bsd_part + 'a');		      print_a_completion (str);		    }		  else if (! IS_PC_SLICE_TYPE_BSD (current_slice))		    {		      char str[8];		      		      grub_sprintf (str, "%d)", pc_slice);		      print_a_completion (str);		    }		}	    }	  	  errnum = ERR_NONE;#endif /* ! STAGE1_5 */	  	  /* Check if this is the destination partition.  */	  if (! flags	      && (dest_partition == current_partition		  || ((dest_partition >> 16) == 0xFF		      && ((dest_partition >> 8) & 0xFF) == bsd_part)))	    return 1;	}    }#ifndef STAGE1_5  if (flags)    {      if (! (current_drive & 0x80))	{	  current_partition = 0xFFFFFF;	  check_and_print_mount ();	}            errnum = ERR_NONE;      return 1;    }#endif /* ! STAGE1_5 */    return 0;}intopen_partition (void){  return real_open_partition (0);}#ifndef STAGE1_5/* XX used for device completion in 'set_device' and 'print_completions' */static int incomplete, disk_choice;static enum{  PART_UNSPECIFIED = 0,  PART_DISK,  PART_CHOSEN,}part_choice;#endif /* ! STAGE1_5 */char *set_device (char *device){#ifdef STAGE1_5    /* In Stage 1.5, the first 4 bytes of FILENAME has a device number.  */  unsigned long dev = *((unsigned long *) device);  int drive = (dev >> 24) & 0xFF;  int partition = dev & 0xFFFFFF;  /* If DRIVE is disabled, use SAVED_DRIVE instead.  */  if (drive == GRUB_INVALID_DRIVE)    current_drive = saved_drive;  else    current_drive = drive;  /* The `partition' part must always have a valid number.  */  current_partition = partition;    return device + sizeof (unsigned long);  #else /* ! STAGE1_5 */    int result = 0;  incomplete = 0;  disk_choice = 1;  part_choice = PART_UNSPECIFIED;  current_drive = saved_drive;  current_partition = 0xFFFFFF;  if (*device == '(' && !*(device + 1))    /* user has given '(' only, let disk_choice handle what disks we have */    return device + 1;  if (*device == '(' && *(++device))    {      if (*device != ',' && *device != ')')	{	  char ch = *device;#ifdef SUPPORT_NETBOOT	  if (*device == 'f' || *device == 'h'	      || (*device == 'n' && network_ready)	      || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE))#else	  if (*device == 'f' || *device == 'h'	      || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE))#endif /* SUPPORT_NETBOOT */	    {	      /* user has given '([fhn]', check for resp. add 'd' and		 let disk_choice handle what disks we have */	      if (!*(device + 1))		{		  device++;		  *device++ = 'd';		  *device = '\0';		  return device;		}	      else if (*(device + 1) == 'd' && !*(device + 2))		return device + 2;	    }	  if ((*device == 'f'	       || *device == 'h'#ifdef SUPPORT_NETBOOT	       || (*device == 'n' && network_ready)#endif	       || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE))	      && (device += 2, (*(device - 1) != 'd')))	    errnum = ERR_NUMBER_PARSING;	  #ifdef SUPPORT_NETBOOT	  if (ch == 'n' && network_ready)	    current_drive = NETWORK_DRIVE;	  else#endif /* SUPPORT_NETBOOT */	    {	      if (ch == 'c' && cdrom_drive != GRUB_INVALID_DRIVE)		current_drive = cdrom_drive;	      else		{		  safe_parse_maxint (&device, (int *) &current_drive);		  		  disk_choice = 0;		  if (ch == 'h')		    current_drive += 0x80;		}	    }	}      if (errnum)	return 0;      if (*device == ')')	{	  part_choice = PART_CHOSEN;	  result = 1;	}      else if (*device == ',')	{	  /* Either an absolute PC or BSD partition. */	  disk_choice = 0;	  part_choice ++;	  device++;	  if (*device >= '0' && *device <= '9')	    {	      part_choice ++;	      current_partition = 0;	      if (!(current_drive & 0x80)		  || !safe_parse_maxint (&device, (int *) &current_partition)		  || current_partition > 254)		{		  errnum = ERR_DEV_FORMAT;		  return 0;		}	      current_partition = (current_partition << 16) + 0xFFFF;	      if (*device == ',')		device++;	      	      if (*device >= 'a' && *device <= 'h')		{		  current_partition = (((*(device++) - 'a') << 8)				       | (current_partition & 0xFF00FF));		}	    }	  else if (*device >= 'a' && *device <= 'h')	    {	      part_choice ++;	      current_partition = ((*(device++) - 'a') << 8) | 0xFF00FF;	    }	  if (*device == ')')	    {	      if (part_choice == PART_DISK)		{		  current_partition = saved_partition;		  part_choice ++;		}	      result = 1;	    }	}    }  if (! sane_partition ())    return 0;    if (result)    return device + 1;  else    {      if (!*device)	incomplete = 1;      errnum = ERR_DEV_FORMAT;    }  return 0;  #endif /* ! STAGE1_5 */}/* *  This performs a "mount" on the current device, both drive and partition *  number. */intopen_device (void){  if (open_partition ())    attempt_mount ();  if (errnum != ERR_NONE)    return 0;  return 1;}#ifndef STAGE1_5intset_bootdev (int hdbias){  int i, j;  /* Copy the boot partition information to 0x7be-0x7fd for chain-loading.  */  if ((saved_drive & 0x80) && cur_part_addr)    {      if (rawread (saved_drive, cur_part_offset,		   0, SECTOR_SIZE, (char *) SCRATCHADDR))	{	  char *dst, *src;      	  /* Need only the partition table.	     XXX: We cannot use grub_memmove because BOOT_PART_TABLE	     (0x07be) is less than 0x1000.  */	  dst = (char *) BOOT_PART_TABLE;	  src = (char *) SCRATCHADDR + BOOTSEC_PART_OFFSET;	  while (dst < (char *) BOOT_PART_TABLE + BOOTSEC_PART_LENGTH)	    *dst++ = *src++;	  	  /* Set the active flag of the booted partition.  */	  for (i = 0; i < 4; i++)	    PC_SLICE_FLAG (BOOT_PART_TABLE, i) = 0;	  	  *((unsigned char *) cur_part_addr) = PC_SLICE_FLAG_BOOTABLE;	  boot_part_addr = cur_part_addr;	}      else	return 0;    }    /*   *  Set BSD boot device.   */  i = (saved_partition >> 16) + 2;  if (saved_partition == 0xFFFFFF)    i = 1;  else if ((saved_partition >> 16) == 0xFF)    i = 0;  /* FIXME: extremely evil hack!!! */  j = 2;  if (saved_drive & 0x80)    j = bsd_evil_hack;  return MAKEBOOTDEV (j, (i >> 4), (i & 0xF),		      ((saved_drive - hdbias) & 0x7F),		      ((saved_partition >> 8) & 0xFF));}#endif /* STAGE1_5 */static char *setup_part (char *filename){#ifdef STAGE1_5  if (! (filename = set_device (filename)))    {      current_drive = GRUB_INVALID_DRIVE;      return 0;    }  # ifndef NO_BLOCK_FILES  if (*filename != '/')    open_partition ();  else# endif /* ! NO_BLOCK_FILES */    open_device ();

⌨️ 快捷键说明

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