Skip to content

Instantly share code, notes, and snippets.

@kategray
Created January 26, 2019 16:37
Show Gist options
  • Save kategray/198160ed4676c031b0a6a009ba259505 to your computer and use it in GitHub Desktop.
Save kategray/198160ed4676c031b0a6a009ba259505 to your computer and use it in GitHub Desktop.
Convert a Cypress .dld format firmware to an Intel Hex firmware
#!/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