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

📄 bios.c

📁 grub4dos-0.4.4-2008- 08-src.zip
💻 C
📖 第 1 页 / 共 2 页
字号:
/* bios.c - implement C part of low-level BIOS disk input and output *//* *  GRUB  --  GRand Unified Bootloader *  Copyright (C) 1999,2000,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 "iso9660.h"/* These are defined in asm.S, and never be used elsewhere, so declare the   prototypes here.  */extern int biosdisk_standard (int ah, int drive,			      int coff, int hoff, int soff,			      int nsec, int segment);extern int get_diskinfo_standard (int drive,				  unsigned long *cylinders,				  unsigned long *heads,				  unsigned long *sectors);extern struct drive_map_slot hooked_drive_map[DRIVE_MAP_SIZE + 1];/* Read/write NSEC sectors starting from SECTOR in DRIVE disk with GEOMETRY   from/into SEGMENT segment. If READ is BIOSDISK_READ, then read it,   else if READ is BIOSDISK_WRITE, then write it. If an geometry error   occurs, return BIOSDISK_ERROR_GEOMETRY, and if other error occurs, then   return the error number. Otherwise, return 0.  */intbiosdisk (int read, int drive, struct geometry *geometry,	  int sector, int nsec, int segment){  int err;    /* first, use EBIOS if possible */  if (geometry->flags & BIOSDISK_FLAG_LBA_EXTENSION)    {      struct disk_address_packet      {	unsigned char length;	unsigned char reserved;	unsigned short blocks;	unsigned long buffer;	unsigned long long block;		/* This structure is passed in the stack. A buggy BIOS could write	 * garbage data to the tail of the struct and hang the machine. So	 * we need this protection. - Tinybit	 */	unsigned char dummy[16];      } __attribute__ ((packed)) *dap;      /* Even the above protection is not enough to avoid stupid actions by       * buggy BIOSes. So we do it in the 0040:0000 segment. - Tinybit       */      dap = (struct disk_address_packet *)0x580;      if (drive == 0xffff || (drive == ram_drive && rd_base != 0xffffffff))      {	char *disk_sector;	char *buf_address;		if (nsec <=0 || nsec >= 0x80)		return 1;	/* failure */		disk_sector = (char *)((sector<<9) + ((drive==0xffff) ? 0 : rd_base));	buf_address = (char *)(segment<<4);	if (read)	/* read == 1 really means write to DISK */		grub_memmove (disk_sector, buf_address, nsec << 9);	else		/* read == 0 really means read from DISK */		grub_memmove (buf_address, disk_sector, nsec << 9);			return 0;	/* success */      }      dap->length = 0x10;      dap->block = sector;      dap->blocks = nsec;      dap->reserved = 0;      dap->buffer = segment << 16;      #ifndef STAGE1_5//      if (debug > 0)//	grub_printf ("Debug: biosdisk: AH=42, drive=%x, sector=%x, nsec=%x, segment=%x ...", drive, sector, nsec, segment);#endif      err = biosdisk_int13_extensions ((read + 0x42) << 8, drive, dap);#ifndef STAGE1_5//      if (debug > 0)//	/* wipe out debug message. *///	grub_printf ("\r                                                                             \r");#endif      if (!err)	return 0;	/* success */      /* bootable CD-ROM specification has no standard CHS-mode call */      if (geometry->flags & BIOSDISK_FLAG_CDROM)      {#ifndef STAGE1_5	if (debug > 1)	  grub_printf ("biosdisk_int13_extensions read=%d, drive=0x%x, dap=%x, err=0x%x\n", read, drive, dap, err);#endif	return err;      }    } /* if (geometry->flags & BIOSDISK_FLAG_LBA_EXTENSION) */   /* try the standard CHS mode */      {      int cylinder_offset, head_offset, sector_offset;      int head;      /* SECTOR_OFFSET is counted from one, while HEAD_OFFSET and	 CYLINDER_OFFSET are counted from zero.  */      sector_offset = sector % geometry->sectors + 1;      head = sector / geometry->sectors;      head_offset = head % geometry->heads;      cylinder_offset = head / geometry->heads;      //      if (cylinder_offset >= geometry->cylinders)//	return BIOSDISK_ERROR_GEOMETRY;#ifndef STAGE1_5//      if (debug > 0)//	grub_printf ("Debug: biosdisk: AH=02, drive=%x, C=%x, H=%x, S=%x, nsec=%x, segment=%x ...", drive, cylinder_offset, head_offset, sector_offset, nsec, segment);#endif      err = biosdisk_standard (read + 0x02, drive,			       cylinder_offset, head_offset, sector_offset,			       nsec, segment);#ifndef STAGE1_5//      if (debug > 0)//	/* wipe out debug message. *///	grub_printf ("\r                                                                             \r");#endif    }  return err;}/* Check bootable CD-ROM emulation status.   * Return 0 on failure.  */intget_cdinfo (int drive, struct geometry *geometry){  int err;  struct iso_spec_packet  {    unsigned char size;    unsigned char media_type;    unsigned char drive_no;    unsigned char controller_no;    unsigned long image_lba;    unsigned short device_spec;    unsigned short cache_seg;    unsigned short load_seg;    unsigned short length_sec512;    unsigned char cylinders;    unsigned char sectors;    unsigned char heads;        unsigned char dummy[16];  } __attribute__ ((packed));    struct iso_spec_packet *cdrp;    cdrp = (struct iso_spec_packet *)0x580;  grub_memset (cdrp, 0, sizeof (struct iso_spec_packet));  cdrp->size = sizeof (struct iso_spec_packet) - 16;#ifndef STAGE1_5//      if (debug > 0)//	grub_printf ("Debug: get_cdinfo: AX=4B01, drive=%x ...", drive);#endif#ifndef STAGE1_5  if (debug > 1)	grub_printf (" int13/4B01(%X),", drive);#endif  err = biosdisk_int13_extensions (0x4B01, drive, cdrp);#ifndef STAGE1_5  if (debug > 1)	grub_printf ("err=%X,drive=%X, ", err, drive);#endif#ifndef STAGE1_5//      if (debug > 0)//	/* wipe out debug message. *///	grub_printf ("\r                                                                             \r");#endif  if (drive == 0x7F && drive < cdrp->drive_no)	drive = cdrp->drive_no;  if (! err && cdrp->drive_no == drive && !(cdrp->media_type & 0x0F))    {//    if ((cdrp.media_type & 0x0F) == 0)//	{          /* No-emulation mode bootable CD-ROM */          geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION | BIOSDISK_FLAG_CDROM;          geometry->cylinders = 65536; // 0;          geometry->heads = 255; //1;          geometry->sectors = 15;          geometry->sector_size = 2048;          geometry->total_sectors = 65536 * 255 * 15; //MAXINT;	  return drive;//	}//    else//	{//	  /* Floppy or hard-disk emulation *///	  geometry->cylinders//	    = ((unsigned int) cdrp.cylinders//	       + (((unsigned int) (cdrp.sectors & 0xC0)) << 2));//	  geometry->heads = cdrp.heads;//	  geometry->sectors = cdrp.sectors & 0x3F;//	  geometry->sector_size = SECTOR_SIZE;//	  geometry->total_sectors = (geometry->cylinders//				     * geometry->heads//				     * geometry->sectors);//	  return -1;//	}    }  return 0;	/* failure */}/* Return the geometry of DRIVE in GEOMETRY. If an error occurs, return   non-zero, otherwise zero.  */intget_diskinfo (int drive, struct geometry *geometry){  int err;  int version;  unsigned long long total_sectors = 0, tmp = 0;  unsigned long flags;        struct drive_parameters *drp;  drp = (struct drive_parameters *)0x580;  if (drive == 0xffff)	/* memory disk */    {      unsigned long long total_mem_bytes;      total_mem_bytes = 0;      if (mbi.flags & MB_INFO_MEM_MAP)        {          struct AddrRangeDesc *map = (struct AddrRangeDesc *) saved_mmap_addr;          unsigned long end_addr = saved_mmap_addr + saved_mmap_length;          for (; end_addr > (unsigned long) map; map = (struct AddrRangeDesc *) (((int) map) + 4 + map->size))	    {	      unsigned long long top_end;	      if (map->Type != MB_ARD_MEMORY)		  continue;	      top_end =  map->BaseAddr + map->Length;	      if (top_end > 0x100000000ULL)		  top_end = 0x100000000ULL;	      if (total_mem_bytes < top_end)		  total_mem_bytes = top_end;	    }        }      else	  grub_printf ("Address Map BIOS Interface is not activated.\n");      if (total_mem_bytes)      {	geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION;	geometry->sector_size = SECTOR_SIZE;	geometry->total_sectors = (total_mem_bytes /*+ SECTOR_SIZE - 1*/) >> SECTOR_BITS;	geometry->heads = 255;	geometry->sectors = 63;	geometry->cylinders = (geometry->total_sectors + 255 * 63 -1) / (255 * 63);	return 0;      }          } else if (drive == ram_drive)	/* ram disk device */    {      if (rd_base != 0xffffffff)      {	geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION;	geometry->sector_size = SECTOR_SIZE;	geometry->total_sectors = (rd_size ? ((rd_size + SECTOR_SIZE - 1)>> SECTOR_BITS) : 0x800000);	geometry->heads = 255;	geometry->sectors = 63;	geometry->cylinders = (geometry->total_sectors + 255 * 63 -1) / (255 * 63);	return 0;      }    }#if defined(GRUB_UTIL) || defined(STAGE1_5)  if (drive == cdrom_drive)#else  if (drive == cdrom_drive || (drive >= min_cdrom_id && drive < min_cdrom_id + atapi_dev_count))#endif  {	/* No-emulation mode bootable CD-ROM */	geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION | BIOSDISK_FLAG_CDROM;	geometry->cylinders = 65536;	geometry->heads = 255;	geometry->sectors = 15;	geometry->sector_size = 2048;	geometry->total_sectors = 65536 * 255 * 15;	return 0;  }  /* Clear the flags.  */  flags = 0;  #ifdef GRUB_UTIL#define FIND_DRIVES 8#else#define FIND_DRIVES (*((char *)0x475))#endif      if (drive >= 0x80 + FIND_DRIVES /* || (version && (drive & 0x80)) */ )#undef FIND_DRIVES	{	  /* Possible CD-ROM - check the status.  */	  if (get_cdinfo (drive, geometry))	    return 0;	}      #if (! defined(GRUB_UTIL)) && (! defined(STAGE1_5))    {	unsigned long j;	unsigned long d;	/* check if the drive is virtual. */	d = drive;	j = DRIVE_MAP_SIZE;		/* real drive */	if (! unset_int13_handler (1))	    for (j = 0; j < DRIVE_MAP_SIZE; j++)	    {		if (drive != hooked_drive_map[j].from_drive)			continue;		if ((hooked_drive_map[j].max_sector & 0x3F) == 1 && hooked_drive_map[j].start_sector == 0 && hooked_drive_map[j].sector_count <= 1)		{			/* this is a map for the whole drive. */			d = hooked_drive_map[j].to_drive;			j = DRIVE_MAP_SIZE;	/* real drive */		}		break;	    }	if (j == DRIVE_MAP_SIZE)	/* real drive */	{	    if (d >= 0x80 && d < 0x84)	    {		d -= 0x80;		if (hd_geom[d].sector_size == 512 && hd_geom[d].sectors > 0 && hd_geom[d].sectors <= 63 && hd_geom[d].heads <= 256)		{			geometry->flags = hd_geom[d].flags;			geometry->sector_size = hd_geom[d].sector_size;			geometry->total_sectors = hd_geom[d].total_sectors;			geometry->heads = hd_geom[d].heads;			geometry->sectors = hd_geom[d].sectors;			geometry->cylinders = hd_geom[d].cylinders;			return 0;		}	    } else if (d < 4) {		if (fd_geom[d].sector_size == 512 && fd_geom[d].sectors > 0 && fd_geom[d].sectors <= 63 && fd_geom[d].heads <= 256)		{			geometry->flags = fd_geom[d].flags;			geometry->sector_size = fd_geom[d].sector_size;			geometry->total_sectors = fd_geom[d].total_sectors;			geometry->heads = fd_geom[d].heads;

⌨️ 快捷键说明

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