无忧启动论坛

标题: 制作光盘启动的源程序,请大家研究 [打印本页]

作者: 超想居士    时间: 2001-8-29 22:24
标题: 制作光盘启动的源程序,请大家研究
/* mkbootcd - make El Torito bootable CD image */
/* O.imaizumi, gigo@yk.rim.or.jp | imaizumi@nisiq.net */
/* 18-Aug-97 Version 1.00 */
/* Known Limitation(to do) */
/* can't treat Extensions (who use this ?) */
/* compiler VC++ or MSC6.00A or gcc for x86  */
#ifdef __FreeBSD__
/* gcc */
#define stricmp(a,b) strcasecmp(a,b)
#endif
#ifdef __NetBSD__
/* gcc */
#define stricmp(a,b) strcasecmp(a,b)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#define byte unsigned char
#define word unsigned short int
#define dword unsigned long
#define VD_LBN  (16+baselbn)
#define BRVD_LBN (17+baselbn)
#define CDSCT 2048L
#pragma pack(1)
/* ISO9660 FileDir */
typedef struct FileDir_t {
    dword Lbn;
    dword Lbn_b; /* big indian */
    dword Len;
    dword Len_b; /* big indian */
    byte  Year;
    byte  Month;
    byte  Date;
    byte  Hour;
    byte  Minute;
    byte  Sec;
    byte  TZoffset;
    byte  Flag;
    byte  stab[6];
    byte  NameLen;
} FileDir;
/* Volume Descriptor at VD_LBN */
typedef struct VD_t {
    byte  Indicator;        /*0x00:    indicator must be 1 */
    byte  Identifier[5];    /*0x01:    ISO9660 Identifier must be 'CD001' */
    byte  Version;          /*0x06:    version of this descriptor must be one. */
    byte  stab;             /*0x07:    must be zero. */
    byte  SysIdentifier[32];/*0x08-27: */
    byte  VolIdentifier[32];/*0x28-47: */
    dword stabw_l;          /*0x48-4b: */
    dword stabw_b;          /*0x4c-4f: */
    dword totsct_l;         /*0x50-53: */
    dword totsct_b;         /*0x54-57: */
    byte  Zeros[32];        /*0x58-77: */
    word  vsetsiz;          /*0x78-79: */
    word  vsetsiz_b;        /*0x7a-7b: */
    word  vsetseq;          /*0x7c-7d: */
    word  vsetseq_b;        /*0x7e-7f: */
    word  sctlen;           /*0x80-81: */
    word  sctlen_b;         /*0x82-83: */
    dword ptblen;           /*0x84-87: */
    dword ptblen_b;         /*0x88-8b: */
    dword lptbLbn1;         /*0x8c-8f: */
    dword lptbLbn2;         /*0x90-93: */
    dword bptbLbn1_b;       /*0x94-97: */
    dword bptbLbn2_b;       /*0x98-9b: */
    byte  dirlen;           /*0x9c:*/
    byte  stabb;            /*0x9d:*/
    FileDir rootdir;        /*0x9e-bc:*/
    byte  rootname;         /*0xbd: */
    byte  VSIdentifier[128];/*0xbe-13d: */
    byte  PBIdentifier[128];/*0x13e-1bd: */
    byte  DPIdentifier[128];/*0x1be-23d: */
    byte  APIdentifier[128];/*0x23e-2bd: */
    byte  CrIdentifier[37]; /*0x2be-2e2: */
    byte  AbIdentifier[37]; /*0x2e3-307: */
    byte  BiIdentifier[37]; /*0x308-32c: */
    byte  VcDate[17];
    byte  MdDate[17];
    byte  VeDate[17];
    byte  EfDate[17];
    byte  stabone;
    byte  stabzero;
    byte  reserve[512];
    byte  zeros2[653];
} VD;
/* Boot Record Volume Descriptor at BRVD_LBN */
typedef struct BRVD_t {
    byte  Indicator;        /*0x00:    Boot record indicator must be 0 */
    byte  Identifier[5];    /*0x01:    ISO9660 Identifier must be 'CD001' */
    byte  Version;          /*0x06:    version of this descriptor must be zero. */
    byte  BSIdentifier[32]; /*0x07-26: must be "EL TORITO SPECIFICATION" padded with 0 s.*/
    byte  stab0[32];        /*0x27-47: Unused, must be 0. */
    dword BootCatLbn;       /*0x47-4a: Absolute pointer to first sector of Boot Catalog */
    byte  stab1[0x7b5];     /*0x4b-7ff:Unused, must be 0. */
} BRVD;
/* Validation Entry at top of boot catalog */
typedef struct VE_t {
    byte  HeaderID;         /*0x00:    must be 01 */
    byte  PlatformID;       /*0x01:    0=80x86, 1=PowerPC, 2=Mac */
    word  reserve;          /*0x02-3:  Reserved must be 0 */
    char  ID[24];           /*0x04-1B: ID string. This is intended to identify */
                            /*           manufacturer/developer of the CD-ROM */
    short int CheckSum;     /*0x1C-1D: Checksum Word. */
    byte  KeyByte1;         /*0x1E:    Key byte, must be 0x55 */
    byte  KeyByte2;         /*0x1F:    Key byte, must be 0xAA */
} VE;
/* Defaults */
byte PlatformID = 0;    /* option -P */
/* section entry */
typedef struct sectionEntry_t {
    byte  HeaderIndicator;  /*0x00:    0x90 -Header, more headers follow, 91 - Final Header */
    byte  PlatformID;       /*0x01:    0=80x86, 1=PowerPC, 2=Mac */
    word  EntryCount;       /*0x02-03: number of entry */
    char  ID[28];           /*0x04-1F: ID string. This is intended to identify */
} SE;
/* Defaults */
char    SectionID[28];  /* option -S */
/* boot Entry */
typedef struct bootEntry_t {
    byte  bootIndicator;    /*0x00:    0x88=Bootable, 0x00 not Bootable */
    byte  bootMediaType;    /*0x01:    0=NO Emulation, 1=1.2MFD, 2=1.44MFD, 3=2.88MFD,4 =HDD */
    word  bootLoadSegment;  /*0x02-03: if 0, traditional 0x7c0 */
    byte  bootSystemType;   /*0x04:    must be a copy of byte 5(System Type) from the */
                            /*         Partition Table found in boot image. */
    byte  stab;             /*0x05:    Unused, must be 0. */
    word  bootSectorCount;  /*0x06-07: number of virtual/emulated sectors during the initial
                            /*         boot procedure */
    dword bootLoadRBA;      /*0x08-0b: start address of the virtual disk. */
    byte  stab2[20];        /*0x0c-1f: Unused, must be 0. */
} BE;
/* defaults */
byte bootIndicator = 0x88;      /* option -I */
byte bootMediaType = 0xf;       /* option -T */
word bootLoadSegment = 0x7C0;   /* option -L */
word bootSectorCount = 1;       /* option -C */
byte bootMediaTypeFlags = 0;    /* option -F */
/* Floppy Disk Boot Sector */
typedef struct FDBS_t {
    byte  JumpByte[1];
    byte  stab1[2];
    char  OemData[8];
    word  BytesPerSector;
    byte  stab2[6];
    word  NumberOfSectors;
    byte  MediaByte[1];
    byte  stab3[2];
    word  SectorsPerTrack;
    word  NumberOfHeads;
    byte  stab4[482];
    byte  KeyByte1;         /*0x1E:    Key byte, must be 0x55 */
    byte  KeyByte2;         /*0x1F:    Key byte, must be 0xAA */
} FDBS;
/* Partition data table */
typedef struct PDT_t {
    byte  BootIndicator;
    byte  BeginningSectorHeadNumber;
    byte  BeginningSector;      /* 2 high bits of cylinder #) */
    byte  BeginningCylinder;    /* low order bits of cylinder */
    byte  SystemIndicator;
    byte  EndingSectorHeadNumber;
    byte  EndingSector;         /* 2 high bits of cylinder # */
    byte  EndingCylinder;       /* low order bits of cylinder */
    dword SctPrePar;
    dword SctInPar;
} PDT;
#pragma pack()
FILE    *ISOFile,*image;
BRVD    BRVDBuf;
VE      VEBuf;
BE      BEBuf;
SE      SEBuf;
FileDir rootDir,DirBuf;
char    FileNameBuf[129];
byte    SctBuf[512];
char    cmdbuf[128],namebuf[128];
long    CurEntryLoc,SectionEntry,BootCatEnd;
PDT     *PDTp;  /* Partition Table */
int     argn = 1;
int     ind = 0;
int     Error = 0;
intWarn = 0;
int     numSection = 0;
word    numEntry = 0;
long    offset = 0L;
dword   baselbn = 0L;
char    DrvLetter = 'Q';
long    imageEndPos;    /* Physical iamge file end */
word    ExpectedNumberOfSectors[] = {0,2400,2880,5760};
int adjFlag = 0;
#ifdef DEBUG
long    entrybase;
#endif
int checkBRVD(void);
int checkVE(void);
int checkSE(void);
int checkBE(void);
int checkZero(byte *p ,int n);
FileDir *getFileDir(char *name);
FileDir *getDirEntry(char *name, long DirPos, long DirLen, int type);
void FileDirList(char *name,FileDir *FileDirBufP);
void xfread(FILE *fp, long loc, void *bufp, int size, char *ErrMsg);
void xfwrite(FILE *fp, long loc, void *bufp, int size, char *ErrMsg);
void fail(void);
void mkVaEntry(void);
void mkSection(int type);
void mkBootEntry(char *name);
char *getcmd(int argc,char *argv[]);
int  checkBootImage(void);
dword dswab(dword big);
void offsetAdj(void);
void usage(void);
void main(int argc,char *argv[])
{
    char *cmd;
    VD *VDp;
    FileDir *FileDirP;
#ifdef DEBUG
    if (sizeof(BRVD)!=0x800 || sizeof(VE)!=32 || sizeof(SE) !=32 || sizeof(BE) !=32) {
        printf("Definition Error.\n");
        printf("sizeof(byte):%d - expected 1.\n",sizeof(byte));
        printf("sizeof(word):%d - expected 2.\n",sizeof(word));
        printf("sizeof(dword):%d - expected 4.\n",sizeof(dword));
        printf("sizeof(short int):%d - expected 2.\n",sizeof(short int));
        printf("sizeof(BRVD):%d - expected 2048.\n",sizeof(BRVD));
        printf("sizeof(VE):%d - expected 32.\n",sizeof(VE));
        printf("sizeof(SE):%d - expected 32.\n",sizeof(SE));
        printf("sizeof(BE):%d - expected 32.\n",sizeof(BE));
        printf("sizeof(FDBS):%d - expected 512.\n",sizeof(FDBS));
        printf("sizeof(VD):%d - expected 2048.\n",sizeof(VD));
        printf("sizeof(FileDir):%d - expected 31.\n",sizeof(FileDir));
        exit(1);
    }
#endif
    printf("mkbootcd - make bootable CD image(El Torito specification)\n");
    printf("18-Aug-97 gigo@yk.rim.or.jp|imaizumi@nisiq.net V1.00\n");
    if (argc < 2)
        usage();
    if ((cmd = getcmd(argc,argv)) == NULL)
        usage();
    if ((ISOFile = fopen(cmd,"r+b")) == NULL) {
        printf("\n*Error - can't open ISO image file -- '%s' !\n",cmd);
        exit(1);
    }
    fseek(ISOFile,0L,SEEK_END);
    imageEndPos = ftell(ISOFile);
    VDp = (VD *)SctBuf;
    xfread(ISOFile, VD_LBN*CDSCT, VDp, sizeof(SctBuf), "Volume Descriptor");
    memcpy(&rootDir,&(VDp->rootdir),sizeof(rootDir));
    if (rootDir.Lbn != dswab(rootDir.Lbn_b)) {
        printf("*Error - root directory not found !?\n");
        exit(1);
    }
    if ((cmd = getcmd(argc,argv)) != NULL) {/* make bootable image */
        if (adjFlag)
            offsetAdj();
        memset(&SEBuf,0,sizeof(SEBuf));
sprintf(&SEBuf.ID[0],"Section %2d",numSection+1);
        SEBuf.EntryCount = 0xffff;
        if ((FileDirP = getFileDir(cmd))==NULL) {
            printf("\n*Error - Boot catalog File '%s' not found in ISO Image !\n",cmd);
            exit(1);
        }
#ifdef DEBUG
        printf("\nDEBUG Boot catalog File found at 0x%08lx.\n",FileDirP->Lbn);
#endif
        if (FileDirP->Len < CDSCT) {
            printf("\n*Error - Boot catalog File Size must be greater than 2048 !\n");
            FileDirList(cmd,FileDirP);
            exit(1);
        }
        BootCatEnd = FileDirP->Lbn*CDSCT + FileDirP->Len + offset;
        /* build Boot Record Volume Descriptor */
        memset(&BRVDBuf,0,sizeof(BRVDBuf));
        memcpy(&BRVDBuf.Identifier[0],"CD001",5);
        BRVDBuf.Version = 1;
        strcpy((char *)&BRVDBuf.BSIdentifier[0],"EL TORITO SPECIFICATION");
        BRVDBuf.BootCatLbn = FileDirP->Lbn;
        xfwrite(ISOFile, BRVD_LBN*CDSCT, &BRVDBuf, sizeof(BRVDBuf), "BRVD");
        if (FileDirP->Lbn < baselbn) {
if (getcmd(argc,argv) != NULL) {
printf("\n*Warning - Boot catalog file is already burned.\n");
printf("           Ignore change/add Boot Media Image.\n");
}
        } else {
        while ((cmd = getcmd(argc,argv)) != NULL) {
        if (SEBuf.EntryCount == 0xffff) /* No Validation entry */
        mkVaEntry();
mkBootEntry(cmd);
}   /* end while */
/* finish */
if (SEBuf.EntryCount == 0xffff) {
printf("*Error - BootMediaImage for Initial/Default Entry Not specified !\n");
exit(1);
}
mkSection(0x91);
}
exit(0);
    } else { /* Verify */
Error = Warn = 0;
if (adjFlag)
            offsetAdj();
        numSection = numEntry = 0;
        /* Boot Record Volume Descriptor */
        xfread(ISOFile, BRVD_LBN*CDSCT, &BRVDBuf, sizeof(BRVDBuf), "Boot Record Volume Descriptor");
        if (checkBRVD())
            fail();
        /* validation entry */
        xfread(ISOFile, BRVDBuf.BootCatLbn*CDSCT, &VEBuf, sizeof(VEBuf), "Validation Entry");
        if (checkVE())
            fail();
        CurEntryLoc = ftell(ISOFile)+offset;    /* save position */
        /* initial/default entry */
        xfread(ISOFile, CurEntryLoc, &BEBuf, sizeof(BEBuf), "initial/default Boot Entry");
        CurEntryLoc = ftell(ISOFile)+offset;
        if (checkBE())
            fail();
        /* minimum requirement OK.*/
        xfread(ISOFile, CurEntryLoc, &SEBuf, sizeof(SEBuf), "Section Entry");
        if (checkZero((byte *)&SEBuf,sizeof(SEBuf))){
            do {
                xfread(ISOFile, CurEntryLoc, &SEBuf, sizeof(SEBuf), "Section Entry");
                ++numSection;
                CurEntryLoc = ftell(ISOFile)+offset;
                if (checkSE())
                    fail();
                for (numEntry = 1;numEntry <= SEBuf.EntryCount;numEntry++) {
                    xfread(ISOFile, CurEntryLoc, &BEBuf, sizeof(BEBuf), "Boot Entry");
                    CurEntryLoc = ftell(ISOFile)+offset;
                    checkBE();
                    /*  fail();*/
                }
/*              if ((BEBuf.bootMediaType & 0x20) == 0) {
                    printf("\nlast boot entry flag missing.\n");
                    fail();
                }*/
            } while(SEBuf.HeaderIndicator != 0x91);
        }
        if (Error != 0)
fail();
if (Warn != 0)
printf("\n %3d Warning(s)",Warn);
        printf("\n=== Verification Success ===\n");
        exit(0);
    }
}
void fail()
{
    printf("\nXXX Verification Failed. XXX\n");
    exit(1);
}
/* == ISO9660 file search routines ==*/
FileDir *getFileDir(char *name)
{
    char    *namep,*delim;
    FileDir *FileDirP;
    /*  root directory */
    FileDirP = &rootDir;
    strcpy(namebuf,name);
    namep = namebuf;
    while (*namep == '\\') /* strip top '\' */
        namep++;
    while((delim = strchr(namep,'\\'))!=NULL) { /* search directory */
        *delim++ = '\0';
        if (strlen(namep) != 0) {
            if ((FileDirP = getDirEntry(namep,FileDirP->Lbn*CDSCT,FileDirP->Len,02))==NULL)
                return NULL;
        }
#ifdef DEBUG
        printf("\nDEBUG Directory of '%s'\n",namep);
#endif
        namep = delim;
    }
    return(getDirEntry(namep,FileDirP->Lbn*CDSCT,FileDirP->Len,00));
}
FileDir *getDirEntry(char *name, long DirPos,long DirLen, int type)
{
    word     len;
    long    DirTop;
    DirTop = DirPos;
    while (DirPos-DirTop < DirLen) {
        do {
            xfread(ISOFile, DirPos, &len, sizeof(len), "Dir Entry Length");
            if (len == 0) {
                DirPos = (DirPos + CDSCT) & ~(CDSCT-1);
                continue;
            }
            if (fread(&DirBuf,sizeof(DirBuf),1,ISOFile) != 1) {
                printf("\n*Error - Read(DirBuf) !\n");
                exit(1);
            }
            if (fread(&FileNameBuf,sizeof(char),DirBuf.NameLen,ISOFile) != DirBuf.NameLen) {
                printf("\n*Error - Read(FileName) !\n");
                exit(1);
            }
            if ((DirBuf.NameLen>=2) && (FileNameBuf[DirBuf.NameLen -2] == ';') )
                DirBuf.NameLen -= 2;
            if (FileNameBuf[DirBuf.NameLen-1] == '.')
                DirBuf.NameLen--;
            FileNameBuf[DirBuf.NameLen] = '\0';
#ifdef DEBUG
            FileDirList(&FileNameBuf[0],&DirBuf);
#endif
            if ((stricmp(name,FileNameBuf) == 0 ) && ((DirBuf.Flag & 2) == type))
                return(&DirBuf);
            DirPos += len;
        } while (len != 0);
    }
    return NULL;
}
void FileDirList(char *name,FileDir *FileDirBufP) {
    if (*name <= ' ')
        return;
    printf("%02d/%02d/%02d  %02d:%02d %10ld          %s%c\n"
        ,FileDirBufP->Year
        ,FileDirBufP->Month
        ,FileDirBufP->Date
        ,FileDirBufP->Hour
        ,FileDirBufP->Minute
        ,FileDirBufP->Len
        ,name
        ,(FileDirBufP->Flag & 02) ? '\\':' ');
}
/* == Verification routines == */
int checkBRVD()
{
    int l;
    char linbuf[33];
    printf("\n== Boot Record Volume Descriptor ==");
    printf("\nIndicator:%d",BRVDBuf.Indicator);
    if (BRVDBuf.Indicator != 0) {
        printf(" *Error - must be zero !");
        Error++;
    }
    memcpy(linbuf,&BRVDBuf.Identifier[0],5);
    linbuf[5]='\0';
    printf("\nIdentifier:'%s'",linbuf);
    if (strcmp((char *)linbuf,"CD001")!=0) {
        printf(" *Error - must be 'CD001' !\n");
        Error++;
    }
    printf("\nVersion:%d",BRVDBuf.Version);
    if (BRVDBuf.Version != 1) {
        printf(" *Error - must be 1 !");
        Error++;
    }
    memcpy(linbuf,&BRVDBuf.BSIdentifier[0],32);
    linbuf[32]='\0';
    printf("\nBSIdentifier:'%s'",linbuf);
    l = strlen((char *)&BRVDBuf.BSIdentifier[0]);
    if ( (strcmp((char *)linbuf,"EL TORITO SPECIFICATION")!=0) ||
        checkZero(&BRVDBuf.BSIdentifier[l],32-l) ) {
        printf(" *Error - must be 'EL TORITO SPECIFICATION' !");
        Error++;
    }
    printf("\nBootCatLbn:0x%08lx(Loc:0x%08lx)",BRVDBuf.BootCatLbn,BRVDBuf.BootCatLbn*CDSCT);
    if ((BRVDBuf.BootCatLbn > baselbn) && (baselbn !=0))
printf(", BootCatLbn in image:0x%08lx(Loc:0x%08lx)",BRVDBuf.BootCatLbn-baselbn,(BRVDBuf.BootCatLbn-baselbn)*CDSCT);
    if (checkZero(&BRVDBuf.stab0[0],32)) {
        printf("\n*Warnning - Some Garbage in stab0.");
Warn++;
    }
    if (checkZero(&BRVDBuf.stab1[0],0x7b5)) {
        printf("\n*Warnning - Some Garbage in stab1.");
Warn++;
    }
    printf("\n");
    return(Error);
}
int checkVE()
{
    int i;
    short int sum,*ip;
char IDBuf[25];
    printf("\n== Validation Entry ==");
    printf("\nHeaderID:%d",VEBuf.HeaderID);
    if (VEBuf.HeaderID != 1) {
        printf(" *Error - HeaderID must be 1 !");
        Error++;
    }
    printf("\nPlatformID:%d - ",VEBuf.PlatformID);
    switch(VEBuf.PlatformID) {
    case 0x00:printf("80x86");break;
    case 0x01:printf("Power PC");break;
    case 0x02:printf("MAC");break;
    default:printf("*Error - Illegal value !");Error++;break;
    }
    if (VEBuf.reserve != 0) {
        printf("\n*Warning - reserve must be zero !");
        Warn++;
    }
strncpy(IDBuf,VEBuf.ID,24);
IDBuf[24]='\0';
    printf("\nID String:'%s'",IDBuf);
    if (VEBuf.KeyByte1 != 0x55) {
        printf("\n*Error - KeyByte1 must be 0x55 !");
        Error++;
    }
    if (VEBuf.KeyByte2 != 0xaa) {
        printf("\n*Error - KeyByte2 must be 0xaa !");
        Error++;
    }
    printf("\nCheckSum:0x%04x",VEBuf.CheckSum & 0xffff);
    ip = (short int *)&VEBuf;
    for (sum = 0, i=0; i< 16; i++)
        sum = (word)(sum + *ip++);
    if (sum != 0) {
        printf(" *Error - expected 0x%04x !",(VEBuf.CheckSum-sum) & 0xffff);
        Error++;
    }
    printf("\n");
    return(Error);
}
int checkSE()
{
    printf("\n== Section Entry %2d ==",numSection);
    printf("\nHeaderIndicator:0x%02x",SEBuf.HeaderIndicator);
    if ((SEBuf.HeaderIndicator != 0x90) && (SEBuf.HeaderIndicator != 0x91) ){
        printf(" *Error - must be 0x90 or 0x91 !");
        Error++;
    }
    printf("\nPlatformID:%d - ",SEBuf.PlatformID);
    switch(SEBuf.PlatformID) {
    case 0x00:printf("80x86");break;
    case 0x01:printf("Power PC");break;
    case 0x02:printf("MAC");break;
    default:printf("*Error - Illegal value !");Error++;break;
    }
    printf("\nEntryCount:%d",SEBuf.EntryCount);
    if (strlen(SEBuf.ID) > 27) {
        printf("\n*Error - ID String too long !");
        Error++;
    } else
        printf("\nID String:'%s'",SEBuf.ID);
    printf("\n");
    return(Error);
}
checkBE()
{
    if (numSection != 0)
        printf("\n == Boot Entry: Section %2d - %2d ==",numSection,numEntry);
    else
        printf("\n == Default/Initial Boot Entry ==");
    printf("\n BootIndicator:0x%02x - ",BEBuf.bootIndicator);
    switch(BEBuf.bootIndicator) {
    case 0x88:printf("Bootable");break;
    case 0x00:printf("Not bootable");break;
    default:printf("*Error - Illegal value !");Error++;break;
    }
    printf("\n MediaType:0x%02x - ",BEBuf.bootMediaType);
    switch(BEBuf.bootMediaType & 0xF) {
    case 0x00:printf("No Emulation");break;
    case 0x01:printf("1.2MFD");break;
    case 0x02:printf("1.44MFD");break;
    case 0x03:printf("2.88MFD");break;
    case 0x04:printf("HARD Disk");break;
    default:printf("*Error - Illegal value !");Error++;break;
    }
    if (BEBuf.bootMediaType & 0x80)
        printf(" with SCSI Driver");
    if (BEBuf.bootMediaType & 0x40)
        printf(" with ATAPI Driver");
    /*
    if (BEBuf.bootMediaType & 0x20)
        printf(" with ATAPI Driver");
    */
    printf("\n LoadSegment:0x%04x",BEBuf.bootLoadSegment);
if (BEBuf.bootLoadSegment == 0)
printf(" - 0x7C0");
    printf("\n SystemType:0x%02x",BEBuf.bootSystemType);
    if (BEBuf.stab != 0) {
        printf("\n *Warning - stab must be zero !");
        Warn++;
    }
    printf("\n SectorCount:%d",BEBuf.bootSectorCount);
    if (BEBuf.bootSectorCount < 1) {
        printf(" *Error - must be greater than zero !");
        Error++;
    }
    printf("\n LoadRBA:0x%08lx(Loc:0x%08lx)",BEBuf.bootLoadRBA,BEBuf.bootLoadRBA*CDSCT);
    if ((BEBuf.bootLoadRBA > baselbn) && (baselbn !=0))
        printf(", RBA in image:0x%08lx(Loc:0x%08lx)",BEBuf.bootLoadRBA-baselbn,(BEBuf.bootLoadRBA-baselbn)*CDSCT);
    if (numSection == 0) {
        if (checkZero(&BEBuf.stab2[0],20))
            printf("\n *Warning - Some Garbage in stab2.");
    } else {
        printf("\n %s",&BEBuf.stab2[1]);
    }
    printf("\n");
    return checkBootImage();
}
int checkBootImage(void)
{
    FDBS    *FDBSBufP;
    char    linbuf[9];
    int     cyl0,cyl1,hed0,hed1,sct0,sct1;
    long    PBRLoc;
    if (BEBuf.bootLoadRBA < baselbn){
        printf("\n*Info - Boot image file can't check as not include this session.\n");
        return 1;
    }
    xfread(ISOFile, BEBuf.bootLoadRBA*CDSCT, &SctBuf, sizeof(SctBuf), "BootMedia Image");
    switch(BEBuf.bootMediaType & 0xf) {
    case 0x01:
    case 0x02:
    case 0x03:
        FDBSBufP = (FDBS *)&SctBuf;
        printf("\n  == Floppy Diskette Boot Image ==");
        if (((SctBuf[0x1FE] != 0x55) || (SctBuf[0x1FF] != 0xAA)) && (BEBuf.bootIndicator == 0x88)) {
            Error++;
            printf(" *Error - Valid boot sector mark 55AA not found !");
        } else {
            strncpy(linbuf,&(FDBSBufP->OemData[0]),8);
            linbuf[8] = 0;
            printf("\n  OEM data: '%s'",linbuf);
            printf("\n  NumberOfSectors:%d(0x%04x)",FDBSBufP->NumberOfSectors,FDBSBufP->NumberOfSectors);
            if (FDBSBufP->NumberOfSectors != ExpectedNumberOfSectors[BEBuf.bootMediaType & 0xf]) {
                Warn++;
                printf(" *Warning - %d expected.",ExpectedNumberOfSectors[BEBuf.bootMediaType & 0xf]);
            }
        }
        break;
    case 0x00:
        printf("\n  == Direct Mode Boot Image ==");
        break;
    case 0x04:
        printf("\n  == Hard Disk Boot Image ==");
        if ((SctBuf[0x1FE] != 0x55) || (SctBuf[0x1FF] != 0xAA)){
            Error++;
            printf("\n *Error - Valid boot sector mark 55AA not found in MBR !");
            return Error;
        }
        PDTp = (PDT *)&SctBuf[0x1BE];
        printf("\n  BootIndicator:0x%02x",PDTp->BootIndicator);
        if ((PDTp->BootIndicator != 0x80) && (BEBuf.bootIndicator==0x88)) {
            printf(" *Error - Non bootable partition !");
            Error++;
        }
        printf("\n  SystemIndicator:0x%02x",PDTp->SystemIndicator);
        if (BEBuf.bootSystemType != PDTp->SystemIndicator) {
            printf(" *Error - Boot entry SytemType Not same(0x%02x) !",BEBuf.bootSystemType);
            Error++;
        }
        printf("\n  BeginningSector Cyl:%03d, Hed:%02d, Sct:%02d",
            cyl0 = PDTp->BeginningCylinder + ((PDTp->BeginningSector&0xC0)<<2),
            hed0 = PDTp->BeginningSectorHeadNumber,
            sct0 = PDTp->BeginningSector&0x3F);
        printf("\n  EndingSector    Cyl:%03d, Hed:%02d, Sct:%02d",
            cyl1 = PDTp->EndingCylinder + ((PDTp->EndingSector&0xC0)<<2),
            hed1 = PDTp->EndingSectorHeadNumber,
            sct1 = PDTp->EndingSector&0x3F);
        printf("\n  SectorsPrecedingPartition:%ld",PDTp->SctPrePar);
        printf("\n  SectorsInPartition:%ld",PDTp->SctInPar);
        /* try to get Partition Boot Records */
        PBRLoc = ((cyl0*64L+hed0)*32L + sct0-1)*512 + BEBuf.bootLoadRBA*CDSCT;
        xfread(ISOFile, PBRLoc, &SctBuf, sizeof(SctBuf), "Partition boot record");
        if ( (SctBuf[0x1FE] != 0x55) || (SctBuf[0x1FF] != 0xAA) ) {
            Error++;
            printf("\n *Error - Valid boot record mark 55AA not found in PBR !");
            printf("\n          We assume 64 track/cylinder, 32 sector/track.\n");
        } else {
            FDBSBufP = (FDBS *)&SctBuf;
            strncpy(linbuf,&(FDBSBufP->OemData[0]),8);
            linbuf[8] = 0;
            printf("\n  Partition OEM data: '%s'",linbuf);
        }
        break;
    default:
        printf("\n  *Error - Illegal Media Type !");
        Error++;
        break;
    }
    printf("\n");
    return Error;
}
int checkZero(byte *p,int n)
{
    for (; n > 0 ; --n) {
        if (*p++ != 0)
            return(1);
    }
    return(0);
}
/* I/O routines */
void xfread(FILE *fp, long loc, void *bufp, int size, char *ErrMsg)
{
    if ((imageEndPos < loc-offset) || (loc-offset < 0)){
        printf("\n*Error - Seek out of range(%s) !",ErrMsg);
        printf("\n         If Multi sessioned, use -M option.\n");
        exit(1);
    }
    if (fseek(fp,loc-offset,SEEK_SET) != 0) {
        printf("\n*Error - Seek(%s) !\n",ErrMsg);
        exit(1);
    }
    if (fread(bufp,size,1,fp) != 1) {
        printf("\n*Error - Read(%s) !\n",ErrMsg);
        exit(1);
    }
}
void xfwrite(FILE *fp, long loc, void *bufp, int size, char *ErrMsg)
{
    if ((imageEndPos < loc-offset) || (loc-offset < 0)){
        printf("\n*Error - Seek out of range(%s) !\n",ErrMsg);
        exit(1);
    }
    if (fseek(fp,loc-offset,SEEK_SET) != 0) {
        printf("\n*Error - Seek(%s) !\n",ErrMsg);
        exit(1);
    }
    if (fwrite(bufp,size,1,fp) != 1) {
        printf("\n*Error - Write(%s) !\n",ErrMsg);
        exit(1);
    }
}
char *getcmd(int argc,char *argv[])
{
    char *q,*p = NULL;
    int i;
    do {
        if (ind) {
            if ( (p = gets(cmdbuf)) == NULL)
                return NULL;
            if (strlen(p) == 0)
                return NULL;
            if (strcmp(p,"-")==0) {
                --ind;
                continue;
            }
        } else {
            if (argn >= argc)
                return NULL;
            if (strcmp(argv[argn],"-")==0) {
                ind++;
                continue;
            }
            p = argv[argn++];
        }
        if (*p == ';') {    /* comment */
            p = NULL;
            continue;
        }
        if (*p == '-') {
            if ((q = strchr(p+1,';')) != NULL)
                *q = '\0';
            switch(toupper(*(p + 1))) {
            case 'B':
case 'M':/* multi session */
                if (*(p+2)) {
                    sscanf(p+2,"%ld",&baselbn);
                    offset = baselbn*CDSCT;
                } else {
                    adjFlag++;  /* auto */
                }
                break;
            case 'D':
if (*(p+2))
                DrvLetter = *(p+2);
else
DrvLetter = 'Q';
                break;
/* entry related */
            case 'I':
if (*(p+2))
                sscanf(p+2,"%x",&i);
else
i = 0x88;
                bootIndicator = (byte)i;
                break;
            case 'T':
if (*(p+2))
                sscanf(p+2,"%x",&i);
else
i = 0xf;
                bootMediaType = (byte) (i & 0xf);
                break;
            case 'F':
                sscanf(p+2,"%x",&i);
                bootMediaTypeFlags = (byte)(i << 4);
                break;
            case 'L':
if (*(p+2))
sscanf(p+2,"%x",&bootLoadSegment);
else
bootLoadSegment = 0x7c0;
                break;
            case 'C':
if (*(p+2))
sscanf(p+2,"%d",&bootSectorCount);
else
bootSectorCount = 1;
                break;
/* Section related */
            case 'P':
                sscanf(p+2,"%d",&i);
                PlatformID = (byte)i;
                break;
            case 'S':
                if (SEBuf.EntryCount != 0xffff) { /* default entry exist */
                    SectionID[0] = '\0';
                    strncpy(SectionID,p+2,27);
                    mkSection(0x90);
                    break;
                }
                printf("\n* Error - No default entry yet. Section ignored.\n");
break;
            default:
                printf("\n* Error - illegal option '%s'\n",p);
                if (ind)
                    break;
                else
                    usage();
            }
            p=NULL;
        } else {
            if ((q = strchr(p,' ')) != NULL)
                *q = '\0';
            if ((q = strchr(p,';')) != NULL)
                *q = '\0';
        }
    } while (p == NULL);
    return(p);
}
/* == build routines ==*/
/* build validation entry */
void mkVaEntry(void)
{
    int i;
    short int sum,*ip;
    memset(&VEBuf,0,sizeof(VEBuf));
    VEBuf.HeaderID = 1;
    VEBuf.PlatformID = PlatformID;
    if (strlen(SectionID) == 0)
        memcpy(&VEBuf.ID[0],"Gigo's Bootable CD TEST",23);
    else
        strncpy(&VEBuf.ID[0],SectionID,23);
    VEBuf.KeyByte1 = 0x55;
    VEBuf.KeyByte2 = 0xAA;
    ip = (short int *)&VEBuf;
    for (sum = 0, i=0; i< 16; i++)
        sum = (word)(sum + *ip++);
    VEBuf.CheckSum = (word)-sum;
#ifdef DEBUG
    printf("\nDEBUG entry %ld:VE\n",(BRVDBuf.BootCatLbn*CDSCT-BRVDBuf.BootCatLbn*CDSCT)/32);
    checkVE();
#endif
    xfwrite(ISOFile, BRVDBuf.BootCatLbn*CDSCT, &VEBuf, sizeof(VEBuf), "VE");
    CurEntryLoc = ftell(ISOFile)+offset;    /* save initial  position */
}
void mkSection(int type)
{
    SEBuf.HeaderIndicator = (byte) type;
    if (SEBuf.EntryCount != 0) {
        xfwrite(ISOFile, SectionEntry, &SEBuf, sizeof(SEBuf), "Section Entry");
        numSection++;
}
#ifdef DEBUG
        printf("\nDEBUG entry %ld:SE\n",(SectionEntry-BRVDBuf.BootCatLbn*CDSCT)/32);
        checkSE();
#endif
memset(&SEBuf,0,sizeof(SEBuf));
    if (type == 0x91) {
        xfwrite(ISOFile, CurEntryLoc, &SEBuf, sizeof(SEBuf), "End of Entry");
    } else {
    SEBuf.PlatformID = PlatformID;
if (strlen(SectionID) == 0)
sprintf(SectionID,"Section %2d",numSection+1);
strncpy(&SEBuf.ID[0],SectionID,27);
}
}
void mkBootEntry(char *name)
{
    FileDir *FileDirP;
    char *p;
    if (CurEntryLoc >= BootCatEnd) {
        printf("\n*Error - Boot catalog overflow. Too many entrys !\n");
        exit(1);
    }
    if ((FileDirP = getFileDir(name))==NULL) {
        printf("\n*Error - BootMediaImage File '%s' not found in ISO Image !\n",name);
#ifdef DEBUG
        if (ind)
            return;
        else
#endif
        exit(1);
    }
    printf("\nAdd BootEntry for Boot Media image File.\n");
    FileDirList(name,FileDirP);
    /* entry */
    if (SEBuf.EntryCount == 0) { /* reserve Section entry space */
        SectionEntry = CurEntryLoc;
        CurEntryLoc += sizeof(SEBuf);
    }
    memset(&BEBuf,0,sizeof(BEBuf));
    BEBuf.bootSectorCount = bootSectorCount;
    BEBuf.bootIndicator = bootIndicator;
    BEBuf.bootLoadSegment = bootLoadSegment;
    BEBuf.bootLoadRBA = FileDirP->Lbn;
    if (bootMediaType == 0xf) { /* auto */
        switch(FileDirP->Len) {
        case 2949120:BEBuf.bootMediaType=3;break;
        case 1474560:BEBuf.bootMediaType=2;break;
        case 1228800:BEBuf.bootMediaType=1;break;
        default:BEBuf.bootMediaType=4;
        }
    } else {
        BEBuf.bootMediaType = bootMediaType;
    }
    /* verifyBootMedia(); */
    if ((BEBuf.bootMediaType & 0xf) == 4){
        if (FileDirP->Lbn > baselbn) {
            xfread(ISOFile, FileDirP->Lbn*CDSCT, &SctBuf, 512, "Partition table");
        } else {
            sprintf(namebuf,"%c:\\%s",DrvLetter,name);
            if ((image = fopen(namebuf,"rb")) == NULL) {
                printf("\n*Error - can't open image file -- '%s' !\n",namebuf);
                exit(1);
            }
            if (fread(&SctBuf,512,1,image) != 1) {
                printf("\n*Error - Read(%s) !\n","Partition table");
                exit(1);
            }
            fclose(image);
        }
        PDTp = (PDT *)&SctBuf[0x1BE];
        BEBuf.bootSystemType = PDTp->SystemIndicator;
    }
    if (SEBuf.EntryCount++ != 0xffff) {
        BEBuf.bootMediaType = (byte)(BEBuf.bootMediaType + bootMediaTypeFlags);
        strcpy(namebuf,name);
        if ((p = strrchr(namebuf,'\\')) == NULL)
            p = namebuf;
        else
            p++;
        strncpy((char *)&BEBuf.stab2[1],p,18);
    }
#ifdef DEBUG
    printf("\nDEBUG entry %ld:BE\n",(CurEntryLoc-BRVDBuf.BootCatLbn*CDSCT)/32);
    numEntry = SEBuf.EntryCount;
    checkBE();
#endif
    xfwrite(ISOFile, CurEntryLoc, &BEBuf, sizeof(BEBuf), "Boot Entry");
    CurEntryLoc = ftell(ISOFile)+offset;    /* save position */
}
dword dswab(dword big)
{
    dword little;
    char *p,*q;
    p =((char *)&big) +3;
    q =(char *)&little;
    *q++ = *p--;
    *q++ = *p--;
    *q++ = *p--;
    *q = *p;
    return little;
}
void offsetAdj()
{
    VD *VDp;
    FileDir *FileDirP;
    VDp = (VD *)SctBuf;
    xfread(ISOFile, VD_LBN*CDSCT, VDp, sizeof(SctBuf), "Volume Descriptor");
    /* We assume first PTB in sector 20. */
    if (VDp->lptbLbn1 < dswab(VDp->bptbLbn1_b))
        baselbn = VDp->lptbLbn1-20L;
    else
        baselbn = dswab(VDp->bptbLbn1_b)-20L;
    do {/* check & search */
        offset = baselbn*CDSCT;
        xfread(ISOFile, rootDir.Lbn*CDSCT, SctBuf, sizeof(SctBuf), "rootdir");
        FileDirP = (FileDir *)&SctBuf[2];
        if ((FileDirP->Lbn == rootDir.Lbn) && (dswab(FileDirP->Lbn_b) == rootDir.Lbn) )
            break;
    } while ((--baselbn) && ((rootDir.Lbn - baselbn)>18L) );
#ifdef DEBUG
    printf("*DEBUG - Assumed baselbn %ld\n",baselbn);
#endif
    adjFlag = 0;
}
void usage() {
    printf("\nUsage:\n");
    printf("verify:mkbootcd isoimage\n");
    printf("make:  mkbootcd isoimage bootentryfile bootimage\n");
    printf("       mkbootcd isoimage bootentryfile - <indirect\n");
    printf("options:\n");
    printf("    -        Use stdin\n");
    printf("    -D[Q]      Set CD-ROM Drive Letter is 'Q'\n");
    printf("    -M[nnnnnn] Set offset for multisession\n");
    printf("    -I[xx]     Set bootIndicator\n");
    printf("    -T[x]      Set bootMediaType, F means Auto\n");
    printf("    -F[x]      Set bootMediaTypeFlags\n");
    printf("    -C[nn]     Set bootSectorCount\n");
    printf("    -L[xxxx]   Set bootLoadSegment\n");
    printf("    -P[nn]     Set PlatformID\n");
    printf("    -S[string] Make Section entry with ID string\n");
    printf("ex.\n");
    printf("mkbootcd mycd.iso bootcat.bin osboot.ima -i00 noboot.ima -i88 osboot2.ima\n");
    printf("\nmailto:gigo@yk.rim.or.jp\n");
    printf("http://www1.yk.rim.or.jp/~gigo/\n");
    exit(1);
}
:em09:




欢迎光临 无忧启动论坛 (http://bbs.wuyou.net/) Powered by Discuz! X3.3