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

📄 bios.c

📁 GRUB 0.93的源代码。有人说可以当一个很小的操作系统了
💻 C
字号:
/* bios.c - implement C part of low-level BIOS disk input and output *//* *  GRUB  --  GRand Unified Bootloader *  Copyright (C) 1999,2000  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"/* These are defined in asm.S, and never be used elsewhere, so declare the   prototypes here.  */extern int biosdisk_int13_extensions (int ah, int drive, void *dap);extern int biosdisk_standard (int ah, int drive,			      int coff, int hoff, int soff,			      int nsec, int segment);extern int check_int13_extensions (int drive);extern int get_diskinfo_int13_extensions (int drive, void *drp);extern int get_diskinfo_standard (int drive,				  unsigned long *cylinders,				  unsigned long *heads,				  unsigned long *sectors);#if 0extern int get_diskinfo_floppy (int drive,				unsigned long *cylinders,				unsigned long *heads,				unsigned long *sectors);#endif/* 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;    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;      } dap;      /* XXX: Don't check the geometry by default, because some buggy	 BIOSes don't return the number of total sectors correctly,	 even if they have working LBA support. Hell.  */#ifdef NO_BUGGY_BIOS_IN_THE_WORLD      if (sector >= geometry->total_sectors)	return BIOSDISK_ERROR_GEOMETRY;#endif /* NO_BUGGY_BIOS_IN_THE_WORLD */      /* FIXME: sizeof (DAP) must be 0x10. Should assert that the compiler	 can't add any padding.  */      dap.length = sizeof (dap);      dap.block = sector;      dap.blocks = nsec;      dap.reserved = 0;      /* This is undocumented part. The address is formated in	 SEGMENT:ADDRESS.  */      dap.buffer = segment << 16;            err = biosdisk_int13_extensions (read + 0x42, drive, &dap);/* #undef NO_INT13_FALLBACK */#ifndef NO_INT13_FALLBACK      if (err)	{	  geometry->flags &= ~BIOSDISK_FLAG_LBA_EXTENSION;	  geometry->total_sectors = (geometry->cylinders				     * geometry->heads				     * geometry->sectors);	  return biosdisk (read, drive, geometry, sector, nsec, segment);	}#endif /* ! NO_INT13_FALLBACK */          }  else    {      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;      err = biosdisk_standard (read + 0x02, drive,			       cylinder_offset, head_offset, sector_offset,			       nsec, segment);    }  return err;}/* 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;  /* Clear the flags.  */  geometry->flags = 0;    if (drive & 0x80)    {      /* hard disk */      int version;      unsigned long total_sectors = 0;            version = check_int13_extensions (drive);      if (version)	{	  struct drive_parameters	  {	    unsigned short size;	    unsigned short flags;	    unsigned long cylinders;	    unsigned long heads;	    unsigned long sectors;	    unsigned long long total_sectors;	    unsigned short bytes_per_sector;	    /* ver 2.0 or higher */	    unsigned long EDD_configuration_parameters;	    /* ver 3.0 or higher */	    unsigned short signature_dpi;	    unsigned char length_dpi;	    unsigned char reserved[3];	    unsigned char name_of_host_bus[4];	    unsigned char name_of_interface_type[8];	    unsigned char interface_path[8];	    unsigned char device_path[8];	    unsigned char reserved2;	    unsigned char checksum;	    /* XXX: This is necessary, because the BIOS of Thinkpad X20	       writes a garbage to the tail of drive parameters,	       regardless of a size specified in a caller.  */	    unsigned char dummy[16];	  } __attribute__ ((packed)) drp;	  /* It is safe to clear out DRP.  */	  grub_memset (&drp, 0, sizeof (drp));	  	  drp.size = sizeof (drp);	  err = get_diskinfo_int13_extensions (drive, &drp);	  if (! err)	    {	      /* Set the LBA flag.  */	      geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION;	      /* I'm not sure if GRUB should check the bit 1 of DRP.FLAGS,		 so I omit the check for now. - okuji  */	      /* if (drp.flags & (1 << 1)) */	       	      /* FIXME: when the 2TB limit becomes critical, we must		 change the type of TOTAL_SECTORS to unsigned long		 long.  */	      if (drp.total_sectors)		total_sectors = drp.total_sectors & ~0L;	      else		/* Some buggy BIOSes doesn't return the total sectors		   correctly but returns zero. So if it is zero, compute		   it by C/H/S returned by the LBA BIOS call.  */		total_sectors = drp.cylinders * drp.heads * drp.sectors;	    }	}      /* Don't pass GEOMETRY directly, but pass each element instead,	 so that we can change the structure easily.  */      err = get_diskinfo_standard (drive,				   &geometry->cylinders,				   &geometry->heads,				   &geometry->sectors);      if (err)	return err;      if (! total_sectors)	{	  total_sectors = (geometry->cylinders			   * geometry->heads			   * geometry->sectors);	}      geometry->total_sectors = total_sectors;    }  else    {      /* floppy disk */      /* First, try INT 13 AH=8h call.  */      err = get_diskinfo_standard (drive,				   &geometry->cylinders,				   &geometry->heads,				   &geometry->sectors);#if 0      /* If fails, then try floppy-specific probe routine.  */      if (err)	err = get_diskinfo_floppy (drive,				   &geometry->cylinders,				   &geometry->heads,				   &geometry->sectors);#endif            if (err)	return err;      geometry->total_sectors = (geometry->cylinders				 * geometry->heads				 * geometry->sectors);    }  return 0;}

⌨️ 快捷键说明

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