📄 expios.c
字号:
// This utility is used to test the expansion function
#ifdef __unix
#include <unistd.h>
#else
#include <io.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define grub_putstr puts
void quit(char* msg)
{
grub_putstr(msg);
exit(1);
}
static int ibuf_pos;
static char *ibuf_ptr,*obuf_ptr;
static unsigned short ibuf_tab[16];
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;
}
}
}
int main(int argc,char** argv)
{
int hd;
char *src,*dst;
long len0,len1;
if (argc<2)
{
grub_putstr("Usage:\n expios input [output]");
exit(1);
}
if ((hd=open(argv[1],O_RDONLY | O_BINARY))<0)
quit("Can\'t open input file");
if ((len0=lseek(hd,0,SEEK_END))==-1L)
quit("Can\'t get the file size");
if (len0>=0xA0000)
quit("File too large to be IO.SYS");
lseek(hd,0,SEEK_SET);
if (((src=malloc(len0))==NULL) || ((dst=malloc(0xA0000))==NULL))
quit("Not enough memory");
if (read(hd,src,len0)!=len0)
quit("Read from input file fails");
close(hd);
if ((*((unsigned short*)src)!=0x5A4D) || (*((unsigned short*)(src+0x7FE))!=0x534D))
quit("Input file is not a valid IO.SYS");
memcpy(dst,src,0x800);
if ((len1=expand_file(src+0x800,dst+0x800))<0)
exit(1);
len1+=0x800;
free(src);
if (argc>=3)
{
if ((hd=open(argv[2],O_RDWR | O_CREAT | O_TRUNC | O_BINARY,S_IREAD | S_IWRITE))<0)
quit("Can\'t open output file");
if (write(hd,dst,len1)!=len1)
quit("Write to output file fails");
close(hd);
}
free(dst);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -