Created
January 26, 2019 16:37
-
-
Save kategray/198160ed4676c031b0a6a009ba259505 to your computer and use it in GitHub Desktop.
Convert a Cypress .dld format firmware to an Intel Hex firmware
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env php | |
<?php | |
/** | |
* Convert a cypress DLD file to an intel hex file for analysis purposes. | |
* | |
* Cypress DLD files start with the string "FF380001020304050607". | |
* | |
* You can produce a binary output using something like: | |
* ./dld2ihex.php [file].dld > [file.ihex] | |
* objcopy -I ihex [file].ihex -O binary [file].bin | |
*/ | |
define ('ERROR_NONE', 0); | |
define ('ERROR_INVALID_ARGUMENTS', 1); | |
define ('ERROR_NOT_DLD', 2); | |
define ('DLD_VALID_HEADER', 'FF380001020304050607'); | |
define ('DLD_VALID_FOOTER', 'FF3B0001020304050607'); | |
define ('DLD_START_CODE', 'FF'); | |
define ('DLD_ROW_BYTES', 64); | |
define ('DLD_RECORD_CONSTANT', '01020304050607'); | |
define ('DLD_END_INSTRUCTION', '3B'); | |
define ('INTEL_START_CODE', ':'); | |
define ('INTEL_DATA_RECORD', '00'); | |
define ('INTEL_FOOTER', ':00000001FF'); | |
if ((2 != $_SERVER['argc']) || !file_exists ($_SERVER['argv'][1])) { | |
printf ("Usage: %s [file]\n", $_SERVER['argv'][0]); | |
return ERROR_INVALID_ARGUMENTS; | |
} | |
$input_file = $_SERVER['argv'][1]; | |
$fp = fopen ($input_file, 'r'); | |
if (!$fp) { | |
printf ("Unable to open specified file.\n"); | |
return ERROR_INVALID_ARGUMENTS; | |
} | |
$header = fgets($fp); | |
if (trim ($header) != DLD_VALID_HEADER) { | |
printf ("File does not appear to be a Cypress DLD file.\n"); | |
return ERROR_NOT_DLD; | |
} | |
// Process the file, one line at a time. | |
$intel_entries = array (); | |
// Line number, 0-indexed | |
$line_number = 0; | |
// The end record should be the last record in the file | |
$end_seen = false; | |
while ($line = trim(fgets ($fp))) { | |
$entry = array ( | |
'start_code' => substr($line, 0, 2), | |
'instruction_type' => substr($line, 2, 2), | |
'constant' => substr ($line, 4, 16), | |
'address' => substr ($line, 20, 4), | |
'data' => substr ($line, 24, 128), | |
'checksum' => substr ($line, 152, 4) | |
); | |
if ($entry['start_code'] != DLD_START_CODE || $entry['constant'] != DLD_RECORD_CONSTANT) { | |
printf ("DLD file appears to be malformed at line %d.\n"); | |
return ERROR_NOT_DLD; | |
} else if ($end_seen) { | |
printf ("Records found after end of file instruction.\n"); | |
return ERROR_NOT_DLD; | |
} | |
if ($entry['instruction_type'] == DLD_END_INSTRUCTION) { | |
if ($line != DLD_VALID_FOOTER) { | |
printf ("DLD file appears to have a corrupted end of file instruction.\n"); | |
return; | |
} | |
$intel_entries[] = INTEL_FOOTER; | |
$end_seen = true; | |
continue; | |
} | |
// We need to convert row numbers to addresses to prevent overlapping | |
$address = hexdec ($entry['address']); | |
$entry['intel_address'] = $address * DLD_ROW_BYTES; | |
$intel_entry = sprintf ("%02X%s%s%s", strlen($entry['data'])/2, sprintf ('%02X', $entry['intel_address']), INTEL_DATA_RECORD, $entry['data']); | |
$intel_entry = sprintf ("%s%s%s", INTEL_START_CODE, $intel_entry, intel_checksum ($intel_entry)); | |
$intel_entries[] = $intel_entry; | |
$line_number++; | |
} | |
foreach ($intel_entries as $intel_entry) { | |
echo sprintf ("%s\n", $intel_entry); | |
} | |
return ERROR_NONE; | |
function intel_checksum ($data) { | |
$bytes = str_split ($data, 2); | |
$sum = 0; | |
foreach ($bytes as $byte) { | |
$sum += hexdec ($byte); | |
} | |
// Get Least Significant Byte | |
$sum = $sum & 0xff; | |
// Get two's complement | |
if ($sum > 0) { | |
$sum = 256 - $sum; | |
} | |
return sprintf ('%02X', $sum); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment