/****************************************************************************** * * Title : coffConv.c * Version 0.0 * * Description: Coff file conversion utility * Input: DSP coff file (fileName.out) * Output: binary files * - by section: section_startAddress.bin * - FLASH (for MDSP): fileName_FLASH.bin * - IPRAM init: fileName_IPRAM.bin * - IDRAM init: fileName_IDRAM.bin * Author: Lukas Tomasek, tomasekl@fzu.cz * * modifications: * * 07.03.02 If the section name is actually a pointer into the string table, * go there to look up its name, and check the flags (see Ass. Lang. * Tools UG A-7) for the sections. If a section is a "copy" section (.vers), * note & ignore it (was being luckily overwritten by the hwi vectors, but * if the section output order changed from the linker, would instead * overwrite them). Ignore initialized data sections (handled by loadCode) * where the size is zero, as DSP-BIOS adds at least one such section to the * list. Ignore the .log section, which BIOS creates as initialized, but * then treats as uninitialized (handled by cinit assembly fxn). The stack * (!) and LOG_system$buf are also searched for by name, and ignored (BIOS * re-initializes them later using gblinit). dpsf * * 03.06.02 Added an xcode output section since 6701 code now needs SDRAM. * Any input section which is labelled xcode* gets put into the * appropriate spot in the xcode output section. dpsf * * 28.02.03 Updated the size of the external code buffer to match the * expanded DSP code size. dpsf * * 05.06.03 Commented out code which produces the individual section files * (other than flash, ipram, idram & xcode). The remaining files * are written depending upon the program name. dpsf * * 28.02.04 Test within code to discover which type of DSP the code runs * on. dpsf * * 18.03.04 Removed wasted space for .cinit table (nearly 64K!) by placing * all the information that the MDSP routine loadCode needs to * parse the flash properly into a header structure, which is inserted * in the flash right after the IPRAM section. dpsf ******************************************************************************/ #include #include #include "processor.h" #include "flash.h" #include "genUtils.h" FlashHeader flashHeader; UINT32 headerOffset; char flashHeaderFound= 0; #define NUM_OF_BLOCKS_ADDR 0x20000 //For the program flag: #define MDSP 0 #define SDSP6701 1 #define SDSP6713 2 #define XDSP 3 unsigned int cinitIdx= -1; unsigned char loadCinit= false; unsigned char *buffer; long fileSize; char coffFileName[300], progFlag= XDSP; char newFileName[300]; char text[100]; char sectionName[100]; int status; int index; FILE *fileHandle; unsigned char *flashBuffer, *idramBuffer, *xcodeBuffer, *cPtr, *buff; UINT32 offset, entryLen; //unsigned char *bridBuffer; int flashBufferIndex; UINT32 numOfBlocks= 0; UINT32 wordSize; UINT32 checksum= 0; UINT16 nSections= 0; int i; unsigned int address, size, location, flashAddr; unsigned int addr[2]; int addrIndex; int flags; #define SYMBOL_ENTRY_SIZE 0x12 int symbolTableBase, numSymbols; int stringTableBase; int stringTableIndex; /* offset into the string table */ int getFileSize(FILE *file, int *size); int main(int argc, char *argv[]){ printf("Coffconv: DSP COFF file parser. %s\n", __DATE__); memset(coffFileName, 0, 300); memset(newFileName, 0, 300); // strcpy(coffFileName,"sdsp6713.out"); // strcpy(coffFileName,"slaveRun.out"); // strcpy(coffFileName,"l:/rodrun_pxl.out"); strcpy(coffFileName,argv[1]); for (i=0; i<300; ++i) coffFileName[i]= tolower(coffFileName[i]); printf("%s\n",coffFileName); fileHandle= fopen(coffFileName, "rb"); /* open binary file for read */ if (fileHandle == NULL) return(-1); status= getFileSize(fileHandle, &fileSize); buffer= calloc(fileSize, sizeof(char)); /* alloc clear buffers */ flashBuffer= calloc(FLASH_SIZE, sizeof(char)); idramBuffer= calloc(0x10000, sizeof(char)); xcodeBuffer= calloc(0x40000, sizeof(char)); // bridBuffer= calloc(0x10000, sizeof(char)); /* set to 0xFF space above first 64k (ie. ~DSP IPRAM) */ memset(flashBuffer, 0xFF, FLASH_SIZE); fileHandle= fopen(coffFileName, "rb"); /* open binary file for read */ if (fileHandle==NULL) return(-1); /* read file block and store it in the buffer */ fread(buffer, sizeof(char), fileSize, fileHandle); status=fclose(fileHandle); if (status!=0) return(-1); symbolTableBase= *( (int *) &buffer[8]); numSymbols= *( (int *) &buffer[12]); stringTableBase= symbolTableBase +SYMBOL_ENTRY_SIZE*numSymbols; strcpy(&coffFileName[strlen(coffFileName)-4], "_"); nSections= *(UINT16 *) &buffer[2]; printf("#sections: 0x%x.\n", nSections); /********************************************************************************* First, loop over the program's sections searching for any that belong in the boot ROM (=> MDSP) Load these there; there should be only two: the flash header and the .cinit initialization table. *********************************************************************************/ flashHeader.flashUsed= 0x10000; //Flash always loads all IPRAM. for (index=0; index in the string table */ stringTableIndex= *( (int *) &buffer[54 +48*index]); if (*(char *) &buffer[stringTableBase +stringTableIndex]=='.') { /* +1 ==> skip the period */ strcpy(sectionName, &buffer[stringTableBase +stringTableIndex +1]); } else { strcpy(sectionName, &buffer[stringTableBase +stringTableIndex]); } } flags= *( (int *) &buffer[90 +48*index]); /* Skip if not either of the two sections mentioned above, and if address is not appropriate for MDSP flash */ if ( (addr[0] < 0x01410000) || (addr[0] >= 0x01420000) ||((strcmp(sectionName,"flash") != 0) && (strcmp(sectionName,"cinit") != 0)) ) continue; wordSize= (size+3)/4; address=addr[0]; progFlag= MDSP; //Copy to flash buffer: note that the header will be overwritten later. if (strcmp(sectionName,"flash") == 0) { flashHeaderFound= 1; headerOffset= address- 0x01400000; flashHeader.revision= FLASH_HEADER_REVISION; flashHeader.headerSize= wordSize; flashHeader.nSect= 0; flashHeader.flashUsed+= flashHeader.headerSize*4; flashHeader.flashSize= FLASH_SIZE; flashHeader.unused= 0; flashHeader.checksum= 0; } else if (strcmp(sectionName,"cinit") == 0) { //Round to the nearest 16 word boundary (+ 16 word padding): flashHeader.cinitSize= (wordSize +31) & (~0xf); flashHeader.flashUsed+= flashHeader.cinitSize*4; memcpy(&flashBuffer[address-0x01400000], &buffer[location], wordSize*4); } } /* loop over sections in coff file, searching for flash sections */ /*********************************************************************************/ if ((!flashHeaderFound) || (flashHeader.headerSize == 0)) { //program uses old method. flashBufferIndex= (NUM_OF_BLOCKS_ADDR) +4; } else { //new method: flashBufferIndex= headerOffset +4*(flashHeader.headerSize +flashHeader.cinitSize); } /********************************************************************************* Now loop over all the other code sections, placing them in the appropriate binary output file. *********************************************************************************/ for (index=0; index in the string table */ stringTableIndex= *( (int *) &buffer[54 +48*index]); if (*(char *) &buffer[stringTableBase +stringTableIndex]=='.') { /* +1 ==> skip the period */ strcpy(sectionName, &buffer[stringTableBase +stringTableIndex +1]); } else { strcpy(sectionName, &buffer[stringTableBase +stringTableIndex]); } } flags= *( (int *) &buffer[90 +48*index]); if ((location==0)||(size==0)) { continue; } strcpy(newFileName, coffFileName); strcat(newFileName,sectionName); if (addr[0]==addr[1]) {sprintf(text,"_%x",addr[0]); } else {sprintf(text,"_%x&%x", addr[0], addr[1]); } printf("\n******************************************************\n"); printf("%s - addr %s , size %x, loc %x\n", sectionName, text, size, location); printf("section flags: "); if (flags&0x1) {printf(" dummy sect."); } if (flags&0x2) {printf(" noload sect."); } if (flags&0x4) {printf(" grouped sect."); } if (flags&0x8) {printf(" padding sect."); } if (flags&0x10) {printf(" copy sect."); } if (flags&0x20) {printf(" code sect."); } if (flags&0x40) {printf(" data sect."); } printf("\n"); #ifdef BRID if (strcmp(sectionName,"$BRID") == 0) { address= addr[0]; memcpy(&bridBuffer[address], &buffer[location], wordSize*4); fileHandle= fopen("c:/brid.bin", "wb"); /* open/create binary file for write */ if(fileHandle==NULL) return(-1); /* write to FLASH file */ fwrite(bridBuffer, sizeof(char), 0x10000, fileHandle); status= fclose(fileHandle); if(status!=0) return(-1); } #endif if ( (strcmp(sectionName,"log")==0) ||(strcmp(sectionName,"stack")==0) ||(strcmp(sectionName,"LOG_system$buf")==0) ){ printf("==> %s section found, ignoring <==\n",sectionName); continue; } if ((flags&0x1)||(flags&0x2)||(flags&0x10)) { /* SDSP code can pre-load .cinit, in which case its copy flag is set (load-time auto-initialization) */ if (strcmp(sectionName, "cinit") == 0) { printf("==> cinit section is processed at load time. <==\n"); cinitIdx= index; loadCinit= true; continue; //Will be processed later. } else { printf("==> %s section not program related, ignoring <==\n", sectionName); continue; } } strcat(newFileName, text); strcat(newFileName,".bin"); printf("%s\n\n", newFileName); if (((size%4)!=0) && (strcmp(sectionName,"const") != 0)) { printf("######################################################\n"); printf("SIZE WARNING!!! SIZE NOT ALIGNED ON 32 BIT BOUNDARY!!!\n"); printf("######################################################\n"); } wordSize= (size+3)/4; for (addrIndex=0; addrIndex<2; ++addrIndex){ if ((addrIndex==1)&&(addr[0]==addr[1])) continue; address=addr[addrIndex]; //Already processed the true flash sections: if ((address>=0x01410000)&&(address<0x01420000)) continue; /* Program internal code => flash buffer. For the MDSP the flash buffer has all the program code & data loaded into it at different addresses; only the IPRAM is actually loaded onto the DSP though & the rest must be copied from the flash memory into the appropriate running location (see loadCode.c). For the two types of SDSPs, the code is written into three separate files for internal program code, internal program data, and external code. The Former of these has the same starting address and size as the MDSP section; the latter two have different addresses which depend on the type of SDSP (Rev. C or Rev. E). */ if(address<0x10000) { //Internal program code memcpy(&flashBuffer[address], &buffer[location], wordSize*4); if((address+size)>0x10000){ printf("######################################################\n"); printf("## ERROR!! IPRAM SECTION EXCEEDS 64k SIZE!!! ##\n"); printf("######################################################\n"); printf("--- PRESS ANY KEY ---"); getchar(); } } else { //Program data & external code /* idram data & sdram code/data for the SDSPs: */ if ((address>=0x80000000)&&(address<0x80010000)) {//6701 SDSP (& 6201 MDSP) memcpy(&idramBuffer[address-0x80000000], &buffer[location], wordSize*4); } else if ((address>=0x10000)&&(address<0x20000)) { //6713 SDSP progFlag= SDSP6713; memcpy(&idramBuffer[address-0x10000], &buffer[location], wordSize*4); } else if ((address>=0x02000000)&&(address<0x02040000)) { //6701 SDSP if (progFlag != MDSP) progFlag= SDSP6701; memcpy(&xcodeBuffer[address-0x02000000], &buffer[location], wordSize*4); } else if ((address>=0xa0000000)&&(address<0xa0040000)) { //6713 SDSP progFlag= SDSP6713; memcpy(&xcodeBuffer[address-0xa0000000], &buffer[location], wordSize*4); } /* All sections are written into the flash buffer for the MDSP, together with the accounting information for each: */ if (progFlag == MDSP) { *(UINT32*) (&flashBuffer[flashBufferIndex])= wordSize; /* add length */ flashBufferIndex+= 4; *(UINT32*) (&flashBuffer[flashBufferIndex])= address; /* add addr */ flashBufferIndex+= 4; memcpy(&flashBuffer[flashBufferIndex], &buffer[location], wordSize*4); flashBufferIndex+= wordSize*4; *(UINT32*) (&flashBuffer[flashBufferIndex])= wordSize; /* repeat length */ flashBufferIndex+= 4; if ((!flashHeaderFound) || (flashHeader.headerSize == 0)) { ++numOfBlocks; *(UINT32*) (&flashBuffer[NUM_OF_BLOCKS_ADDR])= numOfBlocks; /* incr. num of blocks */ } else { ++flashHeader.nSect; flashHeader.flashUsed+= wordSize*4 +12; } } } } //Loop over section addresses. //Uncomment if the individual program sections are wanted. //fileHandle= fopen(newFileName, "wb"); /* open/create binary file for write */ //if(fileHandle==NULL) return(-1); /* write to file */ //fwrite(&buffer[location], sizeof(char), wordSize*4, fileHandle); //status=fclose(fileHandle); //if(status!=0) return(-1); } /* loop over sections in coff file */ /* If the .cinit table is pre-loaded to save space in the SDSP map, process it. */ if (loadCinit) { index= cinitIdx; addr[0]= *(unsigned int *) &buffer[58+48*index]; addr[1]= *(unsigned int *) &buffer[62+48*index]; size= *(unsigned int *) &buffer[66+48*index]; location= *(unsigned int *) &buffer[70+48*index]; cPtr= (unsigned char *) &buffer[location]; /* The .cinit table consists of a series of entries, with each entry having a length (in bytes), destination address, and then the data. If an entry has length % 8 != 0, it is rounded up to the nearest 8 byte boundary in the table. The last entry's length == 0xffffffff to signify that initialization is done. The coff file format is a bit odd & forms many things on 16 bit boundaries, including the sections, so all the (unsigned int) lengths and pointers must be re-formed from the bytes. */ do { entryLen= *cPtr++; entryLen|= (*cPtr++)<<8; entryLen|= (*cPtr++)<<16; entryLen|= (*cPtr++)<<24; address= *cPtr++; address|= (*cPtr++)<<8; address|= (*cPtr++)<<16; address|= (*cPtr++)<<24; //Find which file the entry's destination address belongs in: if(address < 0x10000) { //Internal program code buff= flashBuffer; offset= 0; } else if ((address>=0x80000000)&&(address<0x80010000)) {//6701 SDSP (& 6201 MDSP) buff= idramBuffer; offset= 0x80000000; } else if ((address>=0x10000)&&(address<0x20000)) { //6713 SDSP buff= idramBuffer; offset= 0x10000; } else if ((address>=0x02000000)&&(address<0x02040000)) { //6701 SDSP buff= xcodeBuffer; offset= 0x02000000; } else if ((address>=0xa0000000)&&(address<0xa0040000)) { //6713 SDSP buff= xcodeBuffer; offset= 0xa0000000; } if (entryLen > 0) { memcpy(&buff[address-offset], cPtr, entryLen); cPtr+= entryLen & (~7); if (entryLen & 7) cPtr+= 8; } } while (entryLen > 0); } //End of cinit pre-loading. printf("==============================================================\n"); /****************************************************************/ if (progFlag == MDSP) { /* Add header & checksum */ if ((!flashHeaderFound) || (flashHeader.headerSize == 0)) { for(i=0; i