root/tools/firmware_load.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. addBufRange
  2. findRanges
  3. idx_valid
  4. idx2adr
  5. adr2idx
  6. adr2ptr
  7. idxcorr
  8. set_ignore_errors
  9. fwadr
  10. fwval
  11. fwRd
  12. fwRn
  13. fwRnMOV
  14. fwOp2
  15. LDR2adr
  16. LDR2idx
  17. LDR2val
  18. ADR2adr
  19. ALUop2
  20. ALUop2a
  21. idxFollowBranch
  22. followBranch
  23. followBranch2
  24. isLDR_PC
  25. isLDR_PC_cond
  26. isLDR_SP
  27. isLDR
  28. isLDR_cond
  29. isADR_PC
  30. isADR_PC_cond
  31. isADR
  32. isLDMFD
  33. isLDMFD_PC
  34. isSTMFD
  35. isSTMFD_LR
  36. isSTR
  37. isSTR_cond
  38. isBX
  39. isBX_cond
  40. isBX_LR
  41. isBLX
  42. isBL
  43. isBL_cond
  44. isBLEQ
  45. isB
  46. isBorBL
  47. isCMP
  48. isMOV
  49. isMOV_immed
  50. isORR
  51. isADD
  52. isSUB
  53. isASCIIstring
  54. find_Nth_str
  55. find_str
  56. find_str_bytes
  57. find_inst
  58. find_inst_rev
  59. find_Nth_inst
  60. find_Nth_inst_rev
  61. find_strptr_ref
  62. find_str_ref
  63. find_nxt_str_ref
  64. find_BL
  65. find_B
  66. search_fw
  67. search_fw_bytes
  68. load_firmware

   1 
   2 // Firmware file handling for Canon camera firmware dumps
   3 // Note: only supports DryOS based cameras and ARM32 code.
   4 //       the cameras operate in little endian mode, this code assumes it will
   5 //       be compiled and run on a little endian CPU.
   6 //       It won't work on anything else.
   7 
   8 //------------------------------------------------------------------------------------------------------------
   9 
  10 #include <stdlib.h>
  11 #include <stdio.h>
  12 #include <stdint.h>
  13 #include <string.h>
  14 #include <time.h>
  15 #include <stdarg.h>
  16 
  17 #include "dancingbits.h"
  18 #include "stubs_load.h"
  19 #include "firmware_load.h"
  20 
  21 //------------------------------------------------------------------------------------------------------------
  22 
  23 // These must be supplied elsewhere
  24 extern void error(char*, int);
  25 extern void usage(char *err);
  26 
  27 //------------------------------------------------------------------------------------------------------------
  28 
  29 // Firmware handling
  30 
  31 // Currently used by:
  32 //      finsig_dryos.c for generating stubs_entry.S
  33 //      code_gen.c for generating CHDK source code
  34 
  35 // The firmware dump is loaded into an array of 'uint32_t' 32 bit unsigned integer values
  36 // this simpifies the access and analysis of the data (all ARM32 instructions are 32 bits long and 32 bit aligned)
  37 
  38 // The functions that analyse the firmware work with either memory addresses (uint32_t) or indexes (int)
  39 // The indexes are to the memory array where the firmware is loaded.
  40 // So for a firmware that loads at address 0xFF810000, the index of this instruction in the array will be 0.
  41 // The index for 0xFF810004 = 1, etc.
  42 
  43 // Functions take a pointer to a 'firmware' structure as the first parameter and operate on the contents
  44 // of this structure. Can be used to load and compare multiple dumps.
  45 
  46 //------------------------------------------------------------------------------------------------------------
  47 
  48 // Most firmware dumps contain large blocks that have a value of only 0xFFFFFFFF.
  49 // The BufRange structure and list stores the valid ranges so these empty blocks can be skipped when
  50 // searching for stuff.
  51 
  52 // Add a valid range to the list
  53 void addBufRange(firmware *fw, int o, int l)
  54 {
  55     BufRange *n = malloc(sizeof(BufRange));
  56     n->p = fw->buf + o;
  57     n->off = o;
  58     n->len = l;
  59     n->next = 0;
  60     if (fw->br == 0)
  61     {
  62         fw->br = n;
  63     }
  64     else
  65     {
  66         fw->last->next = n;
  67     }
  68     fw->last = n;
  69 }
  70 
  71 // Find valid ranges for the firmware dump
  72 void findRanges(firmware *fw)
  73 {
  74     int i, j, k;
  75 
  76     // Find all the valid ranges for checking (skips over large blocks of 0xFFFFFFFF)
  77     fw->br = 0; fw->last = 0;
  78     k = -1; j = 0;
  79     for (i = 0; i < fw->size; i++)
  80     {
  81         if (fw->buf[i] == 0xFFFFFFFF)   // Possible start of block to skip
  82         {
  83             if (k == -1)            // Mark start of possible skip block
  84             {
  85                 k = i;
  86             }
  87         }
  88         else                        // Found end of block ?
  89         {
  90             if (k != -1)
  91             {
  92                 if (i - k > 32)     // If block more than 32 words then we want to skip it
  93                 {
  94                     if (k - j > 8)
  95                     {
  96                         // Add a range record for the previous valid range (ignore short ranges)
  97                         addBufRange(fw,j,k - j);
  98                     }
  99                     j = i;          // Reset valid range start to current position
 100                 }
 101                 k = -1;             // Reset marker for skip block
 102             }
 103         }
 104     }
 105     // Add range for last valid block
 106     if (k != -1)
 107     {
 108         if (k - j > 8)
 109         {
 110             addBufRange(fw,j,k - j);
 111         }
 112     }
 113     else
 114     {
 115         if (i - j > 8)
 116         {
 117             addBufRange(fw,j,i - j);
 118         }
 119     }
 120 }
 121 
 122 //------------------------------------------------------------------------------------------------------------
 123 
 124 // Check if the supplied index 'i' is valid for the firmware dump
 125 // Takes into account cameras with 'alternate' firmware base addresses (S110)
 126 // and those that copy a block of the firmware code to RAM (DryOS 50 and up)
 127 
 128 // Assumptions
 129 //  The 'alternate' copy of the firmware is loaded at a higher address than the base copy
 130 //      e.g. base address = 0xF8000000, alt address = 0xFF000000
 131 //          --> i > fw->size
 132 //  The firmware is always loaded at a memory address higher than the RAM that code is
 133 //  copied to.
 134 //          --> i < 0
 135 
 136 int idx_valid(firmware *fw, int i)
 137 {
 138     if ((i >= 0) && (i < fw->size))
 139         return 1;
 140     if ((fw->dryos_ver >= 51) && (fw->alt_base) && (i >= fw->size))
 141     {
 142         i = ((i * 4) - (fw->alt_base - fw->base)) / 4;
 143         if ((i >= 0) && (i < fw->size))
 144             return 1;
 145     }
 146     if (fw->dryos_ver >= 50)
 147     {
 148         int i2 = ((i * 4) + (fw->base - fw->base2)) / 4;
 149         if ((i2 >= 0) && (i2 < fw->size2))
 150             return 1;
 151         // RAM code can also reference ROM, check for that
 152         if (idx2adr(fw,i)>=fw->base && idx2adr(fw,i)<(fw->base+fw->size*4))
 153             return 1;
 154     }
 155     return 0;
 156 }
 157 
 158 // Convert an instruction index to a memory address (see above regarding RAM and 'alternate' values)
 159 uint32_t idx2adr(firmware *fw, int idx)
 160 {
 161     return fw->base + (idx << 2);
 162 }
 163 
 164 // Convert a memory address to an instruction index (see above regarding RAM and 'alternate' values)
 165 int adr2idx(firmware *fw, uint32_t adr)
 166 {
 167     if (adr < fw->base)
 168         return -((fw->base - adr) >> 2);
 169     else
 170         return (adr - fw->base) >> 2;
 171 }
 172 
 173 // Convert a memory address to a pointer into the firmware memory buffer
 174 char* adr2ptr(firmware *fw, uint32_t adr)
 175 {
 176     if ((fw->dryos_ver >= 51) && (fw->alt_base) && (adr >= fw->alt_base))
 177     {
 178         return ((char*)fw->buf) + (adr - fw->alt_base);
 179     }
 180     if ((fw->dryos_ver >= 50) && (adr < fw->base))
 181     {
 182         adr = (adr - fw->base2) + fw->base_copied;
 183     }
 184     return ((char*)fw->buf) + (adr - fw->base);
 185 }
 186 
 187 // check for code copied to RAM, correct idx if needed
 188 int idxcorr(firmware *fw, int idx)
 189 {
 190     static int inited = 0;
 191     static int b2oidx, b2idx;
 192     if (!inited)
 193     {
 194         b2oidx = adr2idx(fw, fw->base_copied);
 195         b2idx = adr2idx(fw, fw->base2);
 196         inited = 1;
 197     }
 198 
 199     if (fw->base2)
 200     {
 201         if ((idx >= b2oidx) && (idx < b2oidx + fw->size2))
 202         {
 203             idx = idx - b2oidx + b2idx;
 204         }
 205     }
 206     return idx;
 207 }
 208 //------------------------------------------------------------------------------------------------------------
 209 
 210 static int ignore_errors = 0;
 211 
 212 void set_ignore_errors(int n)
 213 {
 214     ignore_errors = n;
 215 }
 216 
 217 // These functions should be used to get data & instructions in the firmware dump
 218 // This will ensure that everything works correctly for code / data referenced in RAM
 219 // or the 'alternate' base address for the firmware.
 220 
 221 // Return a pointer to the instruction/data in the memory array at the specified index
 222 // Takes care of converting RAM and 'alternate' indexes and addresses
 223 uint32_t* fwadr(firmware *fw, int i)
 224 {
 225     if ((i >= 0) && (i < fw->size))
 226         return &fw->buf[i];
 227     if ((fw->dryos_ver >= 51) && (fw->alt_base) && (i >= fw->size))
 228     {
 229         i = ((i * 4) - (fw->alt_base - fw->base)) / 4;
 230         if ((i >= 0) && (i < fw->size))
 231             return &fw->buf[i];
 232     }
 233     if ((fw->dryos_ver >= 50) && (i < 0))
 234     {
 235         i = ((i * 4) + (fw->base - fw->base2)) / 4;
 236         if ((i >= 0) && (i < fw->size2))
 237             return &fw->buf2[i];
 238     }
 239     if (ignore_errors)
 240     {
 241         return &fw->buf[0];
 242     }
 243     fprintf(stderr,"Invalid firmware offset %d.\n",i);
 244     error("\nInvalid firmware offset %d. Possible corrupt firmware or incorrect start address.\n",i);
 245     return 0;
 246 }
 247 
 248 // Return the instruction / data at the specified index
 249 uint32_t fwval(firmware *fw, int i)
 250 {
 251     return *fwadr(fw,i);
 252 }
 253 
 254 // Return the destination register of the instruction at the specified index
 255 int fwRd(firmware *fw, int i)
 256 {
 257     // Destination register - Rd
 258     return (*fwadr(fw,i) & 0x0000F000) >> 12;
 259 }
 260 
 261 // Return the source register of the instruction at the specified index
 262 int fwRn(firmware *fw, int i)
 263 {
 264     // Source register - Rn
 265     return (*fwadr(fw,i) & 0x000F0000) >> 16;
 266 }
 267 
 268 // Return the source register of the instruction at the specified index
 269 int fwRnMOV(firmware *fw, int i)
 270 {
 271     // Source register - Rn
 272     return (*fwadr(fw,i) & 0x0000000F);
 273 }
 274 
 275 // Return the operand2 value of the instruction at the specified index
 276 int fwOp2(firmware *fw, int i)
 277 {
 278     // Operand2
 279     return (*fwadr(fw,i) & 0x00000FFF);
 280 }
 281 
 282 //------------------------------------------------------------------------------------------------------------
 283 
 284 // decode LDR instruction at offset and return firmware address pointed to
 285 uint32_t LDR2adr(firmware *fw, int offset)
 286 {
 287     uint32_t inst = fwval(fw,offset);
 288     int offst = (inst & 0xFFF);
 289     uint32_t fadr = (inst & 0x00800000)?idx2adr(fw,offset+2)+offst:idx2adr(fw,offset+2)-offst;
 290     return fadr;
 291 }
 292 
 293 // decode LDR instruction at offset and return firmware buffer index of the new address
 294 uint32_t LDR2idx(firmware *fw, int offset)
 295 {
 296     return adr2idx(fw,LDR2adr(fw,offset));
 297 }
 298 
 299 // decode LDR instruction at offset and return firmware value stored at the address
 300 uint32_t LDR2val(firmware *fw, int offset)
 301 {
 302     return fwval(fw,adr2idx(fw,LDR2adr(fw,offset)));
 303 }
 304 
 305 //------------------------------------------------------------------------------------------------------------
 306 
 307 // decode ADR instruction at offset and return firmware address pointed to
 308 // NOT COMPLETE
 309 uint32_t ADR2adr(firmware *fw, int offset)
 310 {
 311     uint32_t inst = fwval(fw,offset);
 312     int rot = 32 - ((inst & 0xF00) >> 7);
 313     int offst = (inst & 0xFF) <<rot;
 314     uint32_t fadr = 0;
 315     switch (inst & 0x01E00000)
 316     {
 317         case 0x00400000:    // SUB
 318             fadr = idx2adr(fw,offset+2)-offst;
 319             break;
 320         case 0x00800000:    // ADD
 321             fadr = idx2adr(fw,offset+2)+offst;
 322             break;
 323         case 0x01A00000:    // MOV
 324             //fprintf(stderr,"***** ADR2adr MOV\n");
 325             break;
 326         case 0x01E00000:    // MVN
 327             //fprintf(stderr,"***** ADR2adr MVN\n");
 328             break;
 329     }
 330     return fadr;
 331 }
 332 
 333 // decode operand2 from ALU inst (not complete!)
 334 uint32_t ALUop2(firmware *fw, int offset)
 335 {
 336     uint32_t inst = fwval(fw,offset);
 337     int rot = 32 - ((inst & 0xF00) >> 7);
 338     int offst = (inst & 0xFF) <<rot;
 339     uint32_t fadr = 0;
 340     switch (inst & 0x03E00000)
 341     {
 342         case 0x02400000:    // SUB Immed
 343         case 0x02800000:    // ADD Immed
 344         case 0x03400000:    // CMP Immed
 345         case 0x03A00000:    // MOV Immed
 346         case 0x03C00000:    // BIC Immed
 347             fadr = offst;
 348             break;
 349     }
 350     return fadr;
 351 }
 352 
 353 // decode operand2 from ALU inst (not complete, try2 - based on chdk_dasm code)
 354 uint32_t ALUop2a(firmware *fw, int offset)
 355 {
 356     uint32_t inst = fwval(fw,offset);
 357     uint32_t rot = (inst>>7)&0x1e;
 358     uint32_t imm8 = inst & 0xff;
 359     uint32_t offst = (imm8>>rot) | (imm8<<(32-rot));
 360     uint32_t fadr = 0;
 361     switch (inst & 0x03E00000)
 362     {
 363         case 0x02400000:    // SUB Immed
 364         case 0x02800000:    // ADD Immed
 365         case 0x03A00000:    // MOV Immed
 366         case 0x03C00000:    // BIC Immed
 367         case 0x03800000:    // ORR Immed
 368             fadr = offst;
 369             break;
 370     }
 371     return fadr;
 372 }
 373 
 374 //------------------------------------------------------------------------------------------------------------
 375 
 376 // Follow the B / BL / LDR PC instruction at the specified index and return the index of the new location
 377 // Notes:
 378 //      If offset == 0 returns the original index (fidx)
 379 //      The B / BL instruction is at 'fidx + (offset & 0xFFFFFF) - 1'
 380 //      The '(offset & 0xFF000000)' value is a mask that determines instruction matching
 381 //          offset & 0xFF000000 == 0x00000000 --> match B only
 382 //          offset & 0xFF000000 == 0x01000000 --> match B or BL
 383 int idxFollowBranch(firmware *fw, int fidx, int offset)
 384 {
 385     if (offset)
 386     {
 387         uint32_t msk = ~(offset & 0xFF000000);
 388         fidx += ((offset & 0x00FFFFFF) - 1);
 389         uint32_t inst = fwval(fw,fidx);
 390         if ((inst & (0xFF000000&msk)) == (0xEA000000&msk))  // Branch (B or BL depending on msk)
 391         {
 392             int o = inst & 0x00FFFFFF;
 393             if (o & 0x00800000) o |= 0xFF000000;
 394             fidx = fidx + o + 2;
 395         }
 396         else if ((inst & (0xFFFFF000)) == (0xE51FF000))     // LDR PC,=...
 397         {
 398             fidx = adr2idx(fw,LDR2val(fw,fidx));
 399         }
 400     }
 401     return fidx;
 402 }
 403 
 404 // Follow the B / BL / LDR PC instruction at the specified address and return the address of the new location
 405 // Notes as per above.
 406 uint32_t followBranch(firmware *fw, uint32_t fadr, int offset)
 407 {
 408     if (offset)
 409     {
 410         uint32_t msk = ~(offset & 0xFF000000);
 411         uint32_t fidx = adr2idx(fw,fadr);  // function index
 412         fidx += ((offset & 0x00FFFFFF) - 1);
 413         uint32_t inst = fwval(fw,fidx);
 414         if ((inst & (0xFF000000&msk)) == (0xEA000000&msk))  // Branch (B or BL depending on msk)
 415         {
 416             int o = inst & 0x00FFFFFF;
 417             if (o & 0x00800000) o |= 0xFF000000;
 418             if (idx_valid(fw,fidx+o+2))
 419                 fadr = idx2adr(fw,fidx+o+2);
 420         }
 421         else if ((inst & (0xFFFFF000)) == (0xE51FF000))     // LDR PC,=...
 422         {
 423             fadr = LDR2val(fw,fidx);
 424         }
 425     }
 426     return fadr;
 427 }
 428 
 429 // As above; but if offset == 1 then follow any branch at the new location
 430 uint32_t followBranch2(firmware *fw, uint32_t fadr, int offset)
 431 {
 432     fadr = followBranch(fw, fadr, offset);
 433     if ((offset & 0x00FFFFFF) == 1)
 434         fadr = followBranch(fw, fadr, offset);
 435     return fadr;
 436 }
 437 
 438 //------------------------------------------------------------------------------------------------------------
 439 
 440 // These functions test the instruction at the supplied 'offset' index to see if they match specific types
 441 
 442 // LDR Rx, =...
 443 int isLDR_PC(firmware *fw, int offset)
 444 {
 445     return ((fwval(fw,offset) & 0xFE1F0000) == 0xE41F0000);
 446 }
 447 
 448 // LDRnn Rx, =...
 449 int isLDR_PC_cond(firmware *fw, int offset)
 450 {
 451     return ((fwval(fw,offset) & 0x0E1F0000) == 0x041F0000);
 452 }
 453 
 454 // LDR Rx,[SP,...]
 455 int isLDR_SP(firmware *fw, int offset)
 456 {
 457     return ((fwval(fw,offset) & 0xFFFF0000) == 0xE59D0000);
 458 }
 459 
 460 // LDR
 461 int isLDR(firmware *fw, int offset)
 462 {
 463     return ((fwval(fw,offset) & 0xFE100000) == 0xE4100000);
 464 }
 465 
 466 // LDRnn
 467 int isLDR_cond(firmware *fw, int offset)
 468 {
 469     return ((fwval(fw,offset) & 0x0E100000) == 0x04100000);
 470 }
 471 
 472 // ADR Rx, value
 473 int isADR_PC(firmware *fw, int offset)
 474 {
 475     return ((fwval(fw,offset) & 0xFE0F0000) == 0xE20F0000);
 476 }
 477 
 478 // ADRnn Rx, value
 479 int isADR_PC_cond(firmware *fw, int offset)
 480 {
 481     return ((fwval(fw,offset) & 0x0E0F0000) == 0x020F0000);
 482 }
 483 
 484 // ADR or MOV
 485 int isADR(firmware *fw, int offset)
 486 {
 487     return ((fwval(fw,offset) & 0xFE000000) == 0xE2000000);
 488 }
 489 
 490 // LDMFD
 491 int isLDMFD(firmware *fw, int offset)
 492 {
 493     return ((fwval(fw,offset) & 0xFFFF0000) == 0xE8BD0000);
 494 }
 495 
 496 // LDMFD SP!, {..., PC}
 497 int isLDMFD_PC(firmware *fw, int offset)
 498 {
 499     return ((fwval(fw,offset) & 0xFFFF8000) == 0xE8BD8000);
 500 }
 501 
 502 // STMFD SP!,
 503 int isSTMFD(firmware *fw, int offset)
 504 {
 505     return ((fwval(fw,offset) & 0xFFFF0000) == 0xE92D0000);
 506 }
 507 
 508 // STMFD SP!, {..,LR}
 509 int isSTMFD_LR(firmware *fw, int offset)
 510 {
 511     return ((fwval(fw,offset) & 0xFFFF4000) == 0xE92D4000);
 512 }
 513 
 514 // STR
 515 int isSTR(firmware *fw, int offset)
 516 {
 517     return ((fwval(fw,offset) & 0xFE100000) == 0xE4000000);
 518 }
 519 
 520 // STRnn
 521 int isSTR_cond(firmware *fw, int offset)
 522 {
 523     return ((fwval(fw,offset) & 0x0E100000) == 0x04000000);
 524 }
 525 
 526 // BX
 527 int isBX(firmware *fw, int offset)
 528 {
 529     return ((fwval(fw,offset) & 0xFFFFFFF0) == 0xE12FFF10);
 530 }
 531 
 532 // BX
 533 int isBX_cond(firmware *fw, int offset)
 534 {
 535     return ((fwval(fw,offset) & 0x0FFFFFF0) == 0x012FFF10);
 536 }
 537 
 538 // BX LR
 539 int isBX_LR(firmware *fw, int offset)
 540 {
 541     return (fwval(fw,offset) == 0xE12FFF1E);
 542 }
 543 
 544 // BLX
 545 int isBLX(firmware *fw, int offset)
 546 {
 547     return ((fwval(fw,offset) & 0xFFFFFFF0) == 0xE12FFF30);
 548 }
 549 
 550 // BL
 551 int isBL(firmware *fw, int offset)
 552 {
 553     return ((fwval(fw,offset) & 0xFF000000) == 0xEB000000);
 554 }
 555 
 556 // BLxx
 557 int isBL_cond(firmware *fw, int offset)
 558 {
 559     return ((fwval(fw,offset) & 0x0F000000) == 0x0B000000);
 560 }
 561 
 562 // BLEQ
 563 int isBLEQ(firmware *fw, int offset)
 564 {
 565     return ((fwval(fw,offset) & 0xFF000000) == 0x0B000000);
 566 }
 567 
 568 // B
 569 int isB(firmware *fw, int offset)
 570 {
 571     return ((fwval(fw,offset) & 0xFF000000) == 0xEA000000);
 572 }
 573 
 574 // B or BL
 575 int isBorBL(firmware *fw, int offset)
 576 {
 577     return ((fwval(fw,offset) & 0xFE000000) == 0xEA000000);
 578 }
 579 
 580 // CMP
 581 int isCMP(firmware *fw, int offset)
 582 {
 583     return ((fwval(fw,offset) & 0xFFF00000) == 0xE3500000);
 584 }
 585 
 586 // MOV
 587 int isMOV(firmware *fw, int offset)
 588 {
 589     return ((fwval(fw,offset) & 0xFFF00000) == 0xE1A00000);
 590 }
 591 
 592 // MOV Rd, #
 593 int isMOV_immed(firmware *fw, int offset)
 594 {
 595     return ((fwval(fw,offset) & 0xFFF00000) == 0xE3A00000);
 596 }
 597 
 598 // ORR Rd, Rn, #
 599 int isORR(firmware *fw, int offset)
 600 {
 601     return ((fwval(fw,offset) & 0xFFF00000) == 0xE3800000);
 602 }
 603 
 604 // ADD
 605 int isADD(firmware *fw, int offset)
 606 {
 607     return ((fwval(fw,offset) & 0xfff00000) == 0xe2800000);
 608 }
 609 
 610 // SUB
 611 int isSUB(firmware *fw, int offset)
 612 {
 613     return ((fwval(fw,offset) & 0xfff00000) == 0xe2400000);
 614 }
 615 
 616 //------------------------------------------------------------------------------------------------------------
 617 
 618 int isASCIIstring(firmware *fw, uint32_t adr)
 619 {
 620     if (idx_valid(fw, adr2idx(fw, adr)))
 621     {
 622         unsigned char *p = (unsigned char*)adr2ptr(fw, adr);
 623         int i;
 624         for (i = 0; (i < 100) && (p[i] != 0); i++)
 625         {
 626             if (!((p[i] == '\r') || (p[i] == '\n') || (p[i] == '\t') || ((p[i] >= 0x20) && (p[i] <= 0x7f))))
 627             {
 628                 return 0;
 629             }
 630         }
 631         if ((i >= 2) && (p[i] == 0))
 632             return 1;
 633     }
 634     return 0;
 635 }
 636 //------------------------------------------------------------------------------------------------------------
 637 
 638 // Find the index of a string in the firmware
 639 // Assumes the string starts on a 32bit boundary.
 640 // String + terminating zero byte should be at least 4 bytes long
 641 // Handles multiple string instances
 642 int find_Nth_str(firmware *fw, char *str, int N)
 643 {
 644     int nlen = strlen(str);
 645     uint32_t nm0 = *((uint32_t*)str);
 646     uint32_t *p;
 647     int j;
 648 
 649     BufRange *br = fw->br;
 650     while (br)
 651     {
 652         for (p = br->p, j = 0; j < br->len - nlen/4; j++, p++)
 653         {
 654             if ((nm0 == *p) && ((nlen<=4) || (memcmp(p+1,str+4,nlen-4) == 0)) )
 655             {
 656                 if (--N == 0)
 657                     return j+br->off;
 658             }
 659         }
 660         br = br->next;
 661     }
 662 
 663     return -1;
 664 }
 665 
 666 int find_str(firmware *fw, char *str)
 667 {
 668     return find_Nth_str(fw, str, 1);
 669 }
 670 
 671 // Find the index of a string in the firmware, can start at any address
 672 // returns firmware address, not index
 673 uint32_t find_str_bytes(firmware *fw, char *str)
 674 {
 675     BufRange *p = fw->br;
 676     while (p)
 677     {
 678         int k;
 679         for (k = p->off*4; k < (p->off + p->len)*4; k++)
 680         {
 681             if (strcmp(((char*)fw->buf)+k,str) == 0)
 682                 return fw->base+k;
 683         }
 684         p = p->next;
 685     }
 686 
 687     return 0;
 688 }
 689 
 690 // Find the next instance of the instruction matched by the 'inst' function (from the isXXX functions above)
 691 // Starts searching at 'idx' for a max of 'len' instructions
 692 int find_inst(firmware *fw, int (*inst)(firmware*,int), int idx, int len)
 693 {
 694     int k;
 695     for (k = idx; (k < fw->size) && (k < idx + len); k++)
 696     {
 697         if (inst(fw, k))
 698             return k;
 699     }
 700     return -1;
 701 }
 702 
 703 // Find the previous instance of the instruction matched by the 'inst' function (from the isXXX functions above)
 704 // Starts searching at 'idx' for a max of 'len' instructions
 705 int find_inst_rev(firmware *fw, int (*inst)(firmware*,int), int idx, int len)
 706 {
 707     int k;
 708     for (k = idx; (k > 0) && (k > idx - len); k--)
 709     {
 710         if (inst(fw, k))
 711             return k;
 712     }
 713     return -1;
 714 }
 715 
 716 // Find the Nth instance of the instruction matched by the 'inst' function
 717 // Modified version of find_inst()
 718 int find_Nth_inst(firmware *fw, int (*inst)(firmware*,int), int idx, int len, int N)
 719 {
 720     int k;
 721     for (k = idx; (k < fw->size) && (k < idx + len); k++)
 722     {
 723         if (inst(fw, k))
 724             N--;
 725         if (N <= 0)
 726             return k;
 727     }
 728     return -1;
 729 }
 730 
 731 // Find the Nth previous instance of the instruction matched by the 'inst' function
 732 // Modified version of find_inst_rev()
 733 int find_Nth_inst_rev(firmware *fw, int (*inst)(firmware*,int), int idx, int len, int N)
 734 {
 735     int k;
 736     for (k = idx; (k > 0) && (k > idx - len); k--)
 737     {
 738         if (inst(fw, k))
 739             N--;
 740         if (N <= 0)
 741             return k;
 742     }
 743     return -1;
 744 }
 745 
 746 //------------------------------------------------------------------------------------------------------------
 747 
 748 // Finds the first instance of an instruction that references a pointer to the specified string in the firmware.
 749 //  e.g.
 750 //          LDR R0, =p_str  <-- returns index of this instruction
 751 //  p_str   DCD abcdef
 752 //  abcdef  DCB "abcdef",0
 753 int find_strptr_ref(firmware *fw, char *str)
 754 {
 755     uint32_t sadr = find_str_bytes(fw, str);    // string address
 756     if (sadr > 0)
 757     {
 758         int k;
 759         for (k=0; k<fw->size; k++)
 760         {
 761             if (fwval(fw,k) == sadr)
 762             {
 763                 uint32_t fadr = idx2adr(fw,k);  // string pointer address
 764                 int j;
 765                 for (j=0; j<fw->size; j++)
 766                 {
 767                     if (isADR_PC_cond(fw,j) && (ADR2adr(fw,j) == fadr))
 768                     {
 769                         return j;
 770                     }
 771                     else if (isLDR_PC_cond(fw,j) && (LDR2val(fw,j) == fadr))
 772                     {
 773                         return j;
 774                     }
 775                 }
 776             }
 777         }
 778     }
 779     return -1;
 780 }
 781 
 782 // Finds the first instance of an instruction that references the specified string in the firmware.
 783 //  e.g.
 784 //          LDR R0, =abcdef     <-- returns index of this instruction
 785 //  abcdef  DCB "abcdef",0
 786 int find_str_ref(firmware *fw, char *str)
 787 {
 788     int k = find_str(fw, str);
 789     if (k >= fw->lowest_idx)
 790     {
 791         uint32_t sadr = idx2adr(fw,k);        // string address
 792         for (k=0; k<fw->size; k++)
 793         {
 794             if (isADR_PC_cond(fw,k) && (ADR2adr(fw,k) == sadr))
 795             {
 796                 return k;
 797             }
 798             else if (isLDR_PC_cond(fw,k) && (LDR2val(fw,k) == sadr))
 799             {
 800                 return k;
 801             }
 802         }
 803     }
 804     return -1;
 805 }
 806 
 807 // Finds the next reference to a string
 808 int find_nxt_str_ref(firmware *fw, int str_adr, int ofst)
 809 {
 810     if (str_adr >= fw->lowest_idx)
 811     {
 812         int k;
 813         uint32_t sadr = idx2adr(fw,str_adr);        // string address
 814         for (k=ofst+1; k<fw->size; k++)
 815         {
 816             if (isADR_PC_cond(fw,k) && (ADR2adr(fw,k) == sadr))
 817             {
 818                 return k;
 819             }
 820             else if (isLDR_PC_cond(fw,k) && (LDR2val(fw,k) == sadr))
 821             {
 822                 return k;
 823             }
 824         }
 825     }
 826     return -1;
 827 }
 828 
 829 //------------------------------------------------------------------------------------------------------------
 830 
 831 // Checks if the instruction at index 'k' is a BL to address 'v1'
 832 // Used with the 'search_fw' below
 833 int find_BL(firmware *fw, int k, uint32_t v1, uint32_t v2)
 834 {
 835     if (isBL(fw,k))
 836     {
 837         int n = idxFollowBranch(fw, k, 0x01000001);
 838         if (n == v1)
 839             return k;
 840     }
 841     return 0;
 842 }
 843 
 844 // Checks if the instruction at index 'k' is a BL to address 'v1'
 845 // Used with the 'search_fw' below
 846 int find_B(firmware *fw, int k, uint32_t v1, uint32_t v2)
 847 {
 848     if (isB(fw,k))
 849     {
 850         int n = idxFollowBranch(fw, k, 0x00000001);
 851         if (n == v1)
 852             return k;
 853     }
 854     return 0;
 855 }
 856 
 857 //------------------------------------------------------------------------------------------------------------
 858 
 859 // Search the firmware for something. The desired matching is performed using the supplied 'func' function.
 860 // Continues searching until 'func' returns non-zero - then returns the value returned by 'func'
 861 // otherwise returns 0.
 862 // Uses the BufRange structs to speed up searching
 863 int search_fw(firmware *fw, int (*func)(firmware*, int, uint32_t, uint32_t), uint32_t v1, uint32_t v2, int len)
 864 {
 865     BufRange *p = fw->br;
 866     while (p)
 867     {
 868         int k;
 869         for (k = p->off; k <= p->off + p->len - len; k++)
 870         {
 871             int rv = func(fw,k,v1,v2);
 872             if (rv != 0)
 873                 return rv;
 874         }
 875         p = p->next;
 876     }
 877     return 0;
 878 }
 879 
 880 // Search the firmware for something. The desired matching is performed using the supplied 'func' function.
 881 // Continues searching until 'func' returns non-zero - then returns 1
 882 // otherwise returns 0.
 883 // Uses the BufRange structs to speed up searching
 884 // Note: this version searches byte by byte in the firmware dump instead of by words
 885 int search_fw_bytes(firmware *fw, int (*func)(firmware*, int))
 886 {
 887     BufRange *p = fw->br;
 888     while (p)
 889     {
 890         int k;
 891         for (k = p->off*4; k < (p->off + p->len)*4; k++)
 892         {
 893             if (func(fw,k))
 894                 return 1;
 895         }
 896         p = p->next;
 897     }
 898     return 0;
 899 }
 900 
 901 //------------------------------------------------------------------------------------------------------------
 902 
 903 // Load the named firmware file, using the supplied base and alternate base addresses
 904 // Once loaded searches the firmware for information
 905 void load_firmware(firmware *fw, const char *filename, const char *base_addr, const char *alt_base_addr, int os_type)
 906 {
 907     // Open file.
 908     FILE *f = fopen(filename, "rb");
 909     int i, j, k;
 910 
 911     if (f == NULL)
 912     {
 913         fprintf(stderr,"Error opening %s\n",filename);
 914         usage("firmware open");
 915     }
 916 
 917     // these are used regardless of camera generation, have to be initialized here
 918     fw->buf2 = 0;
 919     fw->base2 = 0;
 920     fw->size2 = 0;
 921 
 922     fw->os_type = os_type;
 923 
 924     // File length
 925     fseek(f,0,SEEK_END);
 926     fw->size = (ftell(f)+3)/4;
 927     fseek(f,0,SEEK_SET);
 928 
 929     // Save base addresses
 930     fw->base = strtoul(base_addr, NULL, 0);
 931     if (alt_base_addr)
 932         fw->alt_base = strtoul(alt_base_addr, NULL, 0);
 933     else
 934         fw->alt_base = 0;
 935 
 936     // Max (old) sig size is 32, add extra space at end of buffer and fill with 0xFFFFFFFF
 937     // Allows sig matching past end of firmware without checking each time in the inner loop
 938     fw->buf = malloc((fw->size+32)*4);
 939     k = fread(fw->buf, 4, fw->size, f);
 940     fclose(f);
 941 
 942     // fill extra space in buffer
 943     memset(&fw->buf[fw->size],0xff,32*4);
 944 
 945     // Find all the valid ranges for checking (skips over large blocks of 0xFFFFFFFF)
 946     findRanges(fw);
 947 
 948     // Check for DIGIC 4+ dump
 949     // assumes dump starting with either the main firmware or the bootloader
 950     fw->main_offs = 0;
 951     if (os_type == OS_DRYOS)
 952     {
 953         k = find_str(fw, "gaonisoy");
 954         if (k != 1)
 955         {
 956             fw->main_offs = 0x10000 / 4;
 957         }
 958     }
 959     // Get DRYOS version
 960     fw->real_dryos_ver = fw->dryos_ver = 0;
 961     if (os_type == OS_DRYOS)
 962     {
 963         k = find_str(fw, "DRYOS version 2.3, release #");
 964         if (k != -1)
 965         {
 966             fw->real_dryos_ver = fw->dryos_ver = atoi(((char*)&fw->buf[k])+28);
 967             fw->dryos_ver_str = (char*)&fw->buf[k];
 968         }
 969     }
 970 
 971     // Get firmware version info
 972     fw->firmware_ver_str = 0;
 973     k = find_str(fw, "Firmware Ver ");
 974     if (os_type == OS_VXWORKS)
 975     {
 976         if (k < 0)
 977         {
 978             k = find_str(fw, "Firmware Version GM");    // ixus700
 979         }
 980         if (k < 0)
 981         {
 982             k = find_str(fw, "Firmware Version ");      // ixus30/40
 983         }
 984     }
 985     if (k != -1)
 986     {
 987         fw->firmware_ver_str = (char*)&fw->buf[k];
 988         fw->fwver_idx = k;
 989     }
 990 
 991     // Get camera name & platformid     ***** UPDATE for new each new DryOS version *****
 992     fw->fsize = -((int)fw->base)/4;
 993     if (fw->alt_base) fw->fsize = -((int)fw->alt_base)/4;
 994     fw->cam_idx = -1;
 995     fw->pid_adr = 0xffffffff;
 996     fw->cam = 0;
 997     fw->pid = 0;
 998     if (os_type == OS_DRYOS)
 999     {
1000         if (fw->dryos_ver > 59) fw->dryos_ver = 59; // UPDATE when support is added for higher DryOS versions
1001         switch (fw->dryos_ver)
1002         {
1003             case 20:
1004             case 23:
1005             case 31:
1006             case 39:
1007                 fw->cam_idx = adr2idx(fw,0xFFFE0110);
1008                 fw->pid_adr = 0xFFFE0130;
1009                 break;
1010             case 43:
1011             case 45:
1012                 fw->cam_idx = adr2idx(fw,0xFFFE00D0);
1013                 fw->pid_adr = 0xFFFE0130;
1014                 break;
1015             case 47:
1016                 fw->cam_idx = adr2idx(fw,(fw->base==0xFF000000)?0xFFF40170:0xFFFE0170);
1017                 fw->pid_adr = (fw->base==0xFF000000)?0xFFF40040:0xFFFE0040;
1018                 break;
1019             case 49:
1020             case 50:
1021             case 51:
1022             case 52:
1023                 if (fw->alt_base)
1024                 {
1025                     fw->cam_idx = adr2idx(fw,(fw->alt_base==0xFF000000)?0xFFF40190:0xFFFE0170);
1026                     fw->pid_adr = (fw->alt_base==0xFF000000)?0xFFF40040:0xFFFE0040;
1027                     if (idx_valid(fw,fw->cam_idx) && (strncmp((char*)fwadr(fw,fw->cam_idx),"Canon ",6) != 0))
1028                         fw->cam_idx = adr2idx(fw,(fw->alt_base==0xFF000000)?0xFFF40170:0xFFFE0170);
1029                 }
1030                 else
1031                 {
1032                     fw->cam_idx = adr2idx(fw,(fw->base==0xFF000000)?0xFFF40190:0xFFFE0170);
1033                     fw->pid_adr = (fw->base==0xFF000000)?0xFFF40040:0xFFFE0040;
1034                     if (idx_valid(fw,fw->cam_idx) && (strncmp((char*)fwadr(fw,fw->cam_idx),"Canon ",6) != 0))
1035                         fw->cam_idx = adr2idx(fw,(fw->base==0xFF000000)?0xFFF40170:0xFFFE0170);
1036                 }
1037                 break;
1038             case 54:
1039                 fw->cam_idx = adr2idx(fw,(fw->base==0xFF010000)?0xFFF40170:0xFFFF0170);
1040                 fw->pid_adr = (fw->base==0xFF010000)?0xFFF40040:0xFFFF0040;
1041                 break;
1042             case 55:
1043             case 57: // TODO: based on a single fw dump (ixus275)
1044                 fw->cam_idx = adr2idx(fw,(fw->base==0xFF010000)?0xFFFE0170:0xFFFF0170);
1045                 fw->pid_adr = (fw->base==0xFF010000)?0xFFFE0040:0xFFFF0040;
1046                 break;
1047             case 58:
1048             case 59:
1049                 fw->cam_idx = adr2idx(fw,(fw->base==0xFF010000)?0xFFFE03A0:0xFFFF03A0);
1050                 fw->pid_adr = (fw->base==0xFF010000)?0xFFFE0270:0xFFFF0270;
1051                 break;
1052         }
1053     }
1054     else
1055     {
1056         //                             IXUS 700    IXUS 30/40  IXUS 50     Other
1057         uint32_t vx_name_offsets[] = { 0xFFD70110, 0xFFD70120, 0xFFF80110, 0xFFFE0110 };
1058         uint32_t vx_pid_offsets[] =  { 0xFFD70130, 0xFFD7014E, 0xFFF80130, 0xFFFE0130 };
1059         for (i=0; i<sizeof(vx_name_offsets)/sizeof(vx_name_offsets[0]); i++)
1060         {
1061             int k = adr2idx(fw,vx_name_offsets[i]);
1062             if (idx_valid(fw,k) && (strncmp((char*)fwadr(fw,k),"Canon ",6) == 0))
1063             {
1064                 fw->cam_idx = k;
1065                 fw->pid_adr = vx_pid_offsets[i];
1066                 break;
1067             }
1068         }
1069     }
1070 
1071     // Extact camera name if found
1072     if (idx_valid(fw,fw->cam_idx) && (strncmp((char*)fwadr(fw,fw->cam_idx),"Canon ",6) == 0))
1073     {
1074         fw->cam = (char*)fwadr(fw,fw->cam_idx);
1075     }
1076 
1077     // Set ID if found
1078     if (idx_valid(fw,adr2idx(fw,fw->pid_adr)) && (fw->pid_adr != 0xffffffff))
1079     {
1080         // get the correct halfword
1081         fw->pid = (fwval(fw,adr2idx(fw,fw->pid_adr)) >> ((fw->pid_adr & 2)?16:0)) & 0xFFFF;
1082     }
1083 
1084     // Calc MAXRAMADDR
1085     fw->maxram = 0;
1086     if (os_type == OS_DRYOS)
1087     {
1088         if (((fw->buf[0x10 + fw->main_offs] & 0xFFFFFF00) == 0xE3A00000) && (fw->buf[0x11 + fw->main_offs] == 0xEE060F12))
1089         {
1090             fw->maxram = (1 << (((fw->buf[0x10 + fw->main_offs] & 0x3E) >> 1) + 1)) - 1;
1091         }
1092         else if (((fw->buf[0x14 + fw->main_offs] & 0xFFFFFF00) == 0xE3A00000) && (fw->buf[0x15 + fw->main_offs] == 0xEE060F12))
1093         {
1094             fw->maxram = (1 << (((fw->buf[0x14 + fw->main_offs] & 0x3E) >> 1) + 1)) - 1;
1095         }
1096     }
1097     else if (os_type == OS_VXWORKS)
1098     {
1099         for (k=16; k<100; k++)
1100         {
1101             if ((fw->buf[k] & 0xFFFF0FFF) == 0xEE060F12) // mcr 15, 0, rx, cr6, cr2, {0}
1102             {
1103                 fw->maxram = (1 << (((fw->buf[k-1] & 0x3E) >> 1) + 1)) - 1;
1104                 break;
1105             }
1106         }
1107     }
1108 
1109     // Find MEMISOSTART
1110     fw->memisostart = 0;
1111     if (os_type == OS_DRYOS)
1112     {
1113         for (k=0 + fw->main_offs; k<(100 + fw->main_offs); k++)
1114         {
1115             if (isLDR_PC(fw,k) && (LDR2val(fw,k) == 0x1900) && isLDR_PC(fw,k+6))
1116             {
1117                 fw->memisostart = LDR2val(fw,k+6);
1118             }
1119         }
1120     }
1121     else if (os_type == OS_VXWORKS)
1122     {
1123         for (k=16; k<100; k++)
1124         {
1125             if (isMOV_immed(fw,k) && (ALUop2(fw,k) == 0x1900) && isLDR_PC(fw,k+11))
1126             {
1127                 fw->memisostart = LDR2val(fw,k+11);
1128                 // Find DATA section info
1129                 if (isLDR_PC(fw,k-1) && isLDR_PC(fw,k-4) && ((fwval(fw,k-2) & 0xFFF0FFF0) == 0xE1500000))
1130                 {
1131                     uint32_t fadr = LDR2val(fw,k-1);
1132                     uint32_t dadr = 0x1900;
1133                     uint32_t eadr = LDR2val(fw,k-4);
1134                     if ((fadr > fw->base) && (dadr < fw->base))
1135                     {
1136                         fw->data_start = dadr;
1137                         fw->data_init_start = fadr;
1138                         fw->data_len = eadr / 4;
1139                     }
1140                 }
1141                 break;
1142             }
1143             else if (isMOV_immed(fw,k) && (ALUop2(fw,k) == 0x1900) && isLDR_PC(fw,k-2) && isLDR_PC(fw,k-3))
1144             {
1145                 // special case ixus30/40
1146                 fw->maxram = 0x1FFFFFF; // 32MB, difficult to find
1147                 fw->memisostart = 0x1900 + LDR2val(fw,k-3);
1148                 // Find DATA section info
1149                 fw->data_init_start = LDR2val(fw,k-2);
1150                 fw->data_start = 0x1900;
1151                 j = idxFollowBranch(fw, k+6, 1);
1152                 if (j != k+6)
1153                 {
1154                     k = idxFollowBranch(fw, j+1, 0x01000001);
1155                     if (k != j+1)
1156                     {
1157                         if ( isLDR_PC(fw,k+3) )
1158                         {
1159                             uint32_t eadr = LDR2val(fw,k+3);
1160                             if ( (eadr>0x1000) && (eadr< fw->memisostart - 0x1900) )
1161                             {
1162                                 fw->data_len = (eadr - 0x1900) / 4;
1163                             }
1164                         }
1165                     }
1166                 }
1167                 break;
1168             }
1169             else if (isMOV_immed(fw,k) && (ALUop2(fw,k) == 0x1900) && isLDR_PC(fw,k-2) &&
1170                         ((fwval(fw,k-1) & 0xFFFF0F00) == 0xE50B0000) && isLDR_PC(fw,k+28) && isLDR_PC(fw,k+4)
1171                     )
1172             {
1173                 // special case ixusW
1174                 fw->memisostart = LDR2val(fw,k+28);
1175                 // Find DATA section info
1176                 fw->data_init_start = LDR2val(fw,k-2);
1177                 fw->data_start = 0x1900;
1178                 fw->data_len = (LDR2val(fw,k+4) - 0x1900) / 4;
1179                 break;
1180             }
1181         }
1182     }
1183 
1184     // Find encryption key & dancing bits
1185     fw->ksys_idx = 0;
1186     fw->ksys = 0;
1187     fw->dancing_bits_idx = 0;
1188     fw->dancing_bits = 0;
1189     if (os_type == OS_DRYOS)
1190     {
1191         uint32_t ofst = (fw->main_offs)?0:adr2idx(fw,0xFFFF0000); // Offset of area to find dancing bits
1192         if (idx_valid(fw,ofst) && isB(fw,ofst) && isLDR_PC(fw,ofst+1))
1193         {
1194             // Get KEYSYS value
1195             ofst = adr2idx(fw,LDR2val(fw,ofst+1));     // Address of firmware encryption key
1196             if (idx_valid(fw,ofst))
1197             {
1198                 fw->ksys_idx = ofst;
1199                 fw->ksys = "? Not found, possible new firmware encryption key.";
1200                 switch (fwval(fw,ofst))
1201                 {
1202                     // Note: only check first word of key (assumes Canon won't release a new key with the same initial value as an existing one)
1203                     // (Avoid storing full encryption key in this source code).
1204                     case 0x70726964:    fw->ksys = "d3   "; break;
1205                     case 0x646C726F:    fw->ksys = "d3enc"; break;
1206                     case 0x774D450B:    fw->ksys = "d4   "; break;
1207                     case 0x80751A95:    fw->ksys = "d4a  "; break;
1208                     case 0x76894368:    fw->ksys = "d4b  "; break;
1209                     case 0x50838EF7:    fw->ksys = "d4c  "; break;
1210                     case 0xCCE4D2E6:    fw->ksys = "d4d  "; break;
1211                     case 0x66E0C6D2:    fw->ksys = "d4e  "; break;
1212                     case 0xE1268DB4:    fw->ksys = "d4f  "; break;
1213                     case 0x216EA8C8:    fw->ksys = "d4g  "; break;
1214                     case 0x45264974:    fw->ksys = "d4h  "; break;
1215                                         case 0x666363FC:    fw->ksys = "d4i  "; break;
1216                                         case 0xAE8DB5AF:    fw->ksys = "d4j  "; break;
1217                 }
1218             }
1219 
1220             // Get NEED_ENCODED_DISKBOOT value
1221             ofst = ofst + 4; // Address of dancing bits data (try after firmware key)
1222             if (idx_valid(fw,ofst))
1223             {
1224                 for (i=0; i<VITALY && !fw->dancing_bits; i++)
1225                 {
1226                     fw->dancing_bits = i+1;
1227                     for (j=0; j<8 && fw->dancing_bits; j++)
1228                     {
1229                         if ((fwval(fw,ofst+j) & 0xFF) != _chr_[i][j])
1230                         {
1231                             fw->dancing_bits = 0;
1232                         }
1233                     }
1234                 }
1235                 if (!fw->dancing_bits)
1236                 {
1237                     // Try before firmware key
1238                     ofst = ofst - 12;
1239                     for (i=0; i<VITALY && !fw->dancing_bits; i++)
1240                     {
1241                         fw->dancing_bits = i+1;
1242                         for (j=0; j<8 && fw->dancing_bits; j++)
1243                         {
1244                             if ((fwval(fw,ofst+j) & 0xFF) != _chr_[i][j])
1245                             {
1246                                 fw->dancing_bits = 0;
1247                             }
1248                         }
1249                     }
1250                 }
1251                 if (fw->dancing_bits != 0)
1252                 {
1253                     // Make sure LoadBootFile actually fails on files that are not encoded
1254                     // E.G. G9 - will load and run an un-encoded DISKBOOT.BIN file
1255                     int need_dance = 1;
1256                     for (k = ofst; (k>adr2idx(fw,0xFFFF0000)) && need_dance; k--)
1257                     {
1258                         if (isLDR_PC(fw,k) && (LDR2val(fw,k) == idx2adr(fw,ofst)))
1259                         {
1260                             j = find_inst_rev(fw,isSTMFD_LR,k-1,10);
1261                             if (j >= 0)
1262                             {
1263                                 uint32_t fadr = idx2adr(fw,j);
1264                                 for (i=j-200; i<j+200 && need_dance; i++)
1265                                 {
1266                                     if (isB(fw,i))
1267                                     {
1268                                         uint32_t badr = followBranch(fw,idx2adr(fw,i),1);
1269                                         if (badr == fadr)
1270                                         {
1271                                             int l;
1272                                             for (l=i-1; l>i-50; l--)
1273                                             {
1274                                                 if (isLDR(fw,l) && isCMP(fw,l+1) && isBX_cond(fw,l+2))
1275                                                 {
1276                                                     need_dance = 0;
1277                                                     break;
1278                                                 }
1279                                             }
1280                                         }
1281                                     }
1282                                 }
1283                             }
1284                         }
1285                     }
1286                     if (need_dance)
1287                         fw->dancing_bits_idx = ofst;
1288                     else
1289                         fw->dancing_bits = 0;
1290                 }
1291             }
1292         }
1293     }
1294 
1295     int dx = 3;
1296 
1297     fw->lowest_idx = 0;
1298 
1299     // DryOS R50/R51/R52 etc. copies a block of ROM to RAM and then uses that copy
1300     // Need to allow for this in finding addresses
1301     // Seen on SX260HS
1302     if (fw->dryos_ver >= 50)
1303     {
1304 
1305         // Try and find ROM address copied, and location copied to
1306         for (i=3 + fw->main_offs; i<(100 + fw->main_offs); i++)
1307         {
1308             if (isLDR_PC(fw,i) && isLDR_PC(fw,i+1) && (isLDR_PC(fw,i+2)))
1309             {
1310                 uint32_t fadr = LDR2val(fw,i);
1311                 uint32_t dadr = LDR2val(fw,i+1);
1312                 uint32_t eadr = LDR2val(fw,i+2);
1313                 if ((fadr > fw->base) && (dadr < fw->base))
1314                 {
1315                     fw->buf2 = &fw->buf[adr2idx(fw,fadr)];
1316                     fw->base2 = dadr;
1317                     fw->base_copied = fadr;
1318                     fw->size2 = (eadr - dadr) / 4;
1319                     fw->lowest_idx = adr2idx(fw,fw->base2);
1320                     dx = i+3;
1321                     break;
1322                 }
1323             }
1324         }
1325     }
1326 
1327     // Find DATA section info
1328     if (os_type == OS_DRYOS)
1329     {
1330         for (i=dx; i<(100 + fw->main_offs); i++)
1331         {
1332             if (isLDR_PC(fw,i) && isLDR_PC(fw,i+1) && (isLDR_PC(fw,i+2)))
1333             {
1334                 uint32_t fadr = LDR2val(fw,i);
1335                 uint32_t dadr = LDR2val(fw,i+1);
1336                 uint32_t eadr = LDR2val(fw,i+2);
1337                 if ((fadr > fw->base) && (dadr < fw->base))
1338                 {
1339                     fw->data_start = dadr;
1340                     fw->data_init_start = fadr;
1341                     fw->data_len = (eadr - dadr) / 4;
1342                     break;
1343                 }
1344             }
1345         }
1346     }
1347 }
1348 
1349 //------------------------------------------------------------------------------------------------------------

/* [<][>][^][v][top][bottom][index][help] */