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

📄 disk_io.c

📁 grub4dos-0.4.4-2008- 08-src.zip
💻 C
📖 第 1 页 / 共 4 页
字号:
/* disk_io.c - implement abstract BIOS disk input and output *//* *  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 <shared.h>#include <filesys.h>#include <iso9660.h>#ifdef SUPPORT_NETBOOT# define GRUB	1# include <etherboot.h>#endif#ifdef GRUB_UTIL# include <device.h>#endif/* instrumentation variables */void (*disk_read_hook) (unsigned long, unsigned long, unsigned long) = NULL;void (*disk_read_func) (unsigned long, unsigned long, unsigned long) = NULL;/* Forward declarations.  */static int next_bsd_partition (void);static int next_pc_slice (void);static char open_filename[512];static unsigned long relative_path;#ifndef STAGE1_5int print_possibilities;static int unique;static char *unique_string;static unsigned long cur_part_offset;static unsigned long cur_part_addr;static int do_completion;int dir (char *dirname);static int sane_partition (void);/* 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 */unsigned long i;#if !defined(STAGE1_5) && !defined(GRUB_UTIL)/* The first sector of stage2 can be reused as a tmp buffer. * Do NOT write more than 512 bytes to this buffer! * The stage2-body, i.e., the pre_stage2, starts at 0x8200! * Do NOT overwrite the pre_stage2 code at 0x8200! */char *mbr = (char *)0x8000; /* 512-byte buffer for any use. */#elsechar mbr[SECTOR_SIZE];#endifunsigned long next_partition_drive;unsigned long next_partition_dest;unsigned long *next_partition_partition;unsigned long *next_partition_type;unsigned long *next_partition_start;unsigned long *next_partition_len;unsigned long *next_partition_offset;unsigned long *next_partition_entry;unsigned long *next_partition_ext_offset;char *next_partition_buf;static unsigned long dest_partition;static unsigned long part_offset;static unsigned long entry;static unsigned long ext_offset;static unsigned long bsd_part_no;static unsigned long pc_slice_no;unsigned long fsmax;struct fsys_entry fsys_table[NUM_FSYS + 1] ={  /* TFTP should come first because others don't handle net device.  */# ifdef FSYS_PXE  {"pxe", pxe_mount, pxe_read, pxe_dir, pxe_close, 0},# endif# ifdef FSYS_TFTP  {"tftp", tftp_mount, tftp_read, tftp_dir, tftp_close, 0},# endif# ifdef FSYS_EXT2FS  {"ext2fs", ext2fs_mount, ext2fs_read, ext2fs_dir, 0, 0},# endif# ifdef FSYS_FAT  {"fat", fat_mount, fat_read, fat_dir, 0, 0},# endif# ifdef FSYS_NTFS  {"ntfs", ntfs_mount, ntfs_read, ntfs_dir, 0, 0},# endif# ifdef FSYS_MINIX  {"minix", minix_mount, minix_read, minix_dir, 0, 0},# endif# ifdef FSYS_REISERFS  {"reiserfs", reiserfs_mount, reiserfs_read, reiserfs_dir, 0, reiserfs_embed},# endif# ifdef FSYS_VSTAFS  {"vstafs", vstafs_mount, vstafs_read, vstafs_dir, 0, 0},# endif# ifdef FSYS_JFS  {"jfs", jfs_mount, jfs_read, jfs_dir, 0, jfs_embed},# endif# ifdef FSYS_XFS  {"xfs", xfs_mount, xfs_read, xfs_dir, 0, 0},# endif# ifdef FSYS_UFS2  {"ufs2", ufs2_mount, ufs2_read, ufs2_dir, 0, ufs2_embed},# endif# ifdef FSYS_ISO9660  {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, 0, 0},# endif  /* XX FFS should come last as it's superblock is commonly crossing tracks     on floppies from track 1 to 2, while others only use 1.  */# ifdef FSYS_FFS  {"ffs", ffs_mount, ffs_read, ffs_dir, 0, ffs_embed},# endif  {0, 0, 0, 0, 0, 0}};/* These have the same format as "boot_drive" and "install_partition", but   are meant to be working values. */unsigned long current_drive = GRUB_INVALID_DRIVE;unsigned long current_partition;#ifndef STAGE1_5/* The register ESI should contain the address of the partition to be   used for loading a chain-loader when chain-loading the loader.  */unsigned long boot_part_addr = 0;#endif/* *  Global variables describing details of the filesystem *//* FIXME: BSD evil hack */#include "freebsd.h"int bsd_evil_hack;/* filesystem type */int fsys_type = NUM_FSYS;/* these are the translated numbers for the open partition */unsigned long part_start;unsigned long part_length;unsigned long current_slice;/* disk buffer parameters */int buf_drive = -1;int buf_track = -1;struct geometry buf_geom;struct geometry tmp_geom;	/* tmp variable used in many functions. */struct geometry fd_geom[4];struct geometry hd_geom[4];int rawread_ignore_memmove_overflow = 0;/* blocklist_func() set this to 1 *//* filesystem common variables */unsigned long filepos;unsigned long filemax;unsigned long emu_iso_sector_size_2048 = 0;inline unsigned longlog2_tmp (unsigned long word){  asm volatile ("bsfl %1,%0"		: "=r" (word)		: "r" (word));  return word;}/* Convert unicode filename to UTF-8 filename. N is the max characters to be * converted. The caller should asure there is enough room in the UTF8 buffer. * */voidunicode_to_utf8 (unsigned short *filename, unsigned char *utf8, unsigned long n){	unsigned short uni;	unsigned long j, k;	for (j = 0, k = 0; j < n && (uni = filename[j]); j++)	{		if (uni <= 0x007F)		{			if (uni != ' ')				utf8[k++] = uni;			else			{				/* quote the SPACE with a backslash */				utf8[k++] = '\\';				utf8[k++] = uni;			}		}		else if (uni <= 0x07FF)		{			utf8[k++] = 0xC0 | (uni >> 6);			utf8[k++] = 0x80 | (uni & 0x003F);		}		else		{			utf8[k++] = 0xE0 | (uni >> 12);			utf8[k++] = 0x80 | ((uni >> 6) & 0x003F);			utf8[k++] = 0x80 | (uni & 0x003F);		}	}	utf8[k] = 0;}/* Read bytes from DRIVE to BUF. * * The bytes start at BYTE_OFFSET in absolute sector number SECTOR and with * BYTE_LEN bytes long. * */intrawread (unsigned long drive, unsigned long sector, unsigned long byte_offset, unsigned long byte_len, char *buf){  unsigned long slen, sectors_per_vtrack;  unsigned long sector_size_bits = log2_tmp (buf_geom.sector_size);//  if (byte_len == 0)//    return 1;  errnum = 0;  while (byte_len > 0)    {      unsigned long soff, num_sect, track, size = byte_len;      char *bufaddr;      /*       *  Check track buffer.  If it isn't valid or it is from the       *  wrong disk, then reset the disk geometry.       */      if (buf_drive != drive)	{	  if (get_diskinfo (drive, &buf_geom))	    {	      errnum = ERR_NO_DISK;	      return 0;	    }	  buf_drive = drive;	  buf_track = -1;	  sector_size_bits = log2_tmp (buf_geom.sector_size);	}#if 0      /* Make sure that SECTOR is valid.  */      if (/* sector < 0 || */ sector >= buf_geom.total_sectors)	{	  errnum = ERR_GEOM;	/* Selected cylinder exceeds maximum supported by BIOS. This message is not proper. */	  return 0;	}#endif      /* Sectors that need to read */      slen = ((byte_offset + byte_len + buf_geom.sector_size - 1) >> sector_size_bits);      /* Eliminate a buffer overflow.  */      if ((buf_geom.sectors << sector_size_bits) > BUFFERLEN)	sectors_per_vtrack = (BUFFERLEN >> sector_size_bits);      else	sectors_per_vtrack = buf_geom.sectors;      /* Get the first sector number in the track.  */      soff = sector % sectors_per_vtrack;      /* Get the starting sector number of the track. */      track = sector - soff;      /* max number of sectors to read in the track. */      num_sect = sectors_per_vtrack - soff;      /* Read data into the track buffer; Not all sectors in the track would be filled in. */      bufaddr = ((char *) BUFFERADDR + (soff << sector_size_bits) + byte_offset);      if (track != buf_track)	{	  unsigned long bios_err;	  unsigned long read_start = track;	  unsigned long read_len = sectors_per_vtrack;	  buf_track = track;	  /*	   *  If there's more than one read in this entire loop, then	   *  only make the earlier reads for the portion needed.  This	   *  saves filling the buffer with data that won't be used!	   */	  if (slen > num_sect)	    {	      buf_track = -1;	/* invalidate the buffer */	      read_start = sector;	      read_len = num_sect;	      bufaddr = (char *) BUFFERADDR + byte_offset;	    }	  bios_err = biosdisk (BIOSDISK_READ, drive, &buf_geom, read_start, read_len, BUFFERSEG);	  if (bios_err)	    {	      buf_track = -1;	/* invalidate the buffer *///	      if (bios_err == BIOSDISK_ERROR_GEOMETRY)//	      {//		errnum = ERR_GEOM;//		return 0;//	      }//	      else		{		  /* Do not try again to read sectors near a bad track.		   * Reading these sectors may slow down the system.		   * This can also remind us potential problems with the disk.		   */#if 0		  /*		   *  If there was an error, try to load only the		   *  required sector(s) rather than failing completely.		   */		  if (slen > num_sect		      || biosdisk (BIOSDISK_READ, drive, &buf_geom,				   sector, slen, BUFFERSEG))#endif		  {		    errnum = ERR_READ;		    return 0;		  }		  //bufaddr = (char *) BUFFERADDR + byte_offset;		}	    }	} /* if (track != buf_track) */      if (size > (num_sect << sector_size_bits) - byte_offset)	  size = (num_sect << sector_size_bits) - byte_offset;      /*       *  Instrumentation to tell which sectors were read and used.       */      if (disk_read_func)	{	  unsigned long sector_num = sector;	  unsigned long length = buf_geom.sector_size - byte_offset;	  if (length > size)	    length = size;	  (*disk_read_func) (sector_num++, byte_offset, length);	  length = size - length;	  if (length > 0)	    {	      while (length > buf_geom.sector_size)		{		  (*disk_read_func) (sector_num++, 0, buf_geom.sector_size);		  length -= buf_geom.sector_size;		}	      (*disk_read_func) (sector_num, 0, length);	    }	}      grub_memmove (buf, bufaddr, size);      if (errnum == ERR_WONT_FIT)        {	  if (! rawread_ignore_memmove_overflow)	      return 0;	  errnum = 0;	  buf = NULL; /* so that further memcheck() always fail */        }      else        buf += size;      byte_len -= size;		/* byte_len always >= size */      sector += num_sect;      byte_offset = 0;    } /* while (byte_len > 0 && !errnum) */  return 1;//(!errnum);}intdevread (unsigned long sector, unsigned long byte_offset, unsigned long byte_len, char *buf){  unsigned long sector_size_bits = log2_tmp(buf_geom.sector_size);  if (emu_iso_sector_size_2048)    {      emu_iso_sector_size_2048 = 0;      asm volatile ("shl%L0 %1,%0"		: "=r"(sector)		: "Ic"((int8_t)(ISO_SECTOR_BITS - sector_size_bits)),		"0"(sector));    }  /*   *  Check partition boundaries   *///grub_printf ("sector=%x, byte_offset=%x, byte_len=%x, buf=%x, part_length=%x\n", sector, byte_offset, byte_len, buf, part_length);  if (((unsigned long)(sector + ((byte_offset + byte_len - 1) >> sector_size_bits)) >= part_length) && part_start)    {      errnum = ERR_OUTSIDE_PART;      return 0;    }//  if (byte_len <= 0)//    return 1;  /*   *  Get the read to the beginning of a partition.   */  sector += byte_offset >> sector_size_bits;  byte_offset &= buf_geom.sector_size - 1;#if !defined(STAGE1_5)  if (disk_read_hook && (((unsigned long)debug) >= 0x7FFFFFFF))    printf ("<%d, %d, %d>", sector, byte_offset, byte_len);#endif /* !STAGE1_5 */  /*   *  Call RAWREAD, which is very similar, but:   *   *    --  It takes an extra parameter, the drive number.   *    --  It requires that "sector" is relative to the beginning   *            of the disk.   *    --  It doesn't handle offsets across the sector boundary.   */  return rawread (current_drive, part_start + sector, byte_offset, byte_len, buf);}#ifndef STAGE1_5/* Write 1 sector at BUF onto sector number SECTOR on drive DRIVE. * Only a 512-byte sector should be written with this function. * Return: *		1	success *		0	failure */intrawwrite (unsigned long drive, unsigned long sector, char *buf){  /* skip the write if possible. */  if (biosdisk (BIOSDISK_READ, drive, &buf_geom, sector, 1, SCRATCHSEG))    {      errnum = ERR_READ;      return 0;    }  if (! memcmp ((char *) SCRATCHADDR, buf, SECTOR_SIZE))	return 1;  memmove ((char *) SCRATCHADDR, buf, SECTOR_SIZE);  if (biosdisk (BIOSDISK_WRITE, drive, &buf_geom, sector, 1, SCRATCHSEG))    {      errnum = ERR_WRITE;      return 0;    }#if 1  if (buf_drive == drive && sector - sector % buf_geom.sectors == buf_track)    {	/* Update the cache. */	memmove ((char *) BUFFERADDR + ((sector - buf_track) << SECTOR_BITS), buf, SECTOR_SIZE);    }#else  if (sector - sector % buf_geom.sectors == buf_track)    /* Clear the cache.  */    buf_track = -1;#endif  return 1;}#endif /* ! STAGE1_5 */#ifndef STAGE1_5

⌨️ 快捷键说明

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