|
/* 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: |
|