PageRenderTime 32ms CodeModel.GetById 6ms RepoModel.GetById 0ms app.codeStats 0ms

/firmware/pic16/tag-proximity/create_counted_firmware.php

https://github.com/meriac/openbeacon
PHP | 192 lines | 134 code | 19 blank | 39 comment | 9 complexity | 223137399064bddfa8effae9d3ddb53b MD5 | raw file
  1. #!/usr/bin/php
  2. <?php
  3. /***************************************************************
  4. *
  5. * OpenBeacon.org - firmware serialization
  6. *
  7. * Copyright 2006 Milosch Meriac <meriac@openbeacon.de>
  8. *
  9. * This PHP shell scrip takes precompiled intel hex file, increments
  10. * id, stores random seed and XXTEA key and creates output
  11. * hexfile for PicKit2 programmer software.
  12. *
  13. /***************************************************************
  14. /*
  15. This program is free software; you can redistribute it and/or modify
  16. it under the terms of the GNU General Public License as published by
  17. the Free Software Foundation; version 2.
  18. This program is distributed in the hope that it will be useful,
  19. but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. GNU General Public License for more details.
  22. You should have received a copy of the GNU General Public License along
  23. with this program; if not, write to the Free Software Foundation, Inc.,
  24. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  25. */
  26. define('PIC16_DATA_OPCODE',0x34);
  27. define('INPUT_FILE','obj/openbeacon-proximity.hex');
  28. define('OUTPUT_FILE','openbeacon-proximity.hex');
  29. define('COUNT_FILE','firmware_counter');
  30. define('SYMBOLS_FILE','obj/openbeacon-proximity.sym');
  31. define('SYMBOLS_SEG','STRING');
  32. //
  33. // Default TEA encryption key of the tag - MUST CHANGE !
  34. //
  35. $tea_key = array( 0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF );
  36. // Patches list: symbol, relative offset, data
  37. $patch_list = array(
  38. '_oid' => (is_readable(COUNT_FILE))?intval(trim(file_get_contents(COUNT_FILE))):100,
  39. '_seed' => hexdec(substr(md5(microtime().implode('-',$tea_key).rand()),0,8)),
  40. '_xxtea_key' => $tea_key,
  41. );
  42. // Lookup actual symbol offsets from symbols file
  43. $patches=patch_lookup_patches(SYMBOLS_FILE,$patch_list);
  44. // Read HEX file from file
  45. patch_hexread(INPUT_FILE);
  46. // apply patch first time
  47. patch_apply($patches,TRUE);
  48. echo "\n\nOpenBeacon tag ID set to '$patch_list[_oid]'\n\n";
  49. patch_hexwrite(OUTPUT_FILE);
  50. // Increment tag ID
  51. $patch_list['_oid']++;
  52. file_put_contents(COUNT_FILE,$patch_list['_oid']);
  53. //
  54. // Helper functions
  55. //
  56. function patch_lookup_patches($file,$patch_list)
  57. {
  58. $patches = array();
  59. if(!is_readable($file))
  60. exit("Can't read symbol lookup file '$file'\n");
  61. else
  62. foreach(file($file) as $symbol)
  63. {
  64. $symbol = explode(' ',trim($symbol));
  65. $name = $symbol[0];
  66. if($name && array_key_exists($name,$patch_list))
  67. {
  68. if($symbol[3]!=SYMBOLS_SEG)
  69. exit($name.' must be in '.SYMBOLS_SEG." segment - invalid segment $symbol[3] sepecified\n");
  70. $offset = hexdec($symbol[1])*2;
  71. if($offset)
  72. {
  73. $patch = $patch_list[$name];
  74. // remove found patches from list
  75. unset($patch_list[$name]);
  76. if(is_array($patch))
  77. foreach($patch as $content)
  78. {
  79. $patches[$offset]=$content;
  80. $offset+=8;
  81. }
  82. else
  83. $patches[$offset]=$patch;
  84. }
  85. }
  86. }
  87. // halt on missing map file symbols
  88. if( count($patch_list) )
  89. exit('Missing symbol(s) in map file: '.implode(',',array_keys($patch_list))."\n");
  90. return $patches;
  91. }
  92. function patch_hexread($file)
  93. {
  94. global $hexfile,$memory;
  95. $hexfile=array();
  96. $memory=array();
  97. if(!is_readable($file))
  98. exit("Can't read HEX input file '$file'\n");
  99. else
  100. foreach(file($file) as $row=>$line)
  101. {
  102. if(!preg_match('/^:(..)(....)(..)(.*)(..)$/',$line,$matches))
  103. exit("error at line($row)\n");
  104. $rec=array();
  105. foreach(array( 1=>'count', 2=>'address', 3=>'type', 5=>'checksum') as $offset=>$name )
  106. $rec[$name]=hexdec($matches[$offset]);
  107. if($rec['type']>0)
  108. break;
  109. $hexfile[]=$rec;
  110. $address=$rec['address'];
  111. foreach(explode(',',trim(chunk_split($matches[4],2,','),',')) as $byte)
  112. $memory[$address++]=hexdec($byte);
  113. }
  114. }
  115. function patch_apply($patches,$first=FALSE)
  116. {
  117. global $memory;
  118. foreach($patches as $address=>$data)
  119. {
  120. for($i=0;$i<4;$i++)
  121. {
  122. if($first && (!isset($memory[$address]) || ($memory[$address]!=0xFF)))
  123. exit(sprintf("expecting data set to 0xFF at 0x%04X\n",$address));
  124. if($memory[$address+1]!=PIC16_DATA_OPCODE)
  125. exit(sprintf("expecting PIC16 data opcode at 0x%04X\n",$address+1));
  126. $memory[$address]=$data&0xFF;
  127. $data>>=8;
  128. $address+=2;
  129. }
  130. }
  131. }
  132. function patch_hexwrite($file)
  133. {
  134. global $hexfile,$memory;
  135. $handle=fopen($file,'w');
  136. if(!$handle)
  137. exit("Can't open HEX output file '$file'\n");
  138. else
  139. {
  140. foreach($hexfile as $rec)
  141. {
  142. $address=$rec['address'];
  143. $line=sprintf('%02X%04X%02X',$rec['count'],$address,$rec['type']);
  144. for($i=0;$i<$rec['count'];$i++)
  145. $line.=sprintf('%02X',$memory[$address++]);
  146. $crc=0;
  147. foreach(explode(',',chunk_split($line,2,',')) as $byte)
  148. $crc+=hexdec($byte);
  149. fwrite($handle,sprintf(":%s%02X\n",$line,(0x100-$crc)&0xFF));
  150. }
  151. fwrite($handle,":00000001FF\n");
  152. fclose($handle);
  153. }
  154. }
  155. ?>