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

📄 builtins.c

📁 grub4dos-0.4.4-2008- 08-src.zip
💻 C
📖 第 1 页 / 共 5 页
字号:
static long expand_file(char* src,char* dst);static void ibuf_init(char* buf){  //int i;  ibuf_ptr=buf;  ibuf_pos=0;  // ibuf_tab[i]=(1<<(i+1))-1  ibuf_tab[0]=1;  for (i=1;i<16;i++)    ibuf_tab[i]=ibuf_tab[i-1]*2+1;}static unsigned short ibuf_read(int nbits){  unsigned short res;  res=(unsigned short)((*((unsigned long*)ibuf_ptr)>>ibuf_pos) & ibuf_tab[nbits-1]);  ibuf_pos+=nbits;  if (ibuf_pos>=8)    {      ibuf_ptr+=(ibuf_pos>>3);      ibuf_pos&=7;    }  return res;}#define obuf_init(buf)		obuf_ptr=buf#define obuf_putc(ch)		*(obuf_ptr++)=ch#define obuf_copy(ofs,len)	do { for (;len>0;obuf_ptr++,len--) *(obuf_ptr)=*(obuf_ptr-ofs); } while (0)// Don't use memcpy, otherwise we could be screwed !static int expand_block(int nsec){  while (nsec>0)    {      int cnt;      cnt=0x200;      while (1)        {          int flg,ofs,bts,bse,del,len;          flg=ibuf_read(2);          if (flg==0) ofs=ibuf_read(6); else            if (flg==3)              {                if (ibuf_read(1))                  {                    ofs=ibuf_read(12)+0x140;                    if (ofs==0x113F)                      break;                  }                else                  ofs=ibuf_read(8)+0x40;              } else                {                  char ch;                  cnt--;                  if (cnt<0)                    {                      grub_putstr("Data corrupted");                      return 1;                    }                  ch=ibuf_read(7);                  if (flg & 1)                    ch|=0x80;                  obuf_putc(ch);                  continue;                }          if (ofs==0)            {              grub_putstr("Data corrupted");              return 1;            }          bse=2;          del=0;          for (bts=0;bts<9;bts++)            {              if (ibuf_read(1))                break;              bse+=del+1;              del=del*2+1;            }          if (bts==9)            {              grub_putstr("Data corrupted");              return 1;            }          len=(bts)?bse+ibuf_read(bts):bse;          if ((cnt=cnt-len)<0)            {              grub_putstr("Data corrupted");              return 1;            }          obuf_copy(ofs,len);        }      nsec--;      if ((cnt) && (nsec))        {          grub_putstr("Data corrupted");          return 1;        }    }  return 0;}static long expand_file(char* src,char* dst){  ibuf_init(src);  obuf_init(dst);  if (ibuf_read(16)!=0x4D43)    {      grub_putstr("First CM signature not found");      return -1;    }  while (1)    {      unsigned short flg,len;      flg=ibuf_read(8);      len=ibuf_read(16);      if (len==0)        {          int n;          n=(ibuf_ptr-src) & 0xF;          if ((n) || (ibuf_pos))            {              ibuf_ptr+=16-n;              ibuf_pos=0;            }          if (ibuf_read(16)!=0x4D43)            {              grub_putstr("Second CM signature not found");              return -1;            }          return obuf_ptr-dst;        }      if (flg==0)        {          memcpy(obuf_ptr,ibuf_ptr,len);          ibuf_ptr+=len;          obuf_ptr+=len;        }      else        {          char* save_ptr;          unsigned short sec;          sec=(ibuf_read(16)+511)>>9;          save_ptr=ibuf_ptr;          if (ibuf_read(16)!=0x5344)            {              grub_putstr("0x5344 signature not found");              return -1;            }          ibuf_read(16);          if (expand_block(sec))            return -1;          ibuf_ptr=save_ptr+len;          ibuf_pos=0;        }    }}#endif /* ! defined(GRUB_UTIL) && ! defined (STAGE1_5) */#ifndef GRUB_UTIL/* boot */static intboot_func (char *arg, int flags){  int old_cursor, old_errnum;  struct term_entry *prev_term = current_term;  /* Clear the int15 handler if we can boot the kernel successfully.     This assumes that the boot code never fails only if KERNEL_TYPE is     not KERNEL_TYPE_NONE. Is this assumption is bad?  */  if (kernel_type != KERNEL_TYPE_NONE)    unset_int15_handler ();   /* if our terminal needed initialization, we should shut it down    * before booting the kernel, but we want to save what it was so    * we can come back if needed */  if (current_term->shutdown)     {      (*current_term->shutdown)();      current_term = term_table; /* assumption: console is first */    }#ifdef FSYS_PXE  if (kernel_type!=KERNEL_TYPE_CHAINLOADER)    pxe_unload();#endif#ifdef SUPPORT_NETBOOT  /* Shut down the networking.  */  cleanup_net ();#endif    old_cursor = setcursor (1);  errnum = 0;  //errorcheck = 1;  /* clear keyboard buffer before boot */  while (console_checkkey () != -1) console_getkey ();    switch (kernel_type)    {    case KERNEL_TYPE_FREEBSD:    case KERNEL_TYPE_NETBSD:      /* *BSD */      bsd_boot (kernel_type, bootdev, (char *) mbi.cmdline);      break;    case KERNEL_TYPE_LINUX:      /* Linux */      linux_boot ();      break;    case KERNEL_TYPE_BIG_LINUX:      /* Big Linux */      big_linux_boot ();      break;    case KERNEL_TYPE_CHAINLOADER:      /* Chainloader */            /* set boot drive to the root device.       * the boot drive should be either (fd0) or (hd0) for normal       * MS-style boot sectors. the BIOS only passes (fd0) or (hd0)       * to DL, because these two are the only devices that can be       * booted by BIOS.       *       * You should set boot drive using the rootnoverify command just       * before the boot command.       */      boot_drive = saved_drive;#ifndef GRUB_UTIL      /* extended chainloader */      if (chainloader_load_length > 512 || chainloader_boot_CS > 0 ||		chainloader_skip_length ||		chainloader_ebx_set ||		chainloader_edx_set ||		is_sdi || is_raw || //chainloader_disable_A20 ||		(chainloader_boot_IP >= 0 && chainloader_boot_IP != 0x7c00) ||		(((chainloader_load_segment >= 0)? chainloader_load_segment : 0) << 4) +		((chainloader_load_offset >= 0)? chainloader_load_offset : 0x7c00) != 0x7c00	 )	{		unsigned long read_length;		/* load high */		if (chainloader_load_segment == -1)			chainloader_load_segment = 0;		if (chainloader_load_offset == -1)		{		    if (chainloader_load_segment)			chainloader_load_offset = 0;		    else			chainloader_load_offset = 0x7c00;		}		if (chainloader_boot_CS == -1)			chainloader_boot_CS = chainloader_load_segment;		if (chainloader_boot_IP == -1)			chainloader_boot_IP = chainloader_load_offset;		/* Open the file.  */		if (! grub_open (chainloader_file))		  {		    kernel_type = KERNEL_TYPE_NONE;		    return 0;		  }	  if (is_sdi)	    {	      unsigned long long bytes_needed = filemax;	      unsigned long long base = 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;#define MIN_EMU_BASE 0x200000ULL		      if (map->Length >= bytes_needed			 && (base = (top_end - bytes_needed) & 0xfffff000) >= MIN_EMU_BASE /* page align */			 && map->Length >= top_end - base)				break; /* success */		      base = 0;		    }	        }	      else		  grub_printf ("Address Map BIOS Interface is not activated.\n");	      if (base < MIN_EMU_BASE)		{		  grub_close ();		  return ! (errnum = ERR_WONT_FIT);		}      #undef MIN_EMU_BASE	      //filepos = 0;	      if (grub_read ((char *)((int)base), -1) != filemax)		{			grub_close ();			if (errnum == ERR_NONE)				errnum = ERR_READ;			return 0;		}	      grub_close ();      	      unset_int13_handler (0);      #define BootCodeOffsetLow (*(unsigned long *)((int)base + 0x10))#define BootCodeSizeLow  (*(unsigned long *)((int)base + 0x18))	      read_length = BootCodeSizeLow;	      if (read_length > 0x90000)		  read_length = 0x90000;	      grub_memmove((char *)0x200000, (char *)((unsigned int)base + BootCodeOffsetLow), read_length);#undef BootCodeOffsetLow#undef BootCodeSizeLow	      if (! chainloader_edx_set)		{		  chainloader_edx = (unsigned int)base | 0x41;		  chainloader_edx_set = 1;		}	    }else{		/* Read the first 640K */		read_length = filemax - chainloader_skip_length;		filepos = ((*(unsigned short *)0x413)<<10) - (chainloader_load_segment<<4) - chainloader_load_offset;		if (read_length > filepos)		    read_length = filepos;		filepos = chainloader_skip_length;		/* read the new loader to physical address 2MB, overwriting		 * the backup area of DOS memory.		 */		if (grub_read ((char *) 0x200000, read_length) != read_length)		  {		    grub_close ();		    kernel_type = KERNEL_TYPE_NONE;		    if (errnum == ERR_NONE)			errnum = ERR_EXEC_FORMAT;      		    break;		  }		grub_close ();#ifdef FSYS_PXE                pxe_unload();#endif		/* WinMe support by bean. Thanks! */				// Not a very neat way to test WinME, works anyway		if ((*(unsigned short*)0x200000==0x4D43) &&		    // ((*(char*)0x110002==0) || (*(unsigned short*)0x110000==0x4D43)) &&		    (chainloader_skip_length==0x800))		  {		    unsigned long len;		    len=(unsigned long)expand_file((char*)0x200000,(char*)0x2A0000);		    if (len==0xffffffff || len==0)		      {			kernel_type = KERNEL_TYPE_NONE;			errnum = ERR_EXEC_FORMAT;			break;		      }		    grub_memmove((char*)0x200000,(char*)0x2A0000,len);		    chainloader_load_length=read_length=len;		  }		/* create boot info table for isolinux */		if (is_isolinux)		{			int p;			query_block_entries = -1; /* query block list only */			blocklist_func (chainloader_file, flags);			if (errnum)				break;			if (query_block_entries != 1)			{				errnum = ERR_NON_CONTIGUOUS;				break;			}			*(unsigned long*)0x20000C = map_start_sector;			*(unsigned long*)0x200010 = chainloader_load_length;			old_errnum = 0; /* init to calculate the checksum */			*(unsigned long*)(0x200000 + chainloader_load_length) = 0;			for (p = 0; p < (chainloader_load_length - 0x40 + 3) / 4; p++)			{				old_errnum += *(long *)(0x200040 + (p << 2));			}			*(unsigned long*)0x200014 = old_errnum; /* checksum */		}		/* Turn off A20 here if --disable-a20 was specified.		 * Note: we won't have access to the odd megas of the memory		 * when A20 is off.		 */		if (chainloader_disable_A20)		{			if (! gateA20 (0))			{				/* to asure A20 is on when we return to grub. */				gateA20 (1);	/* turn on A20 in case it is off */				errnum = ERR_DISABLE_A20;				break;			}			if (debug > 0)				grub_printf("\nGate A20 is turned off successfully.\n");		}		if (! chainloader_edx_set)		{			chainloader_edx_set = 1;			chainloader_edx = boot_drive;		}		if (chainloader_edx & 0x80)		{		  if (! probe_bpb((struct master_and_dos_boot_sector *)0x200000))			if (*((unsigned long *) (0x20001C)) == 0)			{			    if (probe_mbr ((struct master_and_dos_boot_sector *)0x200000, 0, ((chainloader_load_length + 511) >> 9), 0))			    {				errnum = ERR_HD_VOL_START_0;		  		break;			    }			}		} else {		  /* clear number of hidden sectors for floppy */		  if (! probe_bpb((struct master_and_dos_boot_sector *)0x200000))    			if (*((unsigned long *) (0x20001C)))        		    *((unsigned long *) (0x20001C)) = 0;		}			    }				if (chainloader_load_length == -1 || chainloader_load_length > read_length)			chainloader_load_length = read_length;		

⌨️ 快捷键说明

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