Commit 328ba56d3a5169c8c0d6dc2c850f301d8952e7f2
1 parent
33dd7c54
Input files as parameters instead of hardcoded strings
Showing
3 changed files
with
201 additions
and
147 deletions
dsoextractfw/ChangeLog
| ... | ... | @@ -23,3 +23,7 @@ |
| 23 | 23 | * Silent make if available |
| 24 | 24 | * Fixed DSO-2100 USB vid/pid |
| 25 | 25 | * Added --with-firmware-dir configure option and udev-rules file generation |
| 26 | + | |
| 27 | +2011-02-03 Oliver Haag <oliver.haag@gmail.com> | |
| 28 | +* Input files are given as commandline parameters (Not hardcoded anymore) | |
| 29 | +* Cleaned up the code | ... | ... |
dsoextractfw/INSTALL
| ... | ... | @@ -5,7 +5,7 @@ $ ./configure |
| 5 | 5 | $ make |
| 6 | 6 | |
| 7 | 7 | Now place the DSO*1.SYS file that came with the windows driver for your oscilloscope into the same directory and run: |
| 8 | -$ ./dsoextractfw | |
| 8 | +$ ./dsoextractfw <driver file> | |
| 9 | 9 | |
| 10 | 10 | 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. |
| 11 | 11 | After restarting udev your oscilloscope should be initialized automatically after connecting it to the computer (You have to reconnect it after installing this package). | ... | ... |
dsoextractfw/dsoextractfw.c
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | // dsoextractfw.c |
| 5 | 5 | // Copyright (C) 2008 Oleg Khudyakov |
| 6 | 6 | // prcoder@potrebitel.ru |
| 7 | -// Copyright (C) 2010 Oliver Haag | |
| 7 | +// Copyright (C) 2010, 2011 Oliver Haag | |
| 8 | 8 | // oliver.haag@gmail.com |
| 9 | 9 | // |
| 10 | 10 | // This program is free software: you can redistribute it and/or modify it |
| ... | ... | @@ -23,184 +23,234 @@ |
| 23 | 23 | //////////////////////////////////////////////////////////////////////////////// |
| 24 | 24 | |
| 25 | 25 | |
| 26 | -#include <stdio.h> | |
| 26 | +#include <ctype.h> | |
| 27 | 27 | #include <malloc.h> |
| 28 | +#include <stdio.h> | |
| 28 | 29 | #include <string.h> |
| 30 | + | |
| 29 | 31 | #include <bfd.h> |
| 30 | 32 | |
| 31 | -static const char *strFirmware = "_firmware"; | |
| 32 | -static const char *strLoader = "_loader"; | |
| 33 | -static const char *strHex = ".hex"; | |
| 34 | -static const char *strDriver = "1.SYS"; | |
| 35 | -static const char *strModels[] = { "DSO2090", "DSO2100", "DSO2150", "DSO2250", "DSO5200", "DSO520A", NULL }; | |
| 36 | 33 | |
| 37 | -int writeIntelHex(const char *filename, unsigned char *ptr, bfd_size_type len); | |
| 38 | -int extractFirmware(const char* model); | |
| 34 | +int extractFirmware(const char *filenameDriver, const char *filenameFirmware, const char *filenameLoader); | |
| 35 | +int writeIntelHex(const char *filename, unsigned char *data, unsigned int length); | |
| 36 | + | |
| 37 | +static const char *filenameEndFirmware = "-firmware.hex"; | |
| 38 | +static const char *filenameEndLoader = "-loader.hex"; | |
| 39 | +static const char *filenameEndDriver = "1.sys"; | |
| 40 | +static const char *nameTarget = "pei-i386"; | |
| 41 | +static const char *nameSection = ".data"; | |
| 42 | +static const char *nameSymbolFirmware = "_firmware"; | |
| 43 | +static const char *nameSymbolLoader = "_loader"; | |
| 39 | 44 | |
| 40 | -int writeIntelHex(const char *filename, unsigned char *ptr, bfd_size_type len) | |
| 41 | -{ | |
| 42 | - unsigned char n, *p, crc=0, eof; | |
| 43 | - bfd_size_type i, t; | |
| 44 | - FILE *f; | |
| 45 | 45 | |
| 46 | - if ((f=fopen(filename, "wt")) == NULL) | |
| 47 | - { | |
| 48 | - perror("Cant' open file for writing"); | |
| 49 | - fclose(f); | |
| 46 | +/// \brief Parse commandline arguments. | |
| 47 | +/// \return 0 on success, negative on error. | |
| 48 | +int main(int argc, char **argv) { | |
| 49 | + char *filenameDriver, *filenameFirmware, *filenameLoader; | |
| 50 | + char *charPointer; | |
| 51 | + int prefixLength; | |
| 52 | + | |
| 53 | + if(argc < 2) { | |
| 54 | + fprintf(stderr, "Usage: %s <input> [<firmware>] [<loader>]\n", argv[0]); | |
| 50 | 55 | return -1; |
| 51 | 56 | } |
| 52 | - | |
| 53 | - for(t=0; t <len; t+=22) | |
| 54 | - { | |
| 55 | - eof = -1; // Always check for End of File Record | |
| 56 | - p = ptr + t; | |
| 57 | - n = *p; | |
| 58 | - fprintf(f, ":%02X", n); | |
| 59 | - if(n != 0) | |
| 60 | - eof = 0; | |
| 61 | - crc = *p++; | |
| 62 | - p++; | |
| 63 | - fprintf(f, "%04X", *(unsigned short *)p); | |
| 64 | - if(*(unsigned short *)p != 0) | |
| 65 | - eof = 0; | |
| 66 | - crc += *p++; | |
| 67 | - crc += *p++; | |
| 68 | - fprintf(f, "%02X", *p); | |
| 69 | - if(*p != 0x01) | |
| 70 | - eof = 0; | |
| 71 | - crc += *p++; | |
| 72 | - for(i=0; i<n; i++) | |
| 73 | - { | |
| 74 | - fprintf(f,"%02X", *p); | |
| 75 | - crc += *p++; | |
| 76 | - } | |
| 77 | - crc = 1 + ~crc; | |
| 78 | - fprintf(f, "%02X\n", crc); | |
| 57 | + filenameDriver = argv[1]; | |
| 58 | + | |
| 59 | + prefixLength = strlen(filenameDriver) - strlen(filenameEndDriver); | |
| 60 | + | |
| 61 | + if(argc < 3) { | |
| 62 | + // Guess correct filename for firmware | |
| 63 | + filenameFirmware = malloc(prefixLength + strlen(filenameEndFirmware) + 1); | |
| 64 | + memcpy(filenameFirmware, filenameDriver, prefixLength); | |
| 65 | + strcpy(filenameFirmware + prefixLength, filenameEndFirmware); | |
| 79 | 66 | |
| 80 | - if(eof) | |
| 81 | - break; | |
| 67 | + // Convert filename to lowercase | |
| 68 | + charPointer = strrchr(filenameFirmware, '/'); | |
| 69 | + if(charPointer == NULL) | |
| 70 | + charPointer = filenameFirmware; | |
| 71 | + for(; *charPointer != 0; charPointer++) | |
| 72 | + *charPointer = tolower(*charPointer); | |
| 82 | 73 | } |
| 83 | - fclose(f); | |
| 84 | - | |
| 85 | - return 0; | |
| 74 | + else { | |
| 75 | + filenameFirmware = argv[2]; | |
| 76 | + } | |
| 77 | + | |
| 78 | + if(argc < 4) { | |
| 79 | + // Guess correct filename for loader | |
| 80 | + filenameLoader = malloc(prefixLength + strlen(filenameEndLoader) + 1); | |
| 81 | + memcpy(filenameLoader, filenameDriver, prefixLength); | |
| 82 | + strcpy(filenameLoader + prefixLength, filenameEndLoader); | |
| 83 | + | |
| 84 | + // Convert filename to lowercase | |
| 85 | + charPointer = strrchr(filenameLoader, '/'); | |
| 86 | + if(charPointer == NULL) | |
| 87 | + charPointer = filenameLoader; | |
| 88 | + for(; *charPointer != 0; charPointer++) | |
| 89 | + *charPointer = tolower(*charPointer); | |
| 90 | + } | |
| 91 | + else { | |
| 92 | + filenameFirmware = argv[3]; | |
| 93 | + } | |
| 94 | + | |
| 95 | + return extractFirmware(filenameDriver, filenameFirmware, filenameLoader); | |
| 86 | 96 | } |
| 87 | 97 | |
| 88 | -int extractFirmware(const char* model) | |
| 89 | -{ | |
| 90 | - bfd *file; | |
| 91 | - asection *section; | |
| 92 | - unsigned storage; | |
| 93 | - asymbol **syms = NULL; | |
| 94 | - asymbol *asym; | |
| 95 | - unsigned nsyms, i; | |
| 96 | - const char *sname; | |
| 97 | - bfd_size_type offsetData = 0, lenData = 0; | |
| 98 | - bfd_size_type offsetFirmware = 0, offsetLoader = 0; | |
| 99 | - bfd_size_type lenFirmware = 0, lenLoader = 0; | |
| 100 | - unsigned char *ptrFirmware, *ptrLoader; | |
| 101 | - char filename[256]; | |
| 98 | +/// \brief Extract firmware and loader data from original driver file. | |
| 99 | +/// \param filenameDriver Name of the original driver file. | |
| 100 | +/// \param filenameFirmware Name of the file where the firmware should be saved. | |
| 101 | +/// \param filenameDriver Name of the file where the loader should be saved. | |
| 102 | +/// \return 0 on success, negative on error. | |
| 103 | +int extractFirmware(const char *filenameDriver, const char *filenameFirmware, const char *filenameLoader) { | |
| 104 | + bfd *bfdDriver; | |
| 105 | + asection *sectionData; | |
| 102 | 106 | |
| 103 | - strcpy(filename, model); | |
| 104 | - strcat(filename, strDriver); | |
| 105 | - printf("Searching %s\n", filename); | |
| 107 | + asymbol **symbols; | |
| 108 | + unsigned int symbolCount; | |
| 109 | + unsigned currentSymbol; | |
| 110 | + const char *symbolName; | |
| 106 | 111 | |
| 112 | + bfd_size_type offsetFirmware = 0, offsetLoader = 0; | |
| 113 | + bfd_size_type lengthFirmware = 0, lengthLoader = 0; | |
| 114 | + unsigned char *bufferFirmware, *bufferLoader; | |
| 115 | + | |
| 116 | + // Initialize bfd and open driver file | |
| 107 | 117 | bfd_init(); |
| 108 | - file = bfd_openr(filename, 0);//"efi-app-ia32"); | |
| 109 | - if (!file) | |
| 110 | - { | |
| 118 | + bfdDriver = bfd_openr(filenameDriver, nameTarget); | |
| 119 | + if(!bfdDriver) { | |
| 111 | 120 | bfd_perror("Error opening file"); |
| 112 | 121 | return -1; |
| 113 | 122 | } |
| 114 | 123 | |
| 115 | - if (!bfd_check_format(file, bfd_object)) | |
| 116 | - { | |
| 124 | + if(!bfd_check_format(bfdDriver, bfd_object)) { | |
| 117 | 125 | bfd_perror("bfd_check_format"); |
| 118 | - bfd_close (file); | |
| 119 | - return -1; | |
| 126 | + bfd_close(bfdDriver); | |
| 127 | + return -2; | |
| 120 | 128 | } |
| 121 | 129 | |
| 122 | - section = bfd_get_section_by_name(file, ".data"); | |
| 123 | - if (section != NULL) | |
| 124 | - { | |
| 125 | - lenData = section->size; | |
| 126 | - offsetData = section->filepos; | |
| 127 | - printf(".data section found at %p, length %li bytes\n", (void*)offsetData, lenData); | |
| 128 | - | |
| 129 | - storage = bfd_get_symtab_upper_bound(file); | |
| 130 | - syms = malloc(storage); | |
| 131 | - nsyms = bfd_canonicalize_symtab(file, syms); | |
| 132 | - for(i=0; i<nsyms; i++) | |
| 133 | - { | |
| 134 | - asym = syms[i]; | |
| 135 | - sname = bfd_asymbol_name(asym); | |
| 136 | - if (strcmp(sname, strFirmware) == 0) | |
| 137 | - offsetFirmware = asym->value; | |
| 138 | - if (strcmp(sname, strLoader) == 0) | |
| 139 | - offsetLoader = asym->value; | |
| 140 | - } | |
| 141 | - free(syms); | |
| 142 | - | |
| 143 | - offsetFirmware -= offsetData; | |
| 144 | - offsetLoader -= offsetData; | |
| 145 | - lenFirmware = offsetLoader - offsetFirmware; | |
| 146 | - lenLoader = lenData - lenFirmware; | |
| 147 | - printf("Firmware found at offset 0x%lX, length %li bytes\n", offsetFirmware, lenFirmware); | |
| 148 | - printf("Loader found at offset 0x%lX, length %li bytes\n", offsetLoader, lenLoader); | |
| 149 | - | |
| 150 | - ptrFirmware = malloc(lenFirmware); | |
| 151 | - ptrLoader = malloc(lenLoader); | |
| 152 | - if (ptrFirmware == NULL || ptrLoader == NULL) | |
| 153 | - { | |
| 154 | - perror("Can't allocate memory"); | |
| 155 | - bfd_close(file); | |
| 156 | - return -1; | |
| 157 | - } | |
| 158 | - | |
| 159 | - if (!bfd_get_section_contents(file, section, ptrFirmware, offsetFirmware, lenFirmware)) | |
| 160 | - { | |
| 161 | - bfd_perror("Can't get firmware contents"); | |
| 162 | - bfd_close(file); | |
| 163 | - return -1; | |
| 164 | - } | |
| 165 | - | |
| 166 | - if (!bfd_get_section_contents(file, section, ptrLoader, offsetLoader, lenLoader)) | |
| 167 | - { | |
| 168 | - bfd_perror("Can't get loader contents"); | |
| 169 | - bfd_close(file); | |
| 170 | - return -1; | |
| 171 | - } | |
| 172 | - | |
| 173 | - strcpy(filename, model); | |
| 174 | - strcat(filename, strFirmware); | |
| 175 | - strcat(filename, strHex); | |
| 176 | - printf("Writing %s\n", filename); | |
| 177 | - writeIntelHex(filename, ptrFirmware, lenFirmware); | |
| 178 | - | |
| 179 | - strcpy(filename, model); | |
| 180 | - strcat(filename, strLoader); | |
| 181 | - strcat(filename, strHex); | |
| 182 | - printf("Writing %s\n", filename); | |
| 183 | - writeIntelHex(filename, ptrLoader, lenLoader); | |
| 130 | + // Search for the data section | |
| 131 | + for(sectionData = bfdDriver->sections; sectionData != NULL; sectionData = sectionData->next) | |
| 132 | + if(strcmp(sectionData->name, nameSection) == 0) | |
| 133 | + break; | |
| 134 | + if(sectionData == NULL) { | |
| 135 | + fprintf(stderr, "Section %s not found\n", nameSection); | |
| 136 | + return -3; | |
| 137 | + } | |
| 138 | + printf("Section %s found (starting at 0x%04lx, %li bytes)\n", nameSection, (unsigned long int) sectionData->filepos, (long int) sectionData->size); | |
| 139 | + | |
| 140 | + // Search for the symbols we want | |
| 141 | + symbols = malloc(bfd_get_symtab_upper_bound(bfdDriver)); | |
| 142 | + symbolCount = bfd_canonicalize_symtab(bfdDriver, symbols); | |
| 143 | + for(currentSymbol = 0; currentSymbol < symbolCount; currentSymbol++) { | |
| 144 | + symbolName = bfd_asymbol_name(symbols[currentSymbol]); | |
| 184 | 145 | |
| 185 | - free(ptrFirmware); | |
| 186 | - free(ptrLoader); | |
| 146 | + if(strcmp(symbolName, nameSymbolFirmware) == 0) | |
| 147 | + offsetFirmware = symbols[currentSymbol]->value; | |
| 148 | + if(strcmp(symbolName, nameSymbolLoader) == 0) | |
| 149 | + offsetLoader = symbols[currentSymbol]->value; | |
| 150 | + } | |
| 151 | + free(symbols); | |
| 152 | + | |
| 153 | + // Calculate position in section and length | |
| 154 | + offsetFirmware -= sectionData->filepos; | |
| 155 | + offsetLoader -= sectionData->filepos; | |
| 156 | + lengthFirmware = offsetLoader - offsetFirmware; | |
| 157 | + lengthLoader = sectionData->size - lengthFirmware; | |
| 158 | + | |
| 159 | + printf("Symbol %s found (offset 0x%04lx, %li bytes)\n", nameSymbolFirmware, (unsigned long int) offsetFirmware, (long int) lengthFirmware); | |
| 160 | + printf("Symbol %s found (offset 0x%04lx, %li bytes)\n", nameSymbolLoader, (unsigned long int) offsetLoader, (long int) lengthLoader); | |
| 161 | + | |
| 162 | + // Extract data | |
| 163 | + bufferFirmware = malloc(lengthFirmware); | |
| 164 | + bufferLoader = malloc(lengthLoader); | |
| 165 | + if (bufferFirmware == NULL || bufferLoader == NULL) { | |
| 166 | + fprintf(stderr, "Can't allocate memory\n"); | |
| 167 | + bfd_close(bfdDriver); | |
| 168 | + return -4; | |
| 187 | 169 | } |
| 188 | - else | |
| 189 | - { | |
| 190 | - fprintf(stderr, "Section .data not found\n"); | |
| 170 | + | |
| 171 | + if(!bfd_get_section_contents(bfdDriver, sectionData, bufferFirmware, offsetFirmware, lengthFirmware)) { | |
| 172 | + bfd_perror("Can't get firmware contents"); | |
| 173 | + bfd_close(bfdDriver); | |
| 174 | + return -5; | |
| 191 | 175 | } |
| 192 | 176 | |
| 193 | - bfd_close(file); | |
| 177 | + if(!bfd_get_section_contents(bfdDriver, sectionData, bufferLoader, offsetLoader, lengthLoader)) { | |
| 178 | + bfd_perror("Can't get loader contents"); | |
| 179 | + bfd_close(bfdDriver); | |
| 180 | + return -6; | |
| 181 | + } | |
| 182 | + | |
| 183 | + printf("Saving firmware as %s\n", filenameFirmware); | |
| 184 | + writeIntelHex(filenameFirmware, bufferFirmware, lengthFirmware); | |
| 185 | + free(bufferFirmware); | |
| 186 | + | |
| 187 | + printf("Saving loader as %s\n", filenameLoader); | |
| 188 | + writeIntelHex(filenameLoader, bufferLoader, lengthLoader); | |
| 189 | + free(bufferLoader); | |
| 190 | + | |
| 191 | + bfd_close(bfdDriver); | |
| 194 | 192 | |
| 195 | 193 | return 0; |
| 196 | 194 | } |
| 197 | 195 | |
| 198 | -int main() | |
| 196 | +/// \brief Save data to a file in intel hex format. | |
| 197 | +/// \param filename Name of the output file. | |
| 198 | +/// \param data Pointer to the binary data that should be stored. | |
| 199 | +/// \param length Size of the data that should be stored. | |
| 200 | +/// \return 0 on success, negative on error. | |
| 201 | +int writeIntelHex(const char *filename, unsigned char *data, unsigned int length) | |
| 199 | 202 | { |
| 200 | - int i; | |
| 203 | + FILE *file; | |
| 204 | + unsigned char crc, eof; | |
| 205 | + unsigned int dataIndex, byteIndex, byteCount; | |
| 206 | + unsigned char *dataPointer; | |
| 207 | + | |
| 208 | + file = fopen(filename, "wt"); | |
| 209 | + if(!file) { | |
| 210 | + fprintf(stderr, "Can't open %s for writing\n", filename); | |
| 211 | + fclose(file); | |
| 212 | + return -1; | |
| 213 | + } | |
| 214 | + | |
| 215 | + for(dataIndex = 0; dataIndex < length; dataIndex += 22) { | |
| 216 | + eof = -1; // Always check for End of File Record | |
| 217 | + dataPointer = data + dataIndex; | |
| 218 | + | |
| 219 | + // Start code and byte count | |
| 220 | + byteCount = *dataPointer; | |
| 221 | + fprintf(file, ":%02X", byteCount); | |
| 222 | + if(byteCount != 0) | |
| 223 | + eof = 0; | |
| 224 | + crc = -*dataPointer++; | |
| 225 | + dataPointer++; | |
| 226 | + | |
| 227 | + // Address | |
| 228 | + fprintf(file, "%04X", *(unsigned short *) dataPointer); | |
| 229 | + if(*(unsigned short *) dataPointer != 0) | |
| 230 | + eof = 0; | |
| 231 | + crc -= *dataPointer++; | |
| 232 | + crc -= *dataPointer++; | |
| 233 | + | |
| 234 | + // Record type | |
| 235 | + fprintf(file, "%02X", *dataPointer); | |
| 236 | + if(*dataPointer != 0x01) | |
| 237 | + eof = 0; | |
| 238 | + crc -= *dataPointer++; | |
| 239 | + | |
| 240 | + // Data | |
| 241 | + for(byteIndex = 0; byteIndex < byteCount; byteIndex++) { | |
| 242 | + fprintf(file, "%02X", *dataPointer); | |
| 243 | + crc -= *dataPointer++; | |
| 244 | + } | |
| 245 | + | |
| 246 | + // CRC | |
| 247 | + fprintf(file, "%02X\n", crc); | |
| 248 | + | |
| 249 | + if(eof) | |
| 250 | + break; | |
| 251 | + } | |
| 201 | 252 | |
| 202 | - for(i=0; strModels[i]!=NULL; i++) | |
| 203 | - extractFirmware(strModels[i]); | |
| 253 | + fclose(file); | |
| 204 | 254 | |
| 205 | 255 | return 0; |
| 206 | 256 | } | ... | ... |