diff --git a/dsoextractfw/ChangeLog b/dsoextractfw/ChangeLog index d0932f6..114ddb7 100644 --- a/dsoextractfw/ChangeLog +++ b/dsoextractfw/ChangeLog @@ -23,3 +23,7 @@ * Silent make if available * Fixed DSO-2100 USB vid/pid * Added --with-firmware-dir configure option and udev-rules file generation + +2011-02-03 Oliver Haag +* Input files are given as commandline parameters (Not hardcoded anymore) +* Cleaned up the code diff --git a/dsoextractfw/INSTALL b/dsoextractfw/INSTALL index 1652a42..af4995b 100644 --- a/dsoextractfw/INSTALL +++ b/dsoextractfw/INSTALL @@ -5,7 +5,7 @@ $ ./configure $ make Now place the DSO*1.SYS file that came with the windows driver for your oscilloscope into the same directory and run: -$ ./dsoextractfw +$ ./dsoextractfw This should create two .hex files. Copy them to /usr/local/share/hantekdso/ and copy the 90-hantek-dso.rules file to /etc/udev/rules.d/. To load the firmware you have to install fxload. After restarting udev your oscilloscope should be initialized automatically after connecting it to the computer (You have to reconnect it after installing this package). diff --git a/dsoextractfw/dsoextractfw.c b/dsoextractfw/dsoextractfw.c index 4afa467..89ab26c 100644 --- a/dsoextractfw/dsoextractfw.c +++ b/dsoextractfw/dsoextractfw.c @@ -4,7 +4,7 @@ // dsoextractfw.c // Copyright (C) 2008 Oleg Khudyakov // prcoder@potrebitel.ru -// Copyright (C) 2010 Oliver Haag +// Copyright (C) 2010, 2011 Oliver Haag // oliver.haag@gmail.com // // This program is free software: you can redistribute it and/or modify it @@ -23,184 +23,234 @@ //////////////////////////////////////////////////////////////////////////////// -#include +#include #include +#include #include + #include -static const char *strFirmware = "_firmware"; -static const char *strLoader = "_loader"; -static const char *strHex = ".hex"; -static const char *strDriver = "1.SYS"; -static const char *strModels[] = { "DSO2090", "DSO2100", "DSO2150", "DSO2250", "DSO5200", "DSO520A", NULL }; -int writeIntelHex(const char *filename, unsigned char *ptr, bfd_size_type len); -int extractFirmware(const char* model); +int extractFirmware(const char *filenameDriver, const char *filenameFirmware, const char *filenameLoader); +int writeIntelHex(const char *filename, unsigned char *data, unsigned int length); + +static const char *filenameEndFirmware = "-firmware.hex"; +static const char *filenameEndLoader = "-loader.hex"; +static const char *filenameEndDriver = "1.sys"; +static const char *nameTarget = "pei-i386"; +static const char *nameSection = ".data"; +static const char *nameSymbolFirmware = "_firmware"; +static const char *nameSymbolLoader = "_loader"; -int writeIntelHex(const char *filename, unsigned char *ptr, bfd_size_type len) -{ - unsigned char n, *p, crc=0, eof; - bfd_size_type i, t; - FILE *f; - if ((f=fopen(filename, "wt")) == NULL) - { - perror("Cant' open file for writing"); - fclose(f); +/// \brief Parse commandline arguments. +/// \return 0 on success, negative on error. +int main(int argc, char **argv) { + char *filenameDriver, *filenameFirmware, *filenameLoader; + char *charPointer; + int prefixLength; + + if(argc < 2) { + fprintf(stderr, "Usage: %s [] []\n", argv[0]); return -1; } - - for(t=0; t size; - offsetData = section->filepos; - printf(".data section found at %p, length %li bytes\n", (void*)offsetData, lenData); - - storage = bfd_get_symtab_upper_bound(file); - syms = malloc(storage); - nsyms = bfd_canonicalize_symtab(file, syms); - for(i=0; ivalue; - if (strcmp(sname, strLoader) == 0) - offsetLoader = asym->value; - } - free(syms); - - offsetFirmware -= offsetData; - offsetLoader -= offsetData; - lenFirmware = offsetLoader - offsetFirmware; - lenLoader = lenData - lenFirmware; - printf("Firmware found at offset 0x%lX, length %li bytes\n", offsetFirmware, lenFirmware); - printf("Loader found at offset 0x%lX, length %li bytes\n", offsetLoader, lenLoader); - - ptrFirmware = malloc(lenFirmware); - ptrLoader = malloc(lenLoader); - if (ptrFirmware == NULL || ptrLoader == NULL) - { - perror("Can't allocate memory"); - bfd_close(file); - return -1; - } - - if (!bfd_get_section_contents(file, section, ptrFirmware, offsetFirmware, lenFirmware)) - { - bfd_perror("Can't get firmware contents"); - bfd_close(file); - return -1; - } - - if (!bfd_get_section_contents(file, section, ptrLoader, offsetLoader, lenLoader)) - { - bfd_perror("Can't get loader contents"); - bfd_close(file); - return -1; - } - - strcpy(filename, model); - strcat(filename, strFirmware); - strcat(filename, strHex); - printf("Writing %s\n", filename); - writeIntelHex(filename, ptrFirmware, lenFirmware); - - strcpy(filename, model); - strcat(filename, strLoader); - strcat(filename, strHex); - printf("Writing %s\n", filename); - writeIntelHex(filename, ptrLoader, lenLoader); + // Search for the data section + for(sectionData = bfdDriver->sections; sectionData != NULL; sectionData = sectionData->next) + if(strcmp(sectionData->name, nameSection) == 0) + break; + if(sectionData == NULL) { + fprintf(stderr, "Section %s not found\n", nameSection); + return -3; + } + printf("Section %s found (starting at 0x%04lx, %li bytes)\n", nameSection, (unsigned long int) sectionData->filepos, (long int) sectionData->size); + + // Search for the symbols we want + symbols = malloc(bfd_get_symtab_upper_bound(bfdDriver)); + symbolCount = bfd_canonicalize_symtab(bfdDriver, symbols); + for(currentSymbol = 0; currentSymbol < symbolCount; currentSymbol++) { + symbolName = bfd_asymbol_name(symbols[currentSymbol]); - free(ptrFirmware); - free(ptrLoader); + if(strcmp(symbolName, nameSymbolFirmware) == 0) + offsetFirmware = symbols[currentSymbol]->value; + if(strcmp(symbolName, nameSymbolLoader) == 0) + offsetLoader = symbols[currentSymbol]->value; + } + free(symbols); + + // Calculate position in section and length + offsetFirmware -= sectionData->filepos; + offsetLoader -= sectionData->filepos; + lengthFirmware = offsetLoader - offsetFirmware; + lengthLoader = sectionData->size - lengthFirmware; + + printf("Symbol %s found (offset 0x%04lx, %li bytes)\n", nameSymbolFirmware, (unsigned long int) offsetFirmware, (long int) lengthFirmware); + printf("Symbol %s found (offset 0x%04lx, %li bytes)\n", nameSymbolLoader, (unsigned long int) offsetLoader, (long int) lengthLoader); + + // Extract data + bufferFirmware = malloc(lengthFirmware); + bufferLoader = malloc(lengthLoader); + if (bufferFirmware == NULL || bufferLoader == NULL) { + fprintf(stderr, "Can't allocate memory\n"); + bfd_close(bfdDriver); + return -4; } - else - { - fprintf(stderr, "Section .data not found\n"); + + if(!bfd_get_section_contents(bfdDriver, sectionData, bufferFirmware, offsetFirmware, lengthFirmware)) { + bfd_perror("Can't get firmware contents"); + bfd_close(bfdDriver); + return -5; } - bfd_close(file); + if(!bfd_get_section_contents(bfdDriver, sectionData, bufferLoader, offsetLoader, lengthLoader)) { + bfd_perror("Can't get loader contents"); + bfd_close(bfdDriver); + return -6; + } + + printf("Saving firmware as %s\n", filenameFirmware); + writeIntelHex(filenameFirmware, bufferFirmware, lengthFirmware); + free(bufferFirmware); + + printf("Saving loader as %s\n", filenameLoader); + writeIntelHex(filenameLoader, bufferLoader, lengthLoader); + free(bufferLoader); + + bfd_close(bfdDriver); return 0; } -int main() +/// \brief Save data to a file in intel hex format. +/// \param filename Name of the output file. +/// \param data Pointer to the binary data that should be stored. +/// \param length Size of the data that should be stored. +/// \return 0 on success, negative on error. +int writeIntelHex(const char *filename, unsigned char *data, unsigned int length) { - int i; + FILE *file; + unsigned char crc, eof; + unsigned int dataIndex, byteIndex, byteCount; + unsigned char *dataPointer; + + file = fopen(filename, "wt"); + if(!file) { + fprintf(stderr, "Can't open %s for writing\n", filename); + fclose(file); + return -1; + } + + for(dataIndex = 0; dataIndex < length; dataIndex += 22) { + eof = -1; // Always check for End of File Record + dataPointer = data + dataIndex; + + // Start code and byte count + byteCount = *dataPointer; + fprintf(file, ":%02X", byteCount); + if(byteCount != 0) + eof = 0; + crc = -*dataPointer++; + dataPointer++; + + // Address + fprintf(file, "%04X", *(unsigned short *) dataPointer); + if(*(unsigned short *) dataPointer != 0) + eof = 0; + crc -= *dataPointer++; + crc -= *dataPointer++; + + // Record type + fprintf(file, "%02X", *dataPointer); + if(*dataPointer != 0x01) + eof = 0; + crc -= *dataPointer++; + + // Data + for(byteIndex = 0; byteIndex < byteCount; byteIndex++) { + fprintf(file, "%02X", *dataPointer); + crc -= *dataPointer++; + } + + // CRC + fprintf(file, "%02X\n", crc); + + if(eof) + break; + } - for(i=0; strModels[i]!=NULL; i++) - extractFirmware(strModels[i]); + fclose(file); return 0; }