📄 grub-winme-c-1129
字号:
diff -NaurbB -X ../patch/grub.skip grub-0.97.org/stage2/builtins.c grub-0.97/stage2/builtins.c--- grub-0.97.org/stage2/builtins.c Sat Dec 10 03:57:03 2005+++ grub-0.97/stage2/builtins.c Sat Dec 10 06:59:09 2005@@ -327,6 +327,186 @@ "Print the blocklist notation of the file FILE." }; +// The following routines are used to decompress IO.SYS from WinME++static int ibuf_pos;+static char *ibuf_ptr,*obuf_ptr;+static unsigned short ibuf_tab[16];++void ibuf_init(char* buf);+unsigned short ibuf_read(int nbits);+int expand_block(int nsec);+long expand_file(char* src,char* dst);++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;+}++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 !++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;+}++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;+ }+ }+}+ /* boot */ static int boot_func (char *arg, int flags)@@ -550,6 +730,24 @@ return 1; } grub_close ();++ // Not a very neat way to test WinME, works anyway+ if ((*(unsigned short*)0x110000==0x4D43) &&+ ((*(char*)0x110002==0) || (*(unsigned short*)0x110000==0x4D43)) &&+ (chainloader_skip_length==0x800))+ {+ unsigned long len;+ len=expand_file((char*)0x110000,(char*)0x1B0000);+ if (len==0)+ {+ kernel_type = KERNEL_TYPE_NONE;+ if (errnum ==ERR_NONE)+ errnum = ERR_EXEC_FORMAT;+ return 1;+ }+ grub_memmove((char*)0x110000,(char*)0x1B0000,len);+ chainloader_load_length=read_length=len;+ } } if (chainloader_load_length == -1 || chainloader_load_length > read_length)@@ -989,7 +1187,7 @@ } else if (*(short *)BOOTSEC_LOCATION == 0x5A4D && filemax > 0x10000 &&- (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET)) == 0 /* != BOOTSEC_SIGNATURE */ && (*(long *)(BOOTSEC_LOCATION + 0xA2)) == 0 ))+ (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET)) == 0)) // /* != BOOTSEC_SIGNATURE */ && (*(long *)(BOOTSEC_LOCATION + 0xA2)) == 0 )) { int err;@@ -1026,11 +1224,27 @@ chainloader_load_length = filemax; if (chainloader_skip_length == 0) chainloader_skip_length = 0x0800;++ // Input parameter for SYSINIT+ // BX,AX: Start sector for the data area of FAT. It doesn't needs to+ // be set. However, we should at least clear BX, otherwise,+ // it would have some minor problem when booting WinME.+ // DI: Length of the boot code, don't need to be set.+ // BP: 0x7C00, boot sector pointer, don't need to be set.+ // DH: Media ID (BS[0x15]) , 0xF0 for floppy, 0xF8 for harddisk+ // DL: Drive number (BS[0x40] for FAT32)+ if (! chainloader_edx_set) {- chainloader_edx = current_drive | ((current_partition >> 8) & 0xFF00);+ //chainloader_edx = current_drive | ((current_partition >> 8) & 0xFF00);+ chainloader_edx = current_drive | 0xF000 | ((current_drive & 0x80)<<4); chainloader_edx_set = 1; }+ if (! chainloader_ebx_set)+ {+ chainloader_ebx = 0;+ chainloader_ebx_set = 1;+ } grub_printf("Will boot MS-DOS 7.x from drive=0x%x\n", (chainloader_edx & 0x80)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -