FirmwareWrapperExtraction.java 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. package de.nplusc.izc.senabitwiggler;
  2. import com.google.common.base.Charsets;
  3. import com.google.common.primitives.Longs;
  4. import org.yaml.snakeyaml.Yaml;
  5. import java.io.*;
  6. import java.security.MessageDigest;
  7. import java.security.NoSuchAlgorithmException;
  8. public class FirmwareWrapperExtraction {
  9. public static void assembleFirmware(File output, String inputfolder)
  10. {
  11. Yaml y = new Yaml();
  12. try {
  13. LongHeader h = y.loadAs(new FileReader(new File(inputfolder+File.separator+"header.yml")),LongHeader.class);
  14. RandomAccessFile f = new RandomAccessFile(output,"rw");
  15. f.write(h.getVersion_raw());
  16. f.write(Utils.LongToRawBytes(h.getMagicShit()));
  17. f.write(Utils.LongToRawBytes(h.getRandom_id()));
  18. HeaderRecord[] records = h.getHeaderRecords();
  19. int count = records.length;
  20. f.write(Utils.LongToRawBytes(count));
  21. long offset = records[0].getOffset();
  22. for(int i=0;i<count;i++)
  23. {
  24. HeaderRecord r = records[i];
  25. File handle = new File(inputfolder+File.separator+r.getFilename());
  26. r.setLength(handle.length());
  27. r.setOffset(offset+0);
  28. offset+=handle.length();
  29. RandomAccessFile file = new RandomAccessFile(handle,"r");
  30. byte[] bfr = new byte[(int)handle.length()];
  31. file.read(bfr);
  32. byte[] newmd5 = MessageDigest.getInstance("MD5").digest(bfr);
  33. r.setMd5sum(newmd5);
  34. }
  35. for(int i=0;i<count;i++)
  36. {
  37. HeaderRecord r = records[i];
  38. f.write(Utils.LongToRawBytes(r.getShortflag_1()));
  39. f.write(Utils.LongToRawBytes(r.getShortflag_2()));
  40. f.write(Utils.LongToRawBytes(r.getOffset()));
  41. f.write(Utils.LongToRawBytes(r.getLength()));
  42. f.write(r.getMd5sum());
  43. }
  44. for(int i=0;i<count;i++)
  45. {
  46. HeaderRecord r = records[i];
  47. f.write(Utils.LongToRawBytes(r.getShortflag_1()));
  48. f.write(Utils.LongToRawBytes(r.getShortflag_2()));
  49. f.write(Utils.LongToRawBytes(r.getOffset()));
  50. f.write(Utils.LongToRawBytes(r.getLength()));
  51. f.write(Utils.LongToRawBytes(r.getFlag_1()));
  52. f.write(Utils.LongToRawBytes(r.getFlag_2()));
  53. f.write(Utils.LongToRawBytes(r.getFlag_3()));
  54. f.write(Utils.LongToRawBytes(r.getFlag_4()));
  55. f.write(Utils.LongToRawBytes(r.getFlag_5()));
  56. f.write(Utils.LongToRawBytes(r.getUnknown_id()));
  57. f.write(r.getPadding());
  58. byte[] filenamebytes = r.getFilename().getBytes(Charsets.US_ASCII);
  59. byte[] filename = new byte[128];
  60. for(int j=0;j<128;j++)
  61. {
  62. if(j<filenamebytes.length)
  63. {
  64. filename[j]=filenamebytes[j];
  65. }
  66. else
  67. {
  68. filename[j]=0;
  69. }
  70. }
  71. f.write(filename);
  72. f.write(r.getMd5sum());
  73. }
  74. for(int i=0;i<count;i++)
  75. {
  76. HeaderRecord r = records[i];
  77. File handle = new File(inputfolder+File.separator+r.getFilename());
  78. RandomAccessFile file = new RandomAccessFile(handle,"r");
  79. byte[] bfr = new byte[(int)handle.length()];
  80. file.read(bfr);
  81. f.write(bfr);
  82. }
  83. f.close();
  84. } catch (FileNotFoundException e) {
  85. e.printStackTrace();
  86. } catch (IOException e) {
  87. e.printStackTrace();
  88. } catch (NoSuchAlgorithmException e) {
  89. e.printStackTrace();
  90. }
  91. }
  92. public static void extractFirmwareLong(File input, String output) throws InputInvalidException {
  93. byte filler = 0x00;
  94. try (RandomAccessFile f = new RandomAccessFile(input,"r")) {
  95. LongHeader hdr = new LongHeader();
  96. byte[] headermagic = new byte[24];
  97. f.read(headermagic);
  98. String versionName = new String(headermagic, Charsets.US_ASCII).split("\0")[0]; //hack, can be done since strings are shorty. https://stackoverflow.com/a/8843313/1405227
  99. hdr.setVersion_raw(headermagic);
  100. hdr.setVersion(versionName);
  101. //12 more bytes
  102. byte[] magic = new byte[4];
  103. f.read(magic);
  104. hdr.setMagicShit(Longs.fromBytes(filler,filler,filler,filler,magic[3],magic[2],magic[1],magic[0]));
  105. // magic[] = {0x19,0x28,0xc5,0xe6}
  106. byte[] unknown_id = new byte[4];
  107. f.read(unknown_id); //product id
  108. hdr.setRandom_id(Longs.fromBytes(filler,filler,filler,filler,unknown_id[3],unknown_id[2],unknown_id[1],unknown_id[0]));
  109. byte[] count_raw = new byte[4];
  110. f.read(count_raw);
  111. long count_l = (Longs.fromBytes(filler,filler,filler,filler,count_raw[3],count_raw[2],count_raw[1],count_raw[0]));
  112. if(count_l>Integer.MAX_VALUE)
  113. {
  114. throw new InputInvalidException();
  115. }
  116. int count = (int)count_l;
  117. HeaderRecord[] records = new HeaderRecord[count];
  118. byte[] skip = new byte[count*32]; /*skipping over shorty header, repeats content with long one*/
  119. f.read(skip);
  120. for(int i=0;i<count;i++)
  121. {
  122. HeaderRecord record = new HeaderRecord();
  123. byte[] flags1 = new byte[4];
  124. f.read(flags1);
  125. record.setShortflag_1(Longs.fromBytes(filler,filler,filler,filler,flags1[3],flags1[2],flags1[1],flags1[0]));
  126. byte[] flags2 = new byte[4];
  127. f.read(flags2);
  128. record.setShortflag_2(Longs.fromBytes(filler,filler,filler,filler,flags2[3],flags2[2],flags2[1],flags2[0]));
  129. byte[] offset = new byte[4];
  130. f.read(offset);
  131. record.setOffset(Longs.fromBytes(filler,filler,filler,filler,offset[3],offset[2],offset[1],offset[0]));
  132. byte[] length = new byte[4];
  133. f.read(length);
  134. record.setLength(Longs.fromBytes(filler,filler,filler,filler,length[3],length[2],length[1],length[0]));
  135. long[] flags = new long[5];
  136. for(int j=0;j<5;j++)
  137. {
  138. byte[] flags_raw = new byte[4];
  139. f.read(flags_raw);
  140. flags[j] = (Longs.fromBytes(filler,filler,filler,filler,flags_raw[3],flags_raw[2],flags_raw[1],flags_raw[0]));
  141. }
  142. record.setFlag_1(flags[0]);
  143. record.setFlag_2(flags[1]);
  144. record.setFlag_3(flags[2]);
  145. record.setFlag_4(flags[3]);
  146. record.setFlag_5(flags[4]);
  147. byte[] unknown = new byte[4];
  148. f.read(unknown);
  149. record.setUnknown_id(Longs.fromBytes(filler,filler,filler,filler,unknown[3],unknown[2],unknown[1],unknown[0]));
  150. byte[] padding = new byte[128];
  151. f.read(padding);
  152. record.setPadding(padding);
  153. byte[] filename_raw = new byte[128];
  154. f.read(filename_raw);
  155. String filename = new String(filename_raw, Charsets.US_ASCII).split("\0")[0]; //hack, can be done since strings are shorty. https://stackoverflow.com/a/8843313/1405227
  156. record.setFilename(filename);
  157. byte[] md5 = new byte[16];
  158. f.read(md5);
  159. record.setMd5sum(md5);
  160. records[i]=record;
  161. }
  162. hdr.setHeaderRecords(records);
  163. Yaml y = new Yaml();
  164. y.dump(hdr, new FileWriter(new File(output+File.separator+"header.yml")));
  165. for(int i=0;i<records.length;i++)
  166. {
  167. HeaderRecord r = records[i];
  168. String target = output+File.separator+r.getFilename();
  169. long offset = r.getOffset();
  170. int len = (int)r.getLength();
  171. byte[] file = new byte[len];
  172. f.seek(offset);
  173. f.read(file);
  174. RandomAccessFile out = new RandomAccessFile(target,"rw");
  175. out.write(file);
  176. out.close();
  177. }
  178. } catch (FileNotFoundException e) {
  179. e.printStackTrace();
  180. } catch (IOException e) {
  181. e.printStackTrace();
  182. }
  183. }
  184. }