root/tools/finsig_vxworks.c

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

DEFINITIONS

This source file includes following definitions.
  1. bprintf
  2. add_blankline
  3. write_output
  4. usage
  5. error
  6. match_compare
  7. addMatch
  8. fwAddMatch
  9. find_saved_sig
  10. save_sig
  11. get_saved_sig
  12. search_saved_sig
  13. match_apex2us
  14. find_apex2us
  15. find_mkdir
  16. find_pow
  17. find_log
  18. find_log10
  19. find_get_ptp_file_buf
  20. find_closedir
  21. find_add_ptp_handler
  22. find_PT_PlaySound
  23. find_ExportToEventProcedure
  24. find_RegisterEventProcedure
  25. find_set_control_event
  26. find_filesem_init
  27. find_getcurrentmachinetime
  28. find_get_nd_value
  29. find_get_current_nd_value_iris
  30. find_get_current_nd_value
  31. find_get_current_deltasv
  32. find_exmem_ufree
  33. find_exmem_ualloc
  34. find_exmem_free
  35. find_exmem_alloc
  36. find_get_ptp_buf_size
  37. find_GetBaseSv
  38. find_GetCurrentDriveBaseSvValue
  39. find_Remove
  40. find_func
  41. vxworks_offset
  42. fw_string_process
  43. fw_string_process_unaligned
  44. fw_process
  45. match_strsig1
  46. match_strsig2a
  47. match_strsig2
  48. match_strsig3a
  49. match_strsig3
  50. match_strsig4a
  51. match_strsig4
  52. match_strsig5a
  53. match_strsig5
  54. match_strsig6
  55. match_strsig7a
  56. match_strsig7
  57. match_strsig8
  58. find_strsig8
  59. find_strsig9
  60. match_strsig11
  61. match_strsig13a
  62. match_strsig13
  63. match_strsig15a
  64. match_strsig15
  65. match_strsig16
  66. find_strsig17
  67. find_strsig19
  68. match_strsig23a
  69. match_strsig23
  70. match_strsig100
  71. match_strsig101
  72. match_strsig102
  73. match_strsig103
  74. match_strsig104
  75. find_strsig
  76. find_str_sig_matches
  77. find_matches
  78. print_results
  79. mode_name
  80. output_modemap
  81. find_modelist
  82. match_FlashParamsTable2
  83. match_FlashParamsTable
  84. find_modemap
  85. find_FileAccessSem
  86. find_DebugAssert_argcount
  87. find_platform_vals
  88. find_viewport_address
  89. match_vid_get_bitmap_fb
  90. match_get_flash_params_count
  91. match_uiprop_count
  92. isMOVLRPC
  93. match_imager_active
  94. find_lib_vals
  95. print_stubs_min
  96. print_exmem_types
  97. find_exmem_alloc_table
  98. match_levent_table
  99. match_movie_status
  100. match_full_screen_refresh
  101. match_canon_shoot_menu_active
  102. match_playrec_mode
  103. match_some_flag_for_af_scan
  104. match_palette_data
  105. match_palette_buffer_offset
  106. match_palette_data3
  107. match_palette_data2
  108. match_SavePaletteData
  109. match_viewport_address3
  110. match_viewport_address2
  111. match_viewport_address
  112. match_physw_status
  113. match_physw_run
  114. match_canon_menu_active
  115. match_zoom_busy
  116. match_focus_busy
  117. match_bitmap_buffer2
  118. match_bitmap_buffer
  119. match_raw_buffer
  120. match_cameracon_state
  121. find_DoMovieFrameCapture_buf
  122. find_stubs_min
  123. find_ctypes
  124. match_nrflag3
  125. match_nrflag
  126. match_nrflag2
  127. isADD_0x220000
  128. find_leds
  129. find_other_vals
  130. print_kval
  131. add_kinfo
  132. add_kmval
  133. kinfo_compare
  134. print_kmvals
  135. match_GetSDProtect
  136. find_key_vals
  137. get_eventproc_val
  138. add_func_name
  139. add_func_name2
  140. match_eventproc
  141. match_registerlists
  142. match_registerlistproc
  143. find_eventprocs
  144. isLDR_PC_r0
  145. isLDR_PC_r3
  146. match_createtask
  147. find_tasks
  148. find_builddate
  149. save_ptp_handler_func
  150. find_ptp_handler_imm
  151. match_ptp_handlers
  152. find_ptp_handlers
  153. write_levent_table_dump
  154. output_firmware_vals
  155. compare_func_names
  156. compare_func_addresses
  157. write_funcs
  158. main

   1 #include <stdlib.h>
   2 #include <stdio.h>
   3 #include <stdint.h>
   4 #include <string.h>
   5 #include <time.h>
   6 #include <stdarg.h>
   7 #include <ctype.h>
   8 
   9 #include "stubs_load.h"
  10 #include "firmware_load.h"
  11 #include "ptp_op_names.h"
  12 
  13 //------------------------------------------------------------------------------------------------------------
  14 // #define DEBUG_PRINT_ALL_FUNC_NAMES 1 // enable debug output on stderr for development
  15 // #define LIST_IMPORTANT_FUNCTIONS   1 // always list functions with 'LIST_ALWAYS' flag, even when not found
  16 // #define PRINT_LEVENT_TABLE 1         // print all levents to file
  17 //------------------------------------------------------------------------------------------------------------
  18 
  19 // Buffer output into header and body sections
  20 
  21 FILE    *out_fp;
  22 char    out_buf[32*1024] = "";
  23 int     out_len = 0;
  24 char    hdr_buf[32*1024] = "";
  25 int     hdr_len = 0;
  26 int     out_hdr = 1;
  27 
  28 void bprintf(char *fmt, ...)
  29 {
  30     va_list argp;
  31     va_start(argp, fmt);
  32 
  33     if (out_hdr)
  34         hdr_len += vsprintf(hdr_buf+hdr_len,fmt,argp);
  35     else
  36         out_len += vsprintf(out_buf+out_len,fmt,argp);
  37 
  38     va_end(argp);
  39 }
  40 
  41 void add_blankline()
  42 {
  43     if (strcmp(hdr_buf+hdr_len-2,"\n\n") != 0)
  44     {
  45         hdr_buf[hdr_len++] = '\n';
  46         hdr_buf[hdr_len] = 0;
  47     }
  48 }
  49 
  50 void write_output()
  51 {
  52     add_blankline();
  53     if (out_fp)
  54     {
  55         fprintf(out_fp,"%s",hdr_buf);
  56         fprintf(out_fp,"%s",out_buf);
  57     }
  58 }
  59 
  60 //------------------------------------------------------------------------------------------------------------
  61 
  62 void usage(char *err)
  63 {
  64     bprintf("finsig <primary> <base> <outputfilename> [alt base] - Error = %s\n",err);
  65     write_output();
  66     fprintf(stderr,"finsig <primary> <base> <outputfilename> [alt base] - Error = %s\n",err);
  67     exit(1);
  68 }
  69 
  70 void error(char *fmt, int n)
  71 {
  72     bprintf(fmt, n);
  73     write_output();
  74     exit(1);
  75 }
  76 
  77 //------------------------------------------------------------------------------------------------------------
  78 
  79 // Signature match handling
  80 
  81 // Structure to store match info
  82 typedef struct {
  83     uint32_t ptr;
  84     uint32_t fail;
  85     uint32_t success;
  86     int sig;
  87 } Match;
  88 
  89 // qsort compare function the Match struture
  90 int match_compare(const Match *p1, const Match *p2)
  91 {
  92     /* NOTE: If a function has *more* matches, it will be prefered, even if it has a lower percent matches */
  93     if (p1->success > p2->success)
  94     {
  95         if ((p2->fail == 0) && (p1->fail > 0))
  96         {
  97             return 1;
  98         }
  99         else
 100         {
 101             return -1;
 102         }
 103     }
 104     else if (p1->success < p2->success)
 105     {
 106         if ((p1->fail == 0) && (p2->fail > 0))
 107         {
 108             return -1;
 109         }
 110         else
 111         {
 112             return 1;
 113         }
 114     }
 115     else
 116     {
 117         if (p1->fail < p2->fail)
 118         {
 119             return -1;
 120         }
 121         else if (p1->fail > p2->fail)
 122         {
 123             return 1;
 124         }
 125     }
 126 
 127     if (p1->sig < p2->sig)
 128     {
 129         return -1;
 130     }
 131     else if (p1->sig > p2->sig)
 132     {
 133         return 1;
 134     }
 135 
 136     /* scores are equal. prefer lower address */
 137 
 138     if (p1->ptr < p2->ptr)
 139     {
 140         return -1;
 141     }
 142     else if (p1->ptr > p2->ptr)
 143     {
 144         return 1;
 145     }
 146 
 147     return 0;
 148 }
 149 
 150 #define MAX_MATCHES (8192)
 151 
 152 Match matches[MAX_MATCHES];
 153 int count;
 154 
 155 // Add a new Match
 156 void addMatch(uint32_t fadr, int s, int f, int sig)
 157 {
 158     matches[count].ptr = fadr;
 159     matches[count].success = s;
 160     matches[count].fail = f;
 161     matches[count].sig = sig;
 162     count++;
 163 }
 164 
 165 // Add a Match, adjust address for stuff in the block copied to RAM
 166 void fwAddMatch(firmware *fw, uint32_t fadr, int s, int f, int sig)
 167 {
 168     if ((fadr >= fw->base_copied) && (fadr < (fw->base_copied + fw->size2*4)))
 169     {
 170         addMatch(fadr - fw->base_copied + fw->base2,s,f,sig);
 171     }
 172     else
 173     {
 174         addMatch(fadr,s,f,sig);
 175     }
 176 }
 177 
 178 //------------------------------------------------------------------------------------------------------------
 179 
 180 // Signature structures generated by gensig2.exe
 181 
 182 typedef struct {
 183     uint32_t offs;
 184     uint32_t value;
 185     uint32_t mask;
 186 } FuncSig;
 187 
 188 typedef struct {
 189     const char *name;
 190     FuncSig *sig;
 191     int ver;
 192 } FuncsList;
 193 
 194 //------------------------------------------------------------------------------------------------------------
 195 
 196 // Master list of functions / addresses to find
 197 
 198 #define DONT_EXPORT     1
 199 #define OPTIONAL        2
 200 #define UNUSED          4
 201 #define BAD_MATCH       8
 202 #define EV_MATCH        16
 203 #define LIST_ALWAYS     32
 204 
 205 typedef struct {
 206     char        *name;
 207     int         flags;
 208     uint32_t    val;
 209 } func_entry;
 210 
 211 int next_func_entry = 0;
 212 
 213 #define MAX_FUNC_ENTRY  5000
 214 
 215 func_entry  func_names[MAX_FUNC_ENTRY] =
 216 {
 217     // Do these first as they are needed to find others
 218     { "ExportToEventProcedure_FW", UNUSED|DONT_EXPORT },
 219     { "RegisterEventProcedure_FW", UNUSED|DONT_EXPORT },
 220     //{ "CreateJumptable", UNUSED|DONT_EXPORT },
 221     { "_uartr_req", UNUSED|DONT_EXPORT },
 222     { "StartRecModeMenu", UNUSED|DONT_EXPORT },
 223     { "LogCameraEvent", UNUSED|DONT_EXPORT },
 224     { "IsControlEventActive", UNUSED|DONT_EXPORT }, // helper, vx
 225     { "GetLogicalEventName", UNUSED|DONT_EXPORT }, // helper, vx, name made up
 226 
 227     { "AllocateMemory", UNUSED },
 228     { "AllocateUncacheableMemory" },
 229     { "Close" },
 230     { "CreateBinarySemaphore" },
 231     { "CreateCountingSemaphore", UNUSED|DONT_EXPORT },
 232     { "CreateTask" },
 233     { "DebugAssert", OPTIONAL },
 234     { "DeleteDirectory_Fut", UNUSED|DONT_EXPORT },
 235     { "DeleteFile_Fut" },
 236     { "DeleteSemaphore", UNUSED|DONT_EXPORT },
 237     { "DoAELock" },
 238     { "DoAFLock" },
 239     { "EnterToCompensationEVF" },
 240     { "ExecuteEventProcedure" },
 241     { "ExitFromCompensationEVF" },
 242     { "ExitTask" },
 243     { "ExpCtrlTool_StartContiAE", OPTIONAL },
 244     { "ExpCtrlTool_StopContiAE", UNUSED|DONT_EXPORT },
 245     { "Fclose_Fut" },
 246     { "Feof_Fut" },
 247     { "Fflush_Fut" },
 248     { "Fgets_Fut" },
 249     { "Fopen_Fut" },
 250     { "Fread_Fut" },
 251     { "FreeMemory", UNUSED },
 252     { "FreeUncacheableMemory" },
 253     { "Fseek_Fut" },
 254     { "Fwrite_Fut" },
 255     { "GetBatteryTemperature" },
 256     { "GetCCDTemperature" },
 257     { "GetCurrentAvValue" },
 258     { "GetCurrentShutterSpeed" },
 259     { "GetUsableMaxAv", OPTIONAL },
 260     { "GetUsableMinAv", OPTIONAL },
 261     { "GetDrive_ClusterSize" },
 262     { "GetDrive_FreeClusters" },
 263     { "GetDrive_TotalClusters" },
 264     { "GetFocusLensSubjectDistance" },
 265     { "GetFocusLensSubjectDistanceFromLens" },
 266     { "GetImageFolder", OPTIONAL },
 267     { "GetKbdState", UNUSED|DONT_EXPORT },
 268     { "GetMemInfo", UNUSED|DONT_EXPORT },
 269     { "GetOpticalTemperature" },
 270     { "GetParameterData" },
 271     { "GetPropertyCase" },
 272     { "GetSystemTime" },
 273     { "GetVRAMHPixelsSize", UNUSED|DONT_EXPORT },
 274     { "GetVRAMVPixelsSize", UNUSED|DONT_EXPORT },
 275     { "GetZoomLensCurrentPoint" },
 276     { "GetZoomLensCurrentPosition" },
 277     { "GiveSemaphore", OPTIONAL },
 278     { "IsStrobeChargeCompleted" },
 279     { "LEDDrive", OPTIONAL },
 280     { "LocalTime" },
 281     { "LockMainPower" },
 282     { "Lseek", UNUSED|DONT_EXPORT },
 283     { "MakeDirectory_Fut" },
 284     { "MakeSDCardBootable", OPTIONAL },
 285     { "MoveFocusLensToDistance" },
 286     { "MoveIrisWithAv", OPTIONAL },
 287     { "MoveZoomLensWithPoint" },
 288     { "NewTaskShell", UNUSED|DONT_EXPORT },
 289     { "Open" },
 290     { "PB2Rec", UNUSED|DONT_EXPORT },
 291     { "PT_MoveDigitalZoomToWide", OPTIONAL },
 292     { "PT_MoveOpticalZoomAt", OPTIONAL },
 293     { "PT_PlaySound" },
 294     { "PostLogicalEventForNotPowerType" },
 295     { "PostLogicalEventToUI" },
 296     { "PutInNdFilter", OPTIONAL },
 297     { "PutOutNdFilter", OPTIONAL },
 298     { "Read" },
 299 //    { "ReadFastDir", UNUSED|DONT_EXPORT },
 300     { "Rec2PB", UNUSED|DONT_EXPORT },
 301     { "RefreshPhysicalScreen" },
 302     { "Remove", OPTIONAL|UNUSED },
 303     { "RenameFile_Fut" },
 304     { "Restart" },
 305     { "ScreenLock", OPTIONAL },
 306     { "ScreenUnlock", OPTIONAL },
 307     { "SetAE_ShutterSpeed" },
 308     { "SetAutoShutdownTime" },
 309     { "SetCurrentCaptureModeType" },
 310     { "SetDate" },
 311     { "SetFileAttributes" },
 312     { "SetFileTimeStamp", UNUSED|DONT_EXPORT },
 313     { "SetLogicalEventActive" },
 314     { "SetParameterData" },
 315     { "SetPropertyCase" },
 316     { "SetScriptMode" },
 317     { "SleepTask" },
 318     { "TakeSemaphore" },
 319     { "TurnOffBackLight" },
 320     { "TurnOnBackLight" },
 321     { "TurnOnDisplay" },
 322     { "TurnOffDisplay" },
 323     { "UIFS_WriteFirmInfoToFile", UNUSED|DONT_EXPORT },
 324     { "UnlockAE" },
 325     { "UnlockAF" },
 326     { "UnlockMainPower" },
 327     { "UnsetZoomForMovie", OPTIONAL },
 328     { "UpdateMBROnFlash" },
 329     { "VbattGet" },
 330     { "Write" },
 331     { "WriteSDCard" },
 332 
 333     { "_log" },
 334     { "_log10" },
 335     { "_pow" },
 336     { "_sqrt" },
 337     { "add_ptp_handler" },
 338     { "apex2us" },
 339     { "close" },
 340     { "err_init_task", OPTIONAL },
 341     { "exmem_alloc", OPTIONAL },
 342     { "exmem_free", UNUSED|OPTIONAL },
 343     { "exmem_alloc_low", UNUSED|OPTIONAL }, // helper
 344     { "exmem_free_low", UNUSED|OPTIONAL }, // helper
 345     { "exmem_ualloc" },
 346     { "exmem_ufree" },
 347     { "exmem_assert", UNUSED|OPTIONAL|LIST_ALWAYS }, // helper
 348     { "free" },
 349     { "get_nd_value", OPTIONAL },
 350     { "get_current_exp", UNUSED|OPTIONAL },
 351     { "get_current_nd_value", OPTIONAL },
 352     { "get_current_deltasv" },
 353     { "GetBaseSv", OPTIONAL|UNUSED },
 354     { "GetCurrentDriveBaseSvValue" },
 355 
 356     { "kbd_p1_f" },
 357     { "kbd_p1_f_cont" },
 358     { "kbd_p2_f" },
 359     { "kbd_read_keys", UNUSED|DONT_EXPORT },
 360     { "kbd_read_keys_r2" },
 361 
 362     { "kbd_pwr_off" },
 363     { "kbd_pwr_on" },
 364     { "lseek" },
 365     { "malloc" },
 366     { "memcmp" },
 367     { "memcpy" },
 368     { "memset" },
 369     { "mkdir" },
 370     { "mktime_ext", UNUSED|DONT_EXPORT },
 371     { "open" },
 372 //    { "OpenFastDir", UNUSED|DONT_EXPORT },
 373     { "closedir" },
 374     { "qsort" },
 375     { "rand" },
 376     { "read", UNUSED|DONT_EXPORT },
 377     { "realloc", OPTIONAL },
 378     { "reboot_fw_update", UNUSED|DONT_EXPORT },
 379     { "set_control_event", UNUSED|DONT_EXPORT },
 380     { "srand" },
 381     { "stat" },
 382     { "strcat" },
 383     { "strchr" },
 384     { "strcmp" },
 385     { "strcpy" },
 386     { "strftime" },
 387     { "strlen" },
 388     { "strncmp" },
 389     { "strncpy" },
 390     { "strrchr" },
 391     { "strtol" },
 392 //    { "strtolx", UNUSED|DONT_EXPORT },
 393 
 394     { "isdigit" },
 395     { "isspace" },
 396     { "isalpha" },
 397     { "isupper" },
 398     { "islower" },
 399     { "ispunct" },
 400     { "isxdigit" },
 401     { "toupper" },
 402     { "tolower" },
 403     { "taskLock" },
 404     { "taskUnlock" },
 405     { "taskName" },
 406     { "taskIdListGet" },
 407     { "errnoOfTaskGet" },
 408     { "readdir" },
 409     { "strtoul" },
 410     { "strpbrk" },
 411     { "utime" },
 412     { "localtime" },
 413     { "mktime" },
 414     { "opendir" },
 415     { "memchr" },
 416     { "memPartInfoGet" },
 417     { "iosDrvInstall" },
 418     { "iosDevAdd" },
 419     { "iosDevDelete" },
 420     { "GetCurrentTargetDistance" },
 421     { "taskCreateHookAdd" },
 422     { "taskDeleteHookAdd" },
 423     { "Mount_FileSystem" },
 424     { "Unmount_FileSystem" },
 425     { "MakeAFScan" },
 426     { "taskSuspend" },
 427     { "taskResume" },
 428 
 429     { "task_CaptSeq", UNUSED|DONT_EXPORT },
 430     { "task_ExpDrv", UNUSED|DONT_EXPORT },
 431     { "task_FileWrite", UNUSED|DONT_EXPORT },
 432     { "task_InitFileModules", UNUSED|DONT_EXPORT },
 433     { "task_MovieRecord", UNUSED|DONT_EXPORT },
 434     { "task_PhySw", UNUSED|DONT_EXPORT },
 435     { "task_SwitchCheck", UNUSED|DONT_EXPORT }, // old name for task_PhySw
 436     { "task_RotaryEncoder", UNUSED|DONT_EXPORT },
 437 //    { "task_TouchPanel", OPTIONAL },
 438 
 439     //{ "hook_CreateTask" },
 440 
 441     { "time" },
 442     { "vsprintf" },
 443     { "write", UNUSED|DONT_EXPORT },
 444 
 445     { "EngDrvIn", OPTIONAL|UNUSED },
 446     { "EngDrvOut", OPTIONAL|UNUSED },
 447     { "EngDrvRead" },
 448     { "EngDrvBits", OPTIONAL|UNUSED },
 449 
 450     { "PTM_GetCurrentItem" },
 451     { "PTM_SetCurrentItem", UNUSED },
 452     { "PTM_NextItem", OPTIONAL|UNUSED },
 453     { "PTM_PrevItem", OPTIONAL|UNUSED },
 454     { "PTM_SetPropertyEnable", OPTIONAL|UNUSED },
 455 
 456     // OS functions, mostly to aid firmware analysis. Order is important!
 457     { "PT_GetSystemTime", OPTIONAL|UNUSED }, // only for locating timer functions
 458     { "_GetSystemTime", OPTIONAL|UNUSED }, // only for locating timer functions
 459     { "SetTimerAfter", OPTIONAL|UNUSED },
 460     { "SetTimerWhen", OPTIONAL|UNUSED },
 461     { "CancelTimer", OPTIONAL|UNUSED },
 462     { "CancelHPTimer" },
 463     { "SetHPTimerAfterTimeout", OPTIONAL|UNUSED },
 464     { "SetHPTimerAfterNow" },
 465     { "CreateTaskStrictly", OPTIONAL|UNUSED },
 466     { "CreateMessageQueue", OPTIONAL|UNUSED },
 467     { "CreateRecursiveLock", OPTIONAL|UNUSED },
 468     { "GetSemaphoreValue", OPTIONAL|UNUSED },
 469     { "TryTakeSemaphore", OPTIONAL|UNUSED },
 470     { "CreateMessageQueueStrictly", OPTIONAL|UNUSED },
 471     { "CreateEventFlagStrictly", OPTIONAL|UNUSED },
 472     { "CreateBinarySemaphoreStrictly", OPTIONAL|UNUSED },
 473     { "CreateCountingSemaphoreStrictly", OPTIONAL|UNUSED },
 474     { "CreateRecursiveLockStrictly", OPTIONAL|UNUSED },
 475     { "DeleteMessageQueue", OPTIONAL|UNUSED },
 476     { "PostMessageQueue", OPTIONAL|UNUSED },
 477     { "ReceiveMessageQueue", OPTIONAL|UNUSED },
 478     { "TryReceiveMessageQueue", OPTIONAL|UNUSED },
 479     { "TryPostMessageQueue", OPTIONAL|UNUSED },
 480     { "GetNumberOfPostedMessages", OPTIONAL|UNUSED },
 481     { "DeleteRecursiveLock", OPTIONAL|UNUSED },
 482     { "AcquireRecursiveLock", OPTIONAL|UNUSED },
 483     { "ReleaseRecursiveLock", OPTIONAL|UNUSED },
 484     { "WaitForAnyEventFlag", OPTIONAL|UNUSED },
 485     { "WaitForAllEventFlag", OPTIONAL|UNUSED },
 486     { "ClearEventFlag", OPTIONAL|UNUSED },
 487     { "SetEventFlag", OPTIONAL|UNUSED },
 488     { "GetEventFlagValue", OPTIONAL|UNUSED },
 489     { "CreateEventFlag", OPTIONAL|UNUSED },
 490     { "DeleteEventFlag", OPTIONAL|UNUSED },
 491     { "CheckAnyEventFlag", OPTIONAL|UNUSED },
 492     { "CheckAllEventFlag", OPTIONAL|UNUSED },
 493     { "RegisterInterruptHandler", OPTIONAL|UNUSED },
 494     { "UnregisterInterruptHandler", OPTIONAL|UNUSED },
 495     { "GetSRAndDisableInterrupt", OPTIONAL|UNUSED }, // disables IRQ, returns a value
 496     { "SetSR", OPTIONAL|UNUSED }, // enables IRQ, puts back value returned by GetSR
 497     { "EnableInterrupt", OPTIONAL|UNUSED }, // enables IRQ
 498     { "GetCurrentMachineTime", OPTIONAL|UNUSED }, // reads usec counter, name from ixus30
 499     { "HwOcReadICAPCounter", OPTIONAL|UNUSED }, // reads usec counter, name from ixus30
 500     { "EnableDispatch", OPTIONAL|UNUSED }, // enables task switching (high level wrapper)
 501     { "DisableDispatch", OPTIONAL|UNUSED }, // disables task switching (high level wrapper)
 502     { "EnableDispatch_low", OPTIONAL|UNUSED }, // enables task switching
 503     { "DisableDispatch_low", OPTIONAL|UNUSED }, // disables task switching
 504 
 505     // Other stuff needed for finding misc variables - don't export to stubs_entry.S
 506     { "GetSDProtect", UNUSED|DONT_EXPORT },
 507     { "DispCon_ShowBitmapColorBar", UNUSED },
 508     { "ResetZoomLens", OPTIONAL|UNUSED },
 509     { "ResetFocusLens", OPTIONAL|UNUSED },
 510     { "NR_GetDarkSubType", OPTIONAL|UNUSED },
 511     { "NR_SetDarkSubType", OPTIONAL|UNUSED },
 512     { "SavePaletteData", OPTIONAL|UNUSED },
 513     { "GUISrv_StartGUISystem", OPTIONAL|UNUSED },
 514     { "get_resource_pointer", OPTIONAL|UNUSED }, // name made up, gets a pointer to a certain resource (font, dialog, icon)
 515 
 516     { "wrapped_malloc", UNUSED|DONT_EXPORT},    // helper to find malloc, finds the other allocator on ixus30/40
 517     { "malloc_alt", UNUSED|DONT_EXPORT },       // should be the same as malloc when found
 518     { "WaitForEventFlag", UNUSED|DONT_EXPORT }, // helper to find other eventflag functions
 519 
 520     { "filesem_init", OPTIONAL|UNUSED }, // file semaphore init function, needed for verification
 521     { "ImagerActivate", OPTIONAL|UNUSED }, // helper
 522     { "DoMovieFrameCapture", OPTIONAL|UNUSED },
 523     { "MenuIn", OPTIONAL|UNUSED },
 524     { "MenuOut", OPTIONAL|UNUSED },
 525 
 526     { "MFOn", OPTIONAL },
 527     { "MFOff", OPTIONAL },
 528 
 529     { "GetAdChValue", OPTIONAL },
 530     { "get_ptp_buf_size", OPTIONAL },
 531     { "get_ptp_file_buf", OPTIONAL },
 532 
 533     { "cameracon_set_state", OPTIONAL|UNUSED }, // made up name, helper for cameracon_state variable
 534 
 535     { 0, 0, 0 }
 536 };
 537 
 538 // Return the array index of a named function in the array above
 539 int find_saved_sig(const char *name)
 540 {
 541     int i;
 542     for (i=0; func_names[i].name != 0; i++)
 543     {
 544         if (strcmp(name,func_names[i].name) == 0)
 545         {
 546             return i;
 547         }
 548     }
 549     return -1;
 550 }
 551 
 552 // Save the address value found for a function in the above array
 553 void save_sig(const char *name, uint32_t val)
 554 {
 555     int i = find_saved_sig(name);
 556     if (i >= 0)
 557     {
 558         func_names[i].val = val;
 559     }
 560 }
 561 
 562 // Get the saved address value for a named function
 563 // If the address value is 0 then assume the function search has not occurred yet, so go search for it.
 564 int get_saved_sig(firmware *fw, const char *name)
 565 {
 566     int i = find_saved_sig(name);
 567     if (i >= 0)
 568     {
 569         if (func_names[i].val == 0)
 570         {
 571             // See if the function is in the 'func_list' array below
 572             int find_func(const char* name);
 573             int k1 = find_func(name);
 574             if (k1 >= 0)
 575             {
 576                 // if found do full search
 577                 void find_matches(firmware*,const char*);
 578                 find_matches(fw, name);
 579                 count = 0;
 580             }
 581             else
 582             {
 583                 // not found, only do string matching search
 584                 void find_str_sig_matches(firmware*,const char*);
 585                 find_str_sig_matches(fw, name);
 586                 count = 0;
 587             }
 588         }
 589         if (func_names[i].val == 0)
 590         {
 591             // If not found return invalid index
 592             i = -1;
 593         }
 594     }
 595     return i;
 596 }
 597 
 598 // Search for something relative to the location stored for a previously matched function
 599 // Matching is done via the 'func' function, searching continues until 'func' returns non-zero
 600 // Starts searching at 'ofst' from the saved address for a max of 'len' instructions
 601 // Returns the 'func' value or 0 if no match found
 602 int search_saved_sig(firmware *fw, char *sig, int (*func)(firmware*, int, int), int v, int ofst, int len)
 603 {
 604     int k = get_saved_sig(fw, sig);
 605     if (k >= 0)
 606     {
 607         int idx = adr2idx(fw, func_names[k].val);
 608         for (k=idx+ofst; k<idx+ofst+len; k++)
 609         {
 610             int rv = func(fw, k, v);
 611             if (rv)
 612                 return rv;
 613         }
 614     }
 615     return 0;
 616 }
 617 
 618 //------------------------------------------------------------------------------------------------------------
 619 
 620 // New string / signature matching structure
 621 
 622 // Structure for matching
 623 
 624 typedef struct {
 625     int     type;               // 1 = func*, string, 2 = string, ... string*, func*, 3 = ADR Rx, func, ADR Ry, string, BL, ... string, etc
 626     char    *name;              // function name
 627     char    *ev_name;           // event / other name to match in the firmware
 628     int     offset;             // offset for following branches, or other tests
 629     // VxWorks version specific offsets?
 630     int     vxworks_offset;
 631 } string_sig;
 632 
 633 // Load old signature matching data generated by gensig_vxworks
 634 #include "signatures_vxworks.h"
 635 
 636 //------------------------------------------------------------------------------------------------------------
 637 
 638 // Data for matching 'apex2us' function
 639 uint32_t apex2us_test[] = { 0x3D09000, 0x3BBA304, 0x3A728D2, 0x3931EF4, 0x37F8303, 0x36C52A2, 0x3598B85, 0x3472B6A, 0 };
 640 
 641 // Special case for apex2us
 642 int match_apex2us(firmware *fw, int k, uint32_t v1, __attribute__ ((unused))uint32_t v2)
 643 {
 644     if (isLDR_PC(fw,k) && (LDR2val(fw,k) == v1) && ((fwRd(fw,k) == 1) || (fwRd(fw,k) == 2)))
 645     {
 646         k = find_inst_rev(fw, isSTMFD_LR, k, 200);
 647         if (k != 0)
 648         {
 649             if (fwval(fw,k-2) == 0xE3700D09)    // CMN R0, #0x240
 650                 k -= 2;
 651             uint32_t fadr = idx2adr(fw,k);
 652             fwAddMatch(fw,fadr,32,0,121);
 653             return 1;
 654         }
 655     }
 656     return 0;
 657 }
 658 int find_apex2us(firmware *fw, __attribute__ ((unused))string_sig *sig, int j)
 659 {
 660     int i;
 661     for (i=0; apex2us_test[i] != 0; i++)
 662         if (fwval(fw,j+i) != apex2us_test[i])
 663             return 0;
 664 
 665     return search_fw(fw, match_apex2us, idx2adr(fw,j), 0, 1);
 666 }
 667 
 668 // Special case for mkdir
 669 int find_mkdir(firmware *fw, __attribute__ ((unused))string_sig *sig, int k)
 670 {
 671     if (fwval(fw,k) == 0x12CEA600)
 672     {
 673         k = find_inst_rev(fw, isSTMFD_LR, k-20, 200);
 674         if (k != 0)
 675         {
 676             if ((((fwval(fw,k+12) & 0xFFF0FFFF) == 0xE350002F) && ((fwval(fw,k+15) & 0xFFF0FFFF) == 0xE3500021) && ((fwval(fw,k+19) & 0xFFF0FFFF) == 0xE3500020)) ||
 677                 (((fwval(fw,k+11) & 0xFFF0FFFF) == 0xE350002F) && ((fwval(fw,k+14) & 0xFFF0FFFF) == 0xE3500021) && ((fwval(fw,k+18) & 0xFFF0FFFF) == 0xE3500020)))
 678             {
 679                 uint32_t fadr = 0;
 680                 if (isBL(fw,k+47))
 681                 {
 682                     fadr = followBranch(fw, idx2adr(fw,k+47), 0x01000001);
 683                 }
 684                 else if (isBL(fw,k+48))
 685                 {
 686                     fadr = followBranch(fw, idx2adr(fw,k+48), 0x01000001);
 687                 }
 688                 if (fadr != 0)
 689                 {
 690                     fwAddMatch(fw,fadr,32,0,121);
 691                     return 1;
 692                 }
 693             }
 694         }
 695     }
 696     return 0;
 697 }
 698 
 699 // Special case for _pow
 700 int find_pow(firmware *fw, __attribute__ ((unused))string_sig *sig, int j)
 701 {
 702     if (!idx_valid(fw,j) || !idx_valid(fw,j+3)) return 0;
 703     // Find values passed to _pow
 704     if ((fwval(fw,j) == 0x00000000) && (fwval(fw,j+1) == 0x40000000) && (fwval(fw,j+2) == 0x00000000) && (fwval(fw,j+3) == 0x408F4000))
 705     {
 706         uint32_t adr1 = idx2adr(fw,j);      // address of 1st value
 707         uint32_t adr2 = idx2adr(fw,j+2);    // address of 2nd value
 708         int j1;
 709 
 710         for (j1 = j-5; j1>0; j1--)
 711         {
 712             if (isADR_PC_cond(fw,j1) &&                 // ADR ?
 713                 (fwval(fw,j1+1) == 0xE8900003) &&       // LDMIA R0,{R0,R1}
 714                 isBL(fw,j1+2) &&                        // BL
 715                 isADR_PC_cond(fw,j1+4))                 // ADR ?
 716             {
 717                 if ((ADR2adr(fw,j1) == adr1) && (ADR2adr(fw,j1+4) == adr2))
 718                 {
 719                     uint32_t fadr = followBranch(fw,idx2adr(fw,j1+2),0x01000001);
 720                     fwAddMatch(fw,fadr,32,0,121);
 721                     return 1;
 722                 }
 723             }
 724             else
 725             if (isADR_PC_cond(fw,j1) &&                 // ADR ?
 726                 (fwval(fw,j1+1) == 0xE8900003) &&       // LDMIA R0,{R0,R1}
 727                 isBL(fw,j1+2) &&                        // BL
 728                 isADR_PC_cond(fw,j1+3))                 // ADR ?
 729             {
 730                 if ((ADR2adr(fw,j1) == adr1) && (ADR2adr(fw,j1+3) == adr2))
 731                 {
 732                     uint32_t fadr = followBranch(fw,idx2adr(fw,j1+2),0x01000001);
 733                     fwAddMatch(fw,fadr,32,0,121);
 734                     return 1;
 735                 }
 736             }
 737             else
 738             if (isADR_PC_cond(fw,j1) &&                 // ADR ?
 739                 (fwval(fw,j1+2) == 0xE8900003) &&       // LDMIA R0,{R0,R1}
 740                 isBL(fw,j1+3) &&                        // BL
 741                 isADR_PC_cond(fw,j1+4))                 // ADR ?
 742             {
 743                 if ((ADR2adr(fw,j1) == adr1) && (ADR2adr(fw,j1+4) == adr2))
 744                 {
 745                     uint32_t fadr = followBranch(fw,idx2adr(fw,j1+3),0x01000001);
 746                     fwAddMatch(fw,fadr,32,0,121);
 747                     return 1;
 748                 }
 749             }
 750         }
 751     }
 752 
 753     return 0;
 754 }
 755 
 756 // Special case for _log & _log10
 757 int find_log(firmware *fw, __attribute__ ((unused))string_sig *sig, int j)
 758 {
 759     // Find values passed to _log
 760     if (isBL(fw,j) && isLDR_PC(fw,j+1) && (LDR2val(fw,j+1) == 0x3FDBCB7B) && isLDR_PC(fw,j+2) && (LDR2val(fw,j+2) == 0x1526E50E))
 761     {
 762         uint32_t fadr = followBranch(fw,idx2adr(fw,j),0x01000001);
 763         fwAddMatch(fw,fadr,32,0,121);
 764         return 1;
 765     }
 766 
 767     return 0;
 768 }
 769 int find_log10(firmware *fw, __attribute__ ((unused))string_sig *sig, int j)
 770 {
 771     // Find values passed to _log
 772     if (isBL(fw,j) && isLDR_PC(fw,j+1) && (LDR2val(fw,j+1) == 0x3FDBCB7B) && isLDR_PC(fw,j+2) && (LDR2val(fw,j+2) == 0x1526E50E))
 773     {
 774         int k = find_inst_rev(fw, isSTMFD_LR, j-1, 100);
 775         uint32_t fadr = idx2adr(fw,k);
 776         fwAddMatch(fw,fadr,32,0,121);
 777         return 1;
 778     }
 779 
 780     return 0;
 781 }
 782 // Special case for get_ptp_file_buf
 783 int find_get_ptp_file_buf(firmware *fw, __attribute__ ((unused))string_sig *sig, int j)
 784 {
 785     /*
 786      * looking for
 787      * MOV r0,#4
 788      * BNE
 789      * BL get_ptp_buf_size
 790      * BIC r1, r0, #1
 791      * MOV r0,#4
 792      * BL sub...
 793     */
 794     if(!(isMOV_immed(fw,j)
 795         && (fwRn(fw,j) == 0)
 796         && ((fwval(fw,j+1) & 0xFF000000) == 0x1A000000) // BNE
 797         && isBL(fw,j+2)
 798         && ((fwval(fw,j+3) & 0xFFF00000) == 0xe3C00000) // BIC
 799         && (ALUop2(fw,j+3) == 1)
 800         && isMOV_immed(fw,j+4)
 801         && (fwRn(fw,j+4) == 0)
 802         && isBL(fw,j+5))) {
 803         return 0;
 804     }
 805     if(ALUop2(fw,j) != 4 || ALUop2(fw,j+4) != 4) {
 806         return 0;
 807     }
 808 
 809     uint32_t f1 = followBranch(fw,idx2adr(fw,j+2),0x01000001);
 810     int i = get_saved_sig(fw,"get_ptp_buf_size");
 811     // if sig not found, end search completely
 812     if(i < 0) {
 813         // fprintf(stderr,"find_get_ptp_file_buf func missing @0x%08x\n",idx2adr(fw,j));
 814         return 1;
 815     }
 816     if(f1 != func_names[i].val) {
 817         // fprintf(stderr,"find_get_ptp_file_buf func mismatch @0x%08x\n",idx2adr(fw,j));
 818         return 0;
 819     }
 820     // search backwards for push
 821     int k = find_inst_rev(fw, isSTMFD_LR, j-1, 8);
 822     if(k < 0) {
 823         // fprintf(stderr,"find_get_ptp_file_buf failed to find push @0x%08x\n",idx2adr(fw,j));
 824         return 0;
 825     }
 826     // functions could have a MOV, LDR etc before the push, but not seen for this function
 827     uint32_t fadr = idx2adr(fw, k);
 828     fwAddMatch(fw,fadr,32,0,121);
 829     // fprintf(stderr,"find_get_ptp_file_buf match @0x%08x\n",fadr);
 830 
 831     return 1;
 832 }
 833 
 834 // Special case for 'closedir' (DryOS)
 835 int find_closedir(firmware *fw)
 836 {
 837     int j = get_saved_sig(fw,"OpenFastDir");
 838     if (j >= 0)
 839     {
 840         int k = find_inst(fw, isSTMFD_LR, adr2idx(fw,func_names[j].val)+1, 100);
 841         if (isB(fw,k-1) && isBL(fw,k-2))
 842         {
 843             uint32_t fadr = followBranch(fw, idx2adr(fw, k-2), 0x01000001);
 844             fwAddMatch(fw,fadr,32,0,121);
 845             return 1;
 846         }
 847     }
 848 
 849     return 0;
 850 }
 851 
 852 // Special case for 'add_ptp_handler'
 853 int find_add_ptp_handler(firmware *fw, __attribute__ ((unused))string_sig *sig, int k)
 854 {
 855     uint32_t vals[] = { 0x9801, 0x9802, 0x9803, 0x9804, 0x9805, 0 };
 856     uint32_t fadr = 0;
 857 
 858     int i = 0;
 859     while ((vals[i] != 0) && isLDR_PC(fw,k) && (fwRd(fw,k) == 0) && (LDR2val(fw,k) == vals[i]))
 860     {
 861         k = find_inst(fw, isBL, k+1, 5);
 862         if (k == 0) return 0;
 863         if (fadr == 0)
 864             fadr = followBranch(fw, idx2adr(fw,k), 0x01000001);
 865         k = find_inst(fw, isLDR_PC, k+1, 5);
 866         if (k == 0) return 0;
 867         i++;
 868     }
 869 
 870     if (fadr != 0)
 871     {
 872         fwAddMatch(fw,fadr,32,0,121);
 873         return 1;
 874     }
 875 
 876     return 0;
 877 }
 878 
 879 // Special case for 'PT_PlaySound'
 880 int find_PT_PlaySound(firmware *fw)
 881 {
 882     int j, k;
 883     int k1 = get_saved_sig(fw,"LogCameraEvent");
 884 
 885     if (k1 >= 0)
 886     {
 887         j = find_str_ref(fw,"BufAccBeep");
 888         if (j >= 0)
 889         {
 890             k = find_inst(fw, isBL, j+1, 4);
 891             if (k >= 0)
 892             {
 893                 uint32_t fadr = followBranch(fw, idx2adr(fw,k), 0x01000001);
 894                 if (func_names[k1].val == fadr)
 895                 {
 896                     k = find_inst(fw, isB, k+1, 10);
 897                     fadr = followBranch(fw, idx2adr(fw, k), 1);
 898                     fwAddMatch(fw,fadr,32,0,122);
 899                     return 1;
 900                 }
 901             }
 902         }
 903     }
 904 
 905     return 0;
 906 }
 907 
 908 // Special case for 'ExportToEventProcedure'
 909 int find_ExportToEventProcedure(firmware *fw)
 910 {
 911     int k = find_str_ref(fw,"ExportToEventProcedure");
 912 
 913     if (k >= 0)
 914     {
 915         if (isLDR_PC(fw,k+1) && (isBorBL(fw,k+2) || isBorBL(fw,k+3)) && (fwRd(fw,k+1) == 1))
 916         {
 917             uint32_t fadr = LDR2val(fw,k+1);
 918             fwAddMatch(fw,fadr,32,0,122);
 919             return 1;
 920         }
 921     }
 922 
 923     return 0;
 924 }
 925 
 926 // Special case for 'RegisterEventProcedure'
 927 int find_RegisterEventProcedure(firmware *fw)
 928 {
 929     int k = find_str_ref(fw,"CreateProxyOfEventProcedure");
 930 
 931     if (k >= 0)
 932     {
 933         if (isLDR_PC(fw,k+1) && (isBorBL(fw,k+2) || isBorBL(fw,k+3)) && (fwRd(fw,k) == 0))
 934         {
 935             uint32_t fadr = 0;
 936             if (isBorBL(fw,k+2))
 937                 fadr = followBranch(fw,idx2adr(fw,k+2),0x01000001);
 938             else
 939                 fadr = followBranch(fw,idx2adr(fw,k+3),0x01000001);
 940             fwAddMatch(fw,fadr,32,0,122);
 941             return 1;
 942         }
 943     }
 944 
 945     return 0;
 946 }
 947 
 948 // Special case for set_control_event (Vx)
 949 int find_set_control_event(firmware *fw)
 950 {
 951     int j1, j2, k, found, n;
 952     int k1 = get_saved_sig(fw,"IsControlEventActive");
 953     int k2 = get_saved_sig(fw,"GetLogicalEventName");
 954 
 955     if ((k1 >= 0) && (k2 >= 0))
 956     {
 957         j1 = adr2idx(fw, func_names[k1].val);
 958         j2 = adr2idx(fw, func_names[k2].val);
 959         found = 0;
 960         // search from IsControlEventActive backwards
 961         for (k=j1-1; k>j1-256; k--)
 962         {
 963             if (isBL(fw,k))
 964             {
 965                 if (j2 == idxFollowBranch(fw,k,0x01000001))
 966                 {
 967                     // reference to GetLogicalEventName found
 968                     found = 1;
 969                     break;
 970                 }
 971             }
 972         }
 973         if (found)
 974         {
 975             found = 0;
 976             // locate function start
 977             k = find_inst_rev(fw,isSTMFD_LR,k,60);
 978             // locate function end
 979             j2 = find_inst(fw,isLDMFD_PC,k+1,128);
 980             if ( (k<0) || (j2<0) )
 981                 return 0;
 982             int prevbldest = 0;
 983             n = 0;
 984             k++;
 985             // look for not more than 7 BLs
 986             while (n<7)
 987             {
 988                 k = find_inst(fw,isBL,k,32);
 989                 // too late hit or no hit
 990                 if ( (k>j2) || (k<0) )
 991                     return 0;
 992                 j1 = idxFollowBranch(fw,k,0x01000001);
 993                 if (prevbldest==j1)
 994                 {
 995                     // two consecutive calls to set_control_event
 996                     found = 1;
 997                     break;
 998                 }
 999                 prevbldest = j1;
1000                 n++;
1001                 k++;
1002             }
1003             if (found)
1004             {
1005                 fwAddMatch(fw,idx2adr(fw,j1),32,0,122);
1006                 return 1;
1007             }
1008         }
1009     }
1010     return 0;
1011 }
1012 
1013 // see also find_FileAccessSem()
1014 int find_filesem_init(firmware *fw)
1015 {
1016     int s1 = find_str(fw, "FileSem.c");
1017     if (s1 < 0)
1018         return 0;
1019     s1 = find_inst(fw, isLDR_PC, s1+2, 16);
1020     if (s1 < 0)
1021         return 0;
1022     s1 = find_inst_rev(fw, isSTMFD_LR, s1-1, 16);
1023     if (s1 < 0)
1024         return 0;
1025     fwAddMatch(fw,idx2adr(fw,s1),32,0,122);
1026     return 1;
1027 }
1028 
1029 int find_getcurrentmachinetime(firmware *fw)
1030 {
1031     int f1 = get_saved_sig(fw,"SetHPTimerAfterNow");
1032     if (f1 < 0)
1033         return 0;
1034     f1 = adr2idx(fw, func_names[f1].val);
1035     f1 = find_inst(fw, isBL, f1, 16);
1036     if (f1>0)
1037     {
1038         f1 = idxFollowBranch(fw,f1,0x01000001);
1039         fwAddMatch(fw,idx2adr(fw,f1),32,0,122);
1040         return 1;
1041     }
1042     return 0;
1043 }
1044 
1045 // for cams with ND and Iris (g7)
1046 int find_get_nd_value(firmware *fw)
1047 {
1048     // match is only for cams with both, task is mostly a good indicator
1049     if((get_saved_sig(fw,"task_NdActuator") < 0) || (get_saved_sig(fw,"task_IrisEvent") < 0)) {
1050         return 0;
1051     }
1052     int f1 = find_saved_sig("get_nd_value");
1053     if ((f1 >= 0) && (func_names[f1].val != 0)) // return if func already found
1054         return 0;
1055 
1056     f1 = get_saved_sig(fw,"PutInNdFilter_FW");
1057     int f2 = get_saved_sig(fw,"ClearEventFlag");
1058 
1059     if ((f1 < 0) || (f2 < 0))
1060         return 0;
1061 
1062     f1 = adr2idx(fw, func_names[f1].val);
1063     f2 = adr2idx(fw, func_names[f2].val);
1064     int k1 = find_Nth_inst(fw,isBL,f1,10,2);
1065     int k2 = find_inst(fw,isBL,f1,6);
1066     if ((k1 == -1) || (k2 == -1))
1067         return 0;
1068     if ( followBranch2(fw,idx2adr(fw,k2),0x01000001) != idx2adr(fw,f2) ) // ClearEventFlag?
1069         return 0;
1070 
1071     // note the folliwng isn't super robust, but only one model
1072     k1 = idxFollowBranch(fw,k1,0x01000001); // PutInNdFilter_low veneer
1073     k1 = find_inst(fw,isB,k1,3); // veneer
1074     if (k1 == -1) {
1075         return 0;
1076     }
1077     k1 = idxFollowBranch(fw,k1,0x00000001); // PutInNdFilter_low
1078     if (k1 == -1) {
1079         return 0;
1080     }
1081     k1 = find_inst(fw,isBL,k1,4); // get_nd_value wrapper
1082     if (k1 == -1) {
1083         return 0;
1084     }
1085     k1 = idxFollowBranch(fw,k1,0x01000001); //
1086     k1 = find_inst(fw,isBL,k1,2); // get_nd_value
1087     if (k1 == -1) {
1088         return 0;
1089     }
1090     k1 = idxFollowBranch(fw,k1,0x01000001);
1091     fwAddMatch(fw,idx2adr(fw,k1),32,0,122);
1092     return 1;
1093 }
1094 
1095 // for cams with both ND and iris
1096 int find_get_current_nd_value_iris(firmware *fw)
1097 {
1098     // match is only for cams with both, task is mostly a good indicator
1099     if((get_saved_sig(fw,"task_NdActuator") < 0) || (get_saved_sig(fw,"task_IrisEvent") < 0)) {
1100         return 0;
1101     }
1102     int f1 = get_saved_sig(fw,"get_current_exp");
1103     if(f1 < 0)
1104         return 0;
1105 
1106     f1 = adr2idx(fw, func_names[f1].val);
1107     int blcnt, i;
1108     // expect
1109     // 2x bl DebugAssert
1110     // followed by 5 bl with other instruction between
1111     // looking for 5th
1112     for(i=0, blcnt=0; i<28 && blcnt < 8; i++) {
1113         if(!isBL(fw,f1+i)) {
1114             continue;
1115         }
1116         blcnt++;
1117         if(blcnt == 7) {
1118             int f2 = idxFollowBranch(fw,f1+i,0x01000001);
1119             // non-ND cameras have a call to return 0
1120             if(isMOV(fw,f2) && (fwRd(fw,f2) == 0) && (fwOp2(fw,f2) == 0)) // MOV R0, 0
1121                 return 0;
1122             // expect wrapper that pushes LR, makes return a short
1123             if(isBL(fw,f2+1)) {
1124                 f2 = idxFollowBranch(fw,f2+1,0x01000001);
1125                 fwAddMatch(fw,idx2adr(fw,f2),32,0,122);
1126                 return 1;
1127             }
1128             return 0;
1129         }
1130     }
1131     return 0;
1132 }
1133 
1134 int find_get_current_nd_value(firmware *fw)
1135 {
1136 
1137     // string only present on ND-only cameres
1138     if(find_str(fw, "IrisSpecification.c") < 0) {
1139         return find_get_current_nd_value_iris(fw);
1140     }
1141 
1142     int f1 = get_saved_sig(fw,"GetCurrentAvValue");
1143     if(f1 < 0)
1144         return 0;
1145 
1146     f1 = adr2idx(fw, func_names[f1].val);
1147     // skip wrapper
1148     if (!isBL(fw,f1+1))
1149         return 0;
1150     f1 = idxFollowBranch(fw,f1+1,0x01000001);
1151     // expect
1152     // ldr r0, ="IrisController.c"
1153     // bl DebugAssert
1154     // bl get_current_nd_value
1155     int sadr = find_str(fw, "IrisController.c");
1156     int j = find_nxt_str_ref(fw, sadr, f1);
1157     if ((j < 0) || (j-f1 > 8))
1158         return 0;
1159 
1160     j = find_Nth_inst(fw,isBL,j,8,2);
1161     if (j == -1)
1162         return 0;
1163     f1 = idxFollowBranch(fw,j,0x01000001);
1164     fwAddMatch(fw,idx2adr(fw,f1),32,0,122);
1165     return 1;
1166 }
1167 
1168 // get live view "DeltaSV" value
1169 int find_get_current_deltasv(firmware *fw)
1170 {
1171     int f1 = get_saved_sig(fw,"get_current_exp");
1172     if(f1 < 0)
1173         return 0;
1174 
1175     f1 = adr2idx(fw, func_names[f1].val);
1176     int blcnt, i;
1177     // expect
1178     // 2x bl DebugAssert
1179     // followed by at least 3 bl with other instructions between
1180     // looking for 3rd
1181     for(i=0, blcnt=0; i<24 && blcnt < 5; i++) {
1182         if(!isBL(fw,f1+i)) {
1183             continue;
1184         }
1185         blcnt++;
1186         if(blcnt == 5) {
1187             int f2 = idxFollowBranch(fw,f1+i,0x01000001);
1188             // veneer?
1189             if(isB(fw,f2)) {
1190                 f2 = idxFollowBranch(fw,f2,0x00000001);
1191             }
1192             fwAddMatch(fw,idx2adr(fw,f2),32,0,122);
1193             return 1;
1194         }
1195     }
1196     return 0;
1197 }
1198 
1199 int find_exmem_ufree(firmware *fw)
1200 {
1201 
1202     int k = get_saved_sig(fw,"ExMem.FreeCacheable_FW"); // newer cam
1203     if (k >= 0)
1204         return 0;
1205     k = get_saved_sig(fw,"memset_FW");
1206     if (k < 0)
1207         return 0;
1208     k = adr2idx(fw, func_names[k].val);
1209     int sadr = find_str(fw, "ComMemMan.c"); // always there
1210     int j = find_nxt_str_ref(fw, sadr, sadr);
1211     if (j < 0)
1212         return 0;
1213     j = find_nxt_str_ref(fw, sadr, j+1);
1214     if (j < 0)
1215         return 0;
1216     int n;
1217     for (n=j+8; n<j+36; n++)
1218     {
1219         if (isBL(fw,n))
1220         {
1221             if (idx2adr(fw,idxFollowBranch(fw,n,0x01000001)) == idx2adr(fw,k))
1222             {
1223                 int m = find_inst_rev(fw,isBL,n-1,4);
1224                 if (m != -1)
1225                 {
1226                     m = idxFollowBranch(fw,m,0x01000001);
1227                     fwAddMatch(fw,idx2adr(fw,m),32,0,122);
1228                     return 1;
1229                 }
1230             }
1231         }
1232     }
1233     // no success, search for first routine calling exmem_free_low
1234     k = get_saved_sig(fw,"exmem_free_low");
1235     if (k < 0)
1236         return 0;
1237     k = adr2idx(fw, func_names[k].val);
1238     for (n=50; n<1000; n++) {
1239         if (isBL(fw,k+n)) {
1240             int m = idxFollowBranch(fw,k+n,0x01000001);
1241             if (idx2adr(fw,m) == idx2adr(fw,k))
1242             {
1243                 j = find_inst_rev(fw,isSTMFD_LR,k+n,23);
1244                 if (j != -1) {
1245                     fwAddMatch(fw,idx2adr(fw,j),32,0,122);
1246                     return 1;
1247                 }
1248             }
1249         }
1250     }
1251     return 0;
1252 }
1253 
1254 int find_exmem_ualloc(firmware *fw)
1255 {
1256 
1257     int k = get_saved_sig(fw,"ExMem.AllocCacheable_FW"); // newer cam
1258     if (k >= 0)
1259         return 0;
1260     k = get_saved_sig(fw,"DebugAssert"); //
1261     if (k < 0)
1262         return 0;
1263     k = adr2idx(fw, func_names[k].val);
1264     int sadr = find_str(fw, "ComMemMan.c"); // always there
1265     int j = find_nxt_str_ref(fw, sadr, sadr);
1266     if (j < 0)
1267         return 0;
1268     int m = find_inst(fw,isBorBL,j+3,10);
1269     if (m != -1)
1270     {
1271         m = idxFollowBranch(fw,m,0x01000001);
1272         if (idx2adr(fw,m) != idx2adr(fw,k))
1273         {
1274             fwAddMatch(fw,idx2adr(fw,m),32,0,122);
1275             return 1;
1276         }
1277     }
1278     // no success, search for first routine calling exmem_alloc_low
1279     k = get_saved_sig(fw,"exmem_alloc_low");
1280     if (k < 0)
1281         return 0;
1282     k = adr2idx(fw, func_names[k].val);
1283     int n;
1284     for (n=70; n<1000; n++) {
1285         if (isBL(fw,k+n)) {
1286             m = idxFollowBranch(fw,k+n,0x01000001);
1287             if (idx2adr(fw,m) == idx2adr(fw,k))
1288             {
1289                 j = find_inst_rev(fw,isSTMFD_LR,k+n,14);
1290                 if (j != -1) {
1291                     fwAddMatch(fw,idx2adr(fw,j),32,0,122);
1292                     return 1;
1293                 }
1294             }
1295         }
1296     }
1297     return 0;
1298 }
1299 
1300 int find_exmem_free(firmware *fw)
1301 {
1302 
1303     int k = get_saved_sig(fw,"ExMem.FreeCacheable_FW"); // newer cam
1304     if (k >= 0)
1305         return 0;
1306     k = get_saved_sig(fw,"exmem_free_low");
1307     if (k < 0)
1308         return 0;
1309     k = adr2idx(fw, func_names[k].val);
1310     int n;
1311     for (n=50; n<1000; n++) {
1312         if (isBL(fw,k+n)) {
1313             int m = idxFollowBranch(fw,k+n,0x01000001);
1314             if (idx2adr(fw,m) == idx2adr(fw,k))
1315             {
1316                 int bic = 0;
1317                 int o;
1318                 for (o=1; o<9; o++) {
1319                     if ((fwval(fw,k+n-o)&0xfff00fff) == 0xe3c00201) { // bic rx, rx, 0x10000000
1320                         bic++;
1321                         break;
1322                     }
1323                 }
1324                 if (!bic) {
1325                     continue;
1326                 }
1327                 int j = find_inst_rev(fw,isSTMFD_LR,k+n,30);
1328                 if (j != -1) {
1329                     fwAddMatch(fw,idx2adr(fw,j),32,0,122);
1330                     return 1;
1331                 }
1332             }
1333         }
1334     }
1335     return 0;
1336 }
1337 
1338 int find_exmem_alloc(firmware *fw)
1339 {
1340 
1341     int k = get_saved_sig(fw,"ExMem.AllocCacheable_FW"); // newer cam
1342     k = get_saved_sig(fw,"exmem_alloc_low");
1343     if (k < 0)
1344         return 0;
1345     k = adr2idx(fw, func_names[k].val);
1346     int n;
1347     for (n=70; n<1000; n++) {
1348         if (isBL(fw,k+n)) {
1349             int m = idxFollowBranch(fw,k+n,0x01000001);
1350             if (idx2adr(fw,m) == idx2adr(fw,k))
1351             {
1352                 int bic = 0;
1353                 int o;
1354                 for (o=1; o<9; o++) {
1355                     if ((fwval(fw,k+n+o)&0xfff00fff) == 0xe3c00201) { // bic rx, rx, 0x10000000
1356                         bic++;
1357                         break;
1358                     }
1359                 }
1360                 if (!bic) {
1361                     continue;
1362                 }
1363                 int j = find_inst_rev(fw,isSTMFD_LR,k+n,16);
1364                 if (j != -1) {
1365                     fwAddMatch(fw,idx2adr(fw,j),32,0,122);
1366                     return 1;
1367                 }
1368             }
1369         }
1370     }
1371     return 0;
1372 }
1373 
1374 int find_get_ptp_buf_size(firmware *fw)
1375 {
1376     int j = get_saved_sig(fw,"handle_PTP_OC_SendObject"); // same handler as CANON_SendObjectByPath
1377     if(j < 0) {
1378         // fprintf(stderr,"find_get_ptp_buf_size missing handle_PTP_OC_SendObject\n");
1379         return 0;
1380     }
1381     int k=adr2idx(fw,func_names[j].val);
1382     int k_max=k+120;
1383     uint32_t adr=0;
1384     // ID of the file buffer appears to always be 4 on vxworks
1385     // very early cams have a hard coded size
1386     uint32_t file_buf_id=4;
1387 
1388     for(; k < k_max;k++) {
1389         // look for
1390         // mov r0,#file_buf_id
1391         // bl ...
1392         if(isMOV_immed(fw,k) && fwRn(fw,k) == 0 && ALUop2(fw,k) == file_buf_id && isBL(fw, k+1)) {
1393             adr = followBranch(fw,idx2adr(fw,k+1),0x01000001);
1394             // fprintf(stderr,"find_get_ptp_buf_size match 1 0x%08x @0x%08x\n",adr,idx2adr(fw,k+1));
1395             break;
1396         }
1397     }
1398     if(!adr) {
1399         // fprintf(stderr,"find_get_ptp_buf_size no match\n");
1400         return 0;
1401     }
1402     // look for same seq again, within 6 ins
1403     k_max = k+6;
1404     for(; k < k_max;k++) {
1405         if(isMOV_immed(fw,k) && fwRn(fw,k) == 0 && ALUop2(fw,k) == file_buf_id && isBL(fw, k+1)) {
1406             uint32_t adr2 = followBranch(fw,idx2adr(fw,k+1),0x01000001);
1407             // is it the same address?
1408             if(adr2 == adr) {
1409                 // fprintf(stderr,"find_get_ptp_buf_size match 2 @0x%08x\n",idx2adr(fw,k+1));
1410                 fwAddMatch(fw,adr,32,0,122);
1411                 return 0;
1412             }
1413             // fprintf(stderr,"find_get_ptp_buf_size match 2 mismatch 0x%08x != 0x%08x @0x%08x\n",adr,adr2,idx2adr(fw,k+1));
1414         }
1415     }
1416     return 0;
1417 }
1418 
1419 int find_GetBaseSv(firmware *fw)
1420 {
1421     int j = get_saved_sig(fw,"SetPropertyCase");
1422     if (j < 0)
1423         return 0;
1424     j = adr2idx(fw, func_names[j].val);
1425     int j2 = get_saved_sig(fw,"DebugAssert");
1426     if (j2 < 0)
1427         return 0;
1428     j2 = adr2idx(fw, func_names[j2].val);
1429 
1430     int sadr = find_str(fw, "Sensitive.c");
1431     if (sadr < fw->lowest_idx)
1432         return 0;
1433     int s1 = find_nxt_str_ref(fw, sadr, -1/*fw->lowest_idx*/);
1434     int hist[3] = {0, 0, 0};
1435     while (s1 >= 0)
1436     {
1437         hist[2] = hist[1];
1438         hist[1] = hist[0];
1439         hist[0] = s1;
1440         if (hist[0] && hist[1] && hist[2])
1441         {
1442             if ((hist[0]-hist[1]<7) && (hist[1]-hist[2]<9))
1443             {
1444                 int n;
1445                 for (n=s1+1; n<s1+26; n++)
1446                 {
1447                     if ( isBL(fw, n) )
1448                     {
1449                         int k;
1450                         k = idxFollowBranch(fw,n,0x01000001);
1451                         if ( idx2adr(fw, k) == idx2adr(fw, j) )
1452                         {
1453                             // SetPropertyCase call found
1454                             k = find_inst(fw, isBL, s1+2, 6);
1455                             if (k != -1)
1456                             {
1457                                 int l = idxFollowBranch(fw,k,0x01000001);
1458                                 if (idx2adr(fw,l) == idx2adr(fw,j2)) // DebugAssert?
1459                                 {
1460                                     k = find_inst(fw, isBL, k+1, 6);
1461                                     if (k == -1)
1462                                         break;
1463                                     l = idxFollowBranch(fw,k,0x01000001);
1464                                 }
1465                                 if ( (fwval(fw,l)==0xe52de004) &&
1466                                      (fwval(fw,l+4)==0xe49df004) &&
1467                                      isBL(fw,l+1) )
1468                                 {
1469                                     void add_func_name(char*, uint32_t, char*);
1470                                     add_func_name("j_GetBaseSv", idx2adr(fw,l), "");
1471                                     k = idxFollowBranch(fw,l+1,0x01000001);
1472                                     fwAddMatch(fw,idx2adr(fw,k),32,0,122);
1473                                     return 1;
1474                                 }
1475                             }
1476                         }
1477                     }
1478                 }
1479             }
1480         }
1481         s1 = find_nxt_str_ref(fw, sadr, s1+1);
1482     }
1483 
1484     return 0;
1485 }
1486 
1487 // get GetCurrentDriveBaseSvValue for old vx
1488 int find_GetCurrentDriveBaseSvValue(firmware *fw)
1489 {
1490     int f1 = get_saved_sig(fw,"ExpCtrlTool.OneShotAE_FW");
1491     if(f1 < 0)
1492         return 0;
1493 
1494     f1 = adr2idx(fw, func_names[f1].val);
1495     int blcnt, i;
1496     // expect 3rd bl
1497     for(i=0, blcnt=0; i<12 && blcnt < 3; i++) {
1498         if(!isBL(fw,f1+i)) {
1499             continue;
1500         }
1501         blcnt++;
1502         if(blcnt == 3) {
1503             int f2 = idxFollowBranch(fw,f1+i,0x01000001);
1504             fwAddMatch(fw,idx2adr(fw,f2),32,0,122);
1505             return 1;
1506         }
1507     }
1508     return 0;
1509 }
1510 
1511 int find_Remove(firmware *fw)
1512 {
1513     int f1 = get_saved_sig(fw,"Close");
1514     if(f1 < 0)
1515         return 0;
1516 
1517     f1 = adr2idx(fw, func_names[f1].val);
1518     int f2, blcnt, i;
1519     f2 = find_str_ref(fw,"File Write Fail.");
1520     if(f2 == -1)
1521         return 0;
1522     // looking for 1st bl after Close
1523     for(i=1, blcnt=0; i<8 && blcnt < 2; i++) {
1524         if(!isBL(fw,f2+i)) {
1525             continue;
1526         }
1527         // is it Close?
1528         if(idxFollowBranch(fw,f2+i,0x01000001) == f1) {
1529             blcnt++;
1530             continue;
1531         }
1532         if (blcnt == 1) {
1533             f2 = idxFollowBranch(fw,f2+i,0x01000001);
1534             fwAddMatch(fw,idx2adr(fw,f2),32,0,122);
1535             return 1;
1536         }
1537     }
1538     return 0;
1539 }
1540 
1541 //------------------------------------------------------------------------------------------------------------
1542 
1543 // Data for matching the '_log' function
1544 uint32_t log_test[] = {
1545     0x1526E50E, 0x3FDBCB7B, 0
1546 };
1547 
1548 // Data for matching 'Fut' functions
1549 uint32_t DeleteDirectory_Fut_test[] = { 0x09400017 };
1550 uint32_t MakeDirectory_Fut_test[]   = { 0x09400015 };
1551 uint32_t RenameFile_Fut_test[]      = { 0x09400013 };
1552 
1553 //------------------------------------------------------------------------------------------------------------
1554 
1555 // Signature matching data
1556 string_sig string_sigs[] =
1557 {
1558     // Same as previously found eventproc - do these first
1559     {20, "AllocateMemory", "AllocateMemory_FW", 1 },
1560     {20, "Close", "Close_FW", 1 },
1561     {20, "CreateCountingSemaphore", "CreateCountingSemaphore_FW", 1 },
1562     {20, "CreateTask", "CreateTask_FW", 1 },
1563     {20, "DeleteSemaphore", "DeleteSemaphore_FW", 1 },
1564     {20, "DispCon_ShowBitmapColorBar", "DispCon_ShowBitmapColorBar_FW", 1 },
1565     {20, "ExitTask", "ExitTask_FW", 1 },
1566     {20, "Fclose_Fut", "Fclose_Fut_FW", 1 },
1567     {20, "Fopen_Fut", "Fopen_Fut_FW", 1 },
1568     {20, "Fread_Fut", "Fread_Fut_FW", 1 },
1569     {20, "FreeMemory", "FreeMemory_FW", 1 },
1570     {20, "Fseek_Fut", "Fseek_Fut_FW", 1 },
1571     {20, "Fwrite_Fut", "Fwrite_Fut_FW", 1 },
1572     {20, "GetSDProtect", "GetSDProtect_FW", 1 },
1573     //{20, "GetSystemTime", "GetSystemTime_FW", 1 },
1574     {20, "GetCurrentAvValue", "GetCurrentAvValue_FW", 1 },
1575     {20, "GetCurrentShutterSpeed", "GetCurrentShutterSpeed_FW", 1 },
1576     {20, "GetUsableMaxAv", "GetUsableMaxAv_FW", 1 },
1577     {20, "GetUsableMinAv", "GetUsableMinAv_FW", 1 },
1578     {20, "GetOpticalTemperature", "GetOpticalTemperature_FW", 1 },
1579     {20, "GetVRAMHPixelsSize", "GetVRAMHPixelsSize_FW", 1 },
1580     {20, "GetVRAMVPixelsSize", "GetVRAMVPixelsSize_FW", 1 },
1581     {20, "GetZoomLensCurrentPoint", "GetZoomLensCurrentPoint_FW", 1 },
1582     {20, "GiveSemaphore", "GiveSemaphore_FW", 1 },
1583     {20, "GUISrv_StartGUISystem", "GUISrv_StartGUISystem_FW", 1 },
1584     {20, "LEDDrive", "LEDDrive_FW", 1 },
1585     {20, "LockMainPower", "LockMainPower_FW", 1 },
1586     //{20, "lseek", "Lseek_FW", 1 },
1587     {20, "Lseek", "Lseek_FW", 1 },
1588     {20, "MoveIrisWithAv", "MoveIrisWithAv_FW", 1 },
1589     {20, "MoveZoomLensWithPoint", "MoveZoomLensWithPoint_FW", 1 },
1590     {20, "memcmp", "memcmp_FW", 1 },
1591     {20, "memcpy", "memcpy_FW", 1 },
1592     {20, "memset", "memset_FW", 1 },
1593     {20, "NewTaskShell", "NewTaskShell_FW", 1 },
1594     {20, "NR_GetDarkSubType", "NR_GetDarkSubType_FW", 1 },
1595     {20, "NR_SetDarkSubType", "NR_SetDarkSubType_FW", 1 },
1596     {20, "Open", "Open_FW", 1 },
1597     {20, "PostLogicalEventForNotPowerType", "PostLogicalEventForNotPowerType_FW", 1 },
1598     {20, "PostLogicalEventToUI", "PostLogicalEventToUI_FW", 1 },
1599     {20, "PT_MoveDigitalZoomToWide", "PT_MoveDigitalZoomToWide_FW", 1 },
1600     {20, "PT_MoveOpticalZoomAt", "PT_MoveOpticalZoomAt_FW", 1 },
1601     {20, "Read", "Read_FW", 1 },
1602     {20, "RefreshPhysicalScreen", "RefreshPhysicalScreen_FW", 1 },
1603     {20, "ResetFocusLens", "ResetFocusLens_FW", 1 },
1604     {20, "ResetZoomLens", "ResetZoomLens_FW", 1 },
1605     {20, "SavePaletteData", "SavePaletteData_FW", 1 },
1606     {20, "SetAutoShutdownTime", "SetAutoShutdownTime_FW", 1 },
1607     {20, "SetCurrentCaptureModeType", "SetCurrentCaptureModeType_FW", 1 },
1608     {20, "SetDate", "SetDate_FW", 1 },
1609     {20, "SetScriptMode", "SetScriptMode_FW", 1 },
1610     {20, "SleepTask", "SleepTask_FW", 1 },
1611     {20, "strcmp", "j_strcmp_FW", 0 },
1612     {20, "strcmp", "strcmp_FW", 0 },
1613     {20, "strcpy", "strcpy_FW", 1 },
1614     {20, "strlen", "strlen_FW", 1 },
1615     {20, "StartRecModeMenu", "StartRecModeMenu_FW", 1 },
1616     //{20, "TakeSemaphore", "TakeSemaphore_FW", 1 },
1617     {20, "UIFS_WriteFirmInfoToFile", "UIFS_WriteFirmInfoToFile_FW", 1 },
1618     {20, "UnlockMainPower", "UnlockMainPower_FW", 1 },
1619     {20, "VbattGet", "VbattGet_FW", 1 },
1620     {20, "write", "Write_FW", 1 },
1621     {20, "Write", "Write_FW", 1 },
1622     {20, "task_CaptSeq", "task_CaptSeqTask", 1 },
1623     {20, "task_ExpDrv", "task_ExpDrvTask", 1 },
1624     {20, "task_FileWrite", "task_FileWriteTask", 1 },
1625     {20, "task_RotaryEncoder", "task_JogDial", 1 },
1626     {20, "task_RotaryEncoder", "task_RotarySw", 1 },
1627     {20, "task_SwitchCheck", "task_SwitchCheckTask", 1 },
1628     {20, "IsControlEventActive", "IsControlEventActive_FW", 0 },
1629     {20, "GetLogicalEventName", "ShowLogicalEventName_FW", 0x01000002 },
1630     {20, "TurnOnDisplay", "DispCon_TurnOnDisplay_FW", 0 },
1631     {20, "TurnOffDisplay", "DispCon_TurnOffDisplay_FW", 0 },
1632     {20, "UnlockAF", "PT_UnlockAF_FW", 0x01000002 }, // newer Vx
1633     {20, "DoAFLock", "PT_DoAFLock_FW", 0x01000002 }, // newer Vx
1634     {20, "DoAFLock", "DoAFLock_FW", 1 },
1635     {20, "UnlockAF", "UnlockAF_FW", 1 },
1636     {20, "UnlockAE", "PT_UnlockAE_FW", 0x01000002 }, // newer Vx
1637     {20, "DoAELock", "PT_DoAELock_FW", 0x01000002 }, // newer Vx
1638     {20, "DoAELock", "DoAELock_FW", 1 },
1639     {20, "UnlockAE", "UnlockAE_FW", 1 },
1640     {20, "MFOn", "MFOn_FW", 1 },
1641     {20, "MFOff", "MFOff_FW", 1 },
1642     {20, "GetAdChValue", "GetAdChValue_FW", 0 },
1643     {20, "HwOcReadICAPCounter", "GetCurrentMachineTime", 3 },
1644     {20, "get_nd_value", "NdActuator.GetNdFilterDeltaEvAdjustValue_FW", 0 }, // old vx
1645     {20, "get_current_nd_value", "NdActuator.GetNdFilterDeltaEv_FW", 0 }, // old vx
1646     {20, "MenuIn", "MenuIn_FW", 1 },
1647     {20, "MenuOut", "MenuOut_FW", 1 },
1648 
1649     { 1, "ExportToEventProcedure_FW", "ExportToEventProcedure", 1 },
1650     { 1, "AllocateMemory", "AllocateMemory", 1 },
1651     { 1, "Close", "Close", 1 },
1652     { 1, "CreateTask", "CreateTask", 1 },
1653     { 1, "DoAFLock", "PT_DoAFLock", 0x01000002 },
1654     { 1, "ExitTask", "ExitTask", 1 },
1655     { 1, "exmem_alloc", "ExMem.AllocCacheable", 5 },
1656     { 1, "exmem_free", "ExMem.FreeCacheable", 0x01000003 },
1657     { 1, "exmem_ualloc", "ExMem.AllocUncacheable", 5 },
1658     { 1, "exmem_ufree", "ExMem.FreeUncacheable", 0x01000003 },
1659     { 1, "Fclose_Fut", "Fclose_Fut", 1 },
1660     { 1, "Feof_Fut", "Feof_Fut", 1 },
1661     { 1, "Fflush_Fut", "Fflush_Fut", 1 },
1662     { 1, "Fgets_Fut", "Fgets_Fut", 1 },
1663     { 1, "Fopen_Fut", "Fopen_Fut", 1 },
1664     { 1, "Fread_Fut", "Fread_Fut", 1 },
1665     { 1, "FreeMemory", "FreeMemory", 1 },
1666     { 1, "Fseek_Fut", "Fseek_Fut", 1 },
1667     { 1, "Fwrite_Fut", "Fwrite_Fut", 1 },
1668     { 1, "GetParameterData", "PTM_RestoreUIProperty", 0xF0000004 },
1669     { 1, "GetPropertyCase", "PT_GetPropertyCaseString", 1 },
1670     { 1, "GetPropertyCase", "PT_GetPropertyCaseInt", 0x0100000F },
1671     { 1, "GetPropertyCase", "GetPropertyCase", 0x0100000F },
1672     { 1, "GetSDProtect", "GetSDProtect", 1 },
1673     { 1, "GetSystemTime", "GetSystemTime", 1 },
1674     { 1, "LEDDrive", "LEDDrive", 1 },
1675     { 1, "LockMainPower", "LockMainPower", 1 },
1676     { 1, "Lseek", "Lseek", 1 },
1677     { 1, "lseek", "Lseek", 1 },
1678     { 1, "memcpy", "memcpy", 1 },
1679     { 1, "memcmp", "memcmp", 1 },
1680     { 1, "memset", "memset", 1 },
1681     { 1, "NewTaskShell", "NewTaskShell", 1 },
1682     { 1, "Open", "Open", 1 },
1683     { 1, "PostLogicalEventToUI", "PostLogicalEventToUI", 1 },
1684     { 1, "PostLogicalEventForNotPowerType", "PostLogicalEventForNotPowerType", 1 },
1685     { 1, "Read", "Read", 1 },
1686     { 1, "read", "Read", 1 },
1687     { 1, "RefreshPhysicalScreen", "RefreshPhysicalScreen", 1 },
1688     { 1, "SetAutoShutdownTime", "SetAutoShutdownTime", 1 },
1689     { 1, "SetCurrentCaptureModeType", "SetCurrentCaptureModeType", 1 },
1690     { 1, "SetLogicalEventActive", "UiEvnt_SetLogicalEventActive", 1 },
1691     { 1, "SetParameterData", "PTM_BackupUIProperty", 1 },
1692     { 1, "SetPropertyCase", "PT_SetPropertyCaseInt", 0x01000003 },
1693     { 1, "SetPropertyCase", "SetPropertyCase", 0x01000004 },
1694     { 1, "SetScriptMode", "SetScriptMode", 1 },
1695     { 1, "SleepTask", "SleepTask", 1 },
1696     { 1, "strcmp", "strcmp", 0 },
1697     { 1, "strcpy", "strcpy", 1 },
1698     { 1, "strlen", "strlen", 1 },
1699     { 1, "strtol", "atol", 3 },
1700     { 1, "TakeSemaphore", "TakeSemaphore", 1 },
1701     { 1, "UIFS_WriteFirmInfoToFile", "UIFS_WriteFirmInfoToFile", 1 },
1702     //{ 1, "UnlockAF", "PT_UnlockAF", 0x01000002 },
1703     { 1, "UnlockMainPower", "UnlockMainPower", 1 },
1704     { 1, "VbattGet", "VbattGet", 1 },
1705     { 1, "Write", "Write", 1 },
1706     { 1, "write", "Write", 1 },
1707     { 1, "GUISrv_StartGUISystem", "GUISrv_StartGUISystem", 1 },
1708 
1709     { 2, "GetBatteryTemperature", "GetBatteryTemperature", 1 },
1710     { 2, "GetCCDTemperature", "GetCCDTemperature", 1 },
1711     { 2, "GetOpticalTemperature", "GetOpticalTemperature", 1 },
1712     //{ 2, "GetFocusLensSubjectDistance", "GetCurrentTargetDistance", 1 },
1713     { 2, "GetZoomLensCurrentPoint", "GetZoomLensCurrentPoint", 1 },
1714     { 2, "GetZoomLensCurrentPosition", "GetZoomLensCurrentPosition", 1 },
1715     { 2, "MoveFocusLensToDistance", "MoveFocusLensToDistance", 1 },
1716     { 2, "MoveZoomLensWithPoint", "MoveZoomLensWithPoint", 1 },
1717     //{ 2, "GetCurrentAvValue", "GetCurrentAvValue", 1 },
1718     { 2, "PT_MoveOpticalZoomAt", "PT_MoveOpticalZoomAt", 1 },
1719     //{ 2, "PT_MoveOpticalZoomAt", "SS.MoveOpticalZoomAt", 1 },
1720     { 2, "PT_MoveDigitalZoomToWide", "PT_MoveDigitalZoomToWide", 1 },
1721     //{ 2, "PT_MoveDigitalZoomToWide", "SS.MoveDigitalZoomToWide", 1 },
1722     { 2, "MoveIrisWithAv", "MoveIrisWithAv", 1},
1723     //{ 2, "PutInNdFilter", "TurnOnNdFilter", 1 },
1724     //{ 2, "PutOutNdFilter", "TurnOffNdFilter", 1 },
1725     //{ 2, "PutInNdFilter", "PutInNdFilter", 1 },
1726     //{ 2, "PutOutNdFilter", "PutOutNdFilter", 1 },
1727     //{ 2, "IsStrobeChargeCompleted", "EF.IsChargeFull", 1 },
1728     { 2, "GetPropertyCase", "PT_GetPropertyCaseInt", 0x01000012 },
1729     { 2, "SetPropertyCase", "PT_SetPropertyCaseInt", 0x01000008 },
1730     { 2, "SetPropertyCase", "PT_SetPropertyCaseInt", 0x01000009 },
1731     //{ 2, "UnlockAF", "PT_UnlockAF", 0x01000002 },
1732     //{ 2, "UnlockAF", "SS.UnlockAF", 0x01000002 },
1733     //{ 2, "DoAFLock", "PT_DoAFLock", 0x01000002 },
1734     //{ 2, "DoAFLock", "SS.DoAFLock", 0x01000002 },
1735     { 2, "GetSystemTime", "PT_GetSystemTime", 0x01000003 },
1736     { 2, "PT_PlaySound", "PT_PlaySound", 0x01000005 },
1737     { 2, "StartRecModeMenu", "StartRecModeMenu", 1 },
1738     { 2, "GetSDProtect", "GetSDProtect", 1 },
1739     { 2, "DispCon_ShowBitmapColorBar", "DispCon_ShowBitmapColorBar", 1 },
1740     { 2, "SetAE_ShutterSpeed", "SetAE_ShutterSpeed", 1 },
1741     { 2, "ResetZoomLens", "ResetZoomLens", 1 },
1742     { 2, "ResetFocusLens", "ResetFocusLens", 1 },
1743     { 2, "NR_GetDarkSubType", "NR_GetDarkSubType", 1 },
1744     //{ 2, "NR_GetDarkSubType", "NRTBL.GetDarkSubType", 1 },
1745     { 2, "NR_SetDarkSubType", "NR_SetDarkSubType", 1 },
1746     //{ 2, "NR_SetDarkSubType", "NRTBL.SetDarkSubType", 1 },
1747     { 2, "SavePaletteData", "SavePaletteData", 1 },
1748     { 2, "GetVRAMHPixelsSize", "GetVRAMHPixelsSize", 1 },
1749     { 2, "GetVRAMVPixelsSize", "GetVRAMVPixelsSize", 1 },
1750     { 2, "EngDrvIn", "EngDrvIn", 4 },
1751     { 2, "EngDrvOut", "EngDrvOut", 0x01000005 },
1752     { 2, "EngDrvRead", "EngDrvRead", 4 },
1753     { 2, "EngDrvBits", "EngDrvBits", 0x01000006 },
1754     { 2, "exmem_alloc", "ExMem.AllocCacheable", 6 },
1755     { 2, "exmem_free", "ExMem.FreeCacheable", 0x01000003 },
1756     { 2, "exmem_ualloc", "ExMem.AllocUncacheable", 6 },
1757     { 2, "exmem_ufree", "ExMem.FreeUncacheable", 0x01000003 },
1758 
1759     { 2, "PTM_GetCurrentItem", "PTM_GetCurrentItem", 0x01000003 },
1760     { 2, "PTM_SetCurrentItem", "PTM_SetCurrentItem", 8 },
1761     { 2, "PTM_NextItem", "PTM_NextItem", 0x01000003 },
1762     { 2, "PTM_PrevItem", "PTM_PrevItem", 0x01000003 },
1763     { 2, "PTM_SetPropertyEnable", "PTM_SetProprietyEnable", 8 },
1764 
1765     { 3, "AllocateMemory", "AllocateMemory", 1 },
1766     { 3, "FreeMemory", "FreeMemory", 1 },
1767     { 3, "PostLogicalEventToUI", "PostLogicalEventToUI", 1 },
1768     { 3, "PostLogicalEventForNotPowerType", "PostLogicalEventForNotPowerType", 1 },
1769     { 3, "LockMainPower", "LockMainPower", 1 },
1770     { 3, "UnlockMainPower", "UnlockMainPower", 1 },
1771     { 3, "SetAutoShutdownTime", "SetAutoShutdownTime", 1 },
1772     { 3, "NewTaskShell", "NewTaskShell", 1 },
1773     { 3, "VbattGet", "VbattGet", 1 },
1774     { 3, "LEDDrive", "LEDDrive", 1 },
1775     { 3, "SetPropertyCase", "PT_SetPropertyCaseInt", 0x01000003 },
1776     //{ 3, "UnlockAF", "PT_UnlockAF", 0x01000002 },
1777     //{ 3, "DoAFLock", "PT_DoAFLock", 0x01000002 },
1778     { 3, "UIFS_WriteFirmInfoToFile", "UIFS_WriteFirmInfoToFile", 1 },
1779     { 3, "PT_MoveOpticalZoomAt", "PT_MoveOpticalZoomAt", 1 },
1780     { 3, "PT_MoveDigitalZoomToWide", "PT_MoveDigitalZoomToWide", 1 },
1781     { 3, "PT_PlaySound", "PT_PlaySound", 1 },
1782     { 3, "exmem_alloc", "ExMem.AllocCacheable", 4 },
1783     { 3, "exmem_free", "ExMem.FreeCacheable", 0x01000003 },
1784     { 3, "GetSDProtect", "GetSDProtect", 1 },
1785 
1786     { 4, "TurnOnBackLight", "TurnOnBackLight", 1 },
1787     { 4, "TurnOffBackLight", "TurnOffBackLight", 1 },
1788     { 4, "EnterToCompensationEVF", "SSAPI::EnterToCompensationEVF", 1 },
1789     { 4, "EnterToCompensationEVF", "ExpComp On", 1 },
1790     { 4, "EnterToCompensationEVF", "ExpOn", 1 },
1791     { 4, "ExitFromCompensationEVF", "SSAPI::ExitFromCompensationEVF", 1 },
1792     { 4, "ExitFromCompensationEVF", "ExpComp Off", 1 },
1793     { 4, "ExitFromCompensationEVF", "ExpOff", 1 },
1794     //{ 4, "PB2Rec", "AC:PB2Rec", 1 },
1795     //{ 4, "PB2Rec", "AC:PB2Rec", 6 },
1796     //{ 4, "PB2Rec", "AC:PB2Rec", 11 },
1797     //{ 4, "Rec2PB", "AC:Rec2PB", 1 },
1798     { 4, "RefreshPhysicalScreen", "ScreenUnLock", 1 },
1799     { 4, "RefreshPhysicalScreen", "ScreenUnLock", 7 },
1800     { 4, "RefreshPhysicalScreen", "ScreenUnLock", 15 },
1801     { 4, "RefreshPhysicalScreen", "Reduce ScreenUnLock", 5 },
1802     { 4, "RefreshPhysicalScreen", "Window:IneffectiveLockPhysicalScreen", 8 },
1803     { 4, "UnsetZoomForMovie", "ZoomCon_UnsetZoomForMovie", 1 },
1804     { 4, "ExpCtrlTool_StopContiAE", "StopContiAE", 9 },
1805     { 4, "ExpCtrlTool_StopContiAE", "StopContiAE", 10 },
1806     { 4, "ExpCtrlTool_StartContiAE", "StartContiAE", 9 },
1807     { 4, "ExpCtrlTool_StartContiAE", "StartContiAE", 10 },
1808     { 4, "ExecuteEventProcedure", "Can not Execute ", 14 },
1809 
1810     { 5, "UIFS_WriteFirmInfoToFile", "UIFS_WriteFirmInfoToFile", 1 },
1811     { 5, "CreateTask", "CreateTask", 1 },
1812     //{ 5, "hook_CreateTask", "CreateTask", 1 },
1813     { 5, "ExitTask", "ExitTask", 1 },
1814     { 5, "SleepTask", "SleepTask", 1 },
1815     { 5, "DeleteSemaphore", "DeleteSemaphore", 1 },
1816     { 5, "CreateCountingSemaphore", "CreateCountingSemaphore", 1 },
1817     //                                                                   ???
1818     { 5, "UpdateMBROnFlash", "MakeBootDisk", 0x01000003,                  11 },
1819     { 5, "MakeSDCardBootable", "MakeBootDisk", 0x01000003,                 1 },
1820 
1821     //{ 6, "Restart", "Bye", 0 },
1822     { 6, "GetImageFolder", "GetCameraObjectTmpPath ERROR[ID:%lx] [TRY:%lx]\n", 0 },
1823     { 6, "reboot_fw_update", "FirmUpgrade.c", 0 },
1824 
1825     { 7, "CreateTaskStrictly", "FileWriteTask", 0x01000001 },
1826     { 7, "RegisterInterruptHandler", "SdDmaInt", 0x01000001 },
1827     { 7, "LogCameraEvent", "BufAccBeep", 0x01000001 },
1828     { 7, "LogCameraEvent", "MyCamFunc_PlaySound_MYCAM_COVER_OPEN", 0x01000001 },
1829     { 7, "exmem_assert", "Type < MAX_NUM_OF_EXMEMORY_TYPE", 0x01000001 },
1830     { 7, "GetCurrentDriveBaseSvValue", "KeepPreviousExposureWithProgress", 0x01000003 },
1831 
1832     { 8, "WriteSDCard", "Mounter.c", 0 },
1833 
1834     // Ensure ordering in func_names is correct for dependencies here
1835     //                                                                   ???
1836     //{ 9, "kbd_p1_f", "task_PhySw", 0,                                      5 },
1837     //{ 9, "kbd_p2_f", "task_PhySw", 0,                                      7 },
1838     { 9, "kbd_read_keys", "kbd_p1_f", 0,                                   2 },
1839     { 9, "kbd_p1_f_cont", "kbd_p1_f", -1,                                  3 },
1840     //{ 9, "kbd_read_keys_r2", "kbd_read_keys", 0,                          11 },
1841     { 9, "GetKbdState", "kbd_read_keys", 0,                                8 },
1842     { 9, "GetKbdState", "kbd_read_keys", 0,                                9 },
1843     //{ 9, "strtolx", "strtol", 0,                                           1 },
1844     //{ 9, "mkdir", "MakeDirectory_Fut", 0x01000001,                        17 },
1845     //{ 9, "mkdir", "MakeDirectory_Fut", 0x01000002,                        17 },
1846     //{ 9, "time", "MakeDirectory_Fut", 0,                                  12 },
1847     { 9, "stat", "_uartr_req", 0,                                          0 },
1848     //{ 9, "PostMessageQueue", "PostMessageQueueStrictly", 0,                3 },
1849     //{ 9, "WaitForAnyEventFlag", "WaitForAnyEventFlagStrictly", 0,          3 },
1850     //{ 9, "WaitForAllEventFlag", "WaitForAllEventFlagStrictly", 0,          3 },
1851     //{ 9, "CreateMessageQueue", "CreateMessageQueueStrictly", 0,            1 },
1852     { 9, "CreateRecursiveLock", "CreateRecursiveLockStrictly", 0,       1 },
1853     { 9, "CreateRecursiveLock", "CreateRecursiveLockStrictly", 0,       6 },    // old vx
1854     { 9, "CreateEventFlag", "CreateEventFlagStrictly", 0,               1 },
1855     { 9, "_GetSystemTime", "PT_GetSystemTime", 0,                       3 },
1856     { 9, "close", "Close", 0,                                              2 },
1857     { 9, "open", "Open", 0,                                                3 },
1858     { 9, "open", "Open", 0,                                                3 },
1859     { 9, "malloc_alt", "wrapped_malloc", 0,                                2 },
1860     { 9, "DisableDispatch_low", "DisableDispatch", 0,                      6 },
1861 
1862     //                                                                   ???
1863     { 11, "err_init_task", "\n-- %s() error in init_task() --", 0,         2 },
1864     { 11, "set_control_event", "Button:0x%08X:%s", 0x01000001,            14 },
1865     { 11, "set_control_event", "Button:0x%08X:%s", 0xf1000001,            15 },
1866     { 11, "set_control_event", "Button:0x%08X:%s", 0x01000001,            19 },
1867     { 11, "set_control_event", "Button:0x%08X:%s", 0x01000001,            20 },
1868     { 11, "_log", (char*)log_test, 0x01000001,                             1 },
1869     { 11, "_uartr_req", "A/uartr.req", 0,                                  3 },
1870 
1871     //                                                                   ???
1872     //{ 12, "DeleteFile_Fut", "DeleteFile_Fut", 1,                        0x38 },
1873     //{ 12, "AllocateUncacheableMemory", "AllocateUncacheableMemory", 1,  0x2C },
1874     //{ 12, "FreeUncacheableMemory", "FreeUncacheableMemory", 1,          0x30 },
1875     //{ 12, "free", "free", 1,                                            0x28 },
1876     //{ 12, "malloc", "malloc", 0x01000003,                               0x24 },
1877     //{ 12, "TakeSemaphore", "TakeSemaphore", 1,                          0x14 },
1878     //{ 12, "GiveSemaphore", "GiveSemaphore", 1,                          0x18 },
1879     //{ 12, "ClearEventFlag", "ClearEventFlag", 1,                        0x04 },
1880     //{ 12, "SetEventFlag", "SetEventFlag", 1,                            0x08 },
1881     //{ 12, "WaitForAnyEventFlag", "WaitForAnyEventFlag", 1,              0x0c },
1882     //{ 12, "WaitForAllEventFlag", "WaitForAllEventFlag", 1,              0x10 },
1883 
1884     { 13, "strftime", "Sunday", 1 },
1885 
1886     { 15, "LocalTime", "%04d:%02d:%02d %02d:%02d:%02d", 0x01000001 },
1887     { 15, "GetMemInfo", "Malloc Information\n", 0x01000001 },
1888     { 15, "GetMemInfo", "Malloc Information (%s type)\n", 0x01000001 },
1889     { 15, "vsprintf", "\nCPrintf Size Over!!", 0x01000001 },
1890     //{ 15, "ReadFastDir", "ReadFast_ERROR\n", 0x01000001 },
1891     //{ 15, "OpenFastDir", "OpenFastDir_ERROR\n", 0x01000001 },
1892     { 15, "realloc", "fatal error - scanner input buffer overflow", 0x01000001 },
1893     { 15, "CreateBinarySemaphore", "SdPower.c", 0x01000001 },
1894     { 15, "CreateBinarySemaphore", "DoWBForEVFOnce CreateBinarySemaphore Error\r\n", 0x01000001 }, // old Vx
1895     { 15, "CreateBinarySemaphore", "DoWBForEVFOnce CreateBinarySemaphore Error\n", 0x01000001 }, // old Vx
1896     //                                                                           Vx
1897     { 15, "SetHPTimerAfterTimeout", "FrameRateGenerator.c", 0x01000001,          0x0008 },
1898     { 15, "wrapped_malloc", "\n malloc error \n", 0x01000001,                    0x0010 },
1899     { 15, "IsStrobeChargeCompleted", "\r\nCaptSeq::ChargeNotCompleted!!", 0x01000001 }, // ixus30, 40
1900     { 15, "get_resource_pointer", "Not found icon resource.\r\n", 0x01000001,    0x0008 },
1901     { 15, "get_nd_value", "IrisSpecification.c", 0x01000001,                     0x0014 },
1902     { 15, "ImagerActivate", "Fail ImagerActivate(ErrorCode:%x)\r", 0x01000001,   0x0007 },
1903     { 15, "DoMovieFrameCapture", "DoMovieFrameCapture executed.",  0x01000001,   0x0007 },
1904     { 15, "EnableDispatch_low", "EnableDispatch : dispatch counter unserflow", 0x01000001,   0x0003 },
1905 
1906     { 16, "DeleteDirectory_Fut", (char*)DeleteDirectory_Fut_test, 0x01000001 },
1907     { 16, "MakeDirectory_Fut", (char*)MakeDirectory_Fut_test, 0x01000001 },
1908     { 16, "RenameFile_Fut", (char*)RenameFile_Fut_test, 0x01000001 },
1909 
1910     { 17, "ScreenLock", "StartRecModeMenu", 0 },
1911     { 17, "ScreenUnlock", "StartRecModeMenu", 0 },
1912 
1913     // Ensure ordering in func_names is correct for dependencies here
1914     //                                                                           Vx
1915     { 19, "CreateMessageQueueStrictly", "CreateTaskStrictly", 0,                 0x0210 },
1916     { 19, "CreateMessageQueueStrictly", "CreateTaskStrictly", 0,                 0x0720 }, // old vx
1917     { 19, "CreateEventFlagStrictly", "CreateMessageQueueStrictly", 0,            0x010b },
1918     { 19, "CreateEventFlagStrictly", "CreateMessageQueueStrictly", 0,            0x0619 }, // old vx
1919     { 19, "CreateBinarySemaphoreStrictly", "CreateEventFlagStrictly", 0,         0x010b },
1920     { 19, "CreateBinarySemaphoreStrictly", "CreateEventFlagStrictly", 0,         0x081b }, // old vx
1921     { 19, "CreateCountingSemaphoreStrictly", "CreateBinarySemaphoreStrictly", 0, 0x010b },
1922     { 19, "CreateCountingSemaphoreStrictly", "CreateBinarySemaphoreStrictly", 0, 0x081b }, // old vx
1923     { 19, "CreateRecursiveLockStrictly", "CreateCountingSemaphoreStrictly", 0,   0x010b },
1924     { 19, "CreateRecursiveLockStrictly", "CreateCountingSemaphoreStrictly", 0,   0x071a }, // old vx
1925     //{ 19, "PostMessageQueue", "TryReceiveMessageQueue", 0,                       0x091f },
1926     //{ 19, "DeleteMessageQueue", "CreateMessageQueue", 0,                         0x1021 },
1927     //{ 19, "ReceiveMessageQueue", "DeleteMessageQueue", 0,                        0x1024 },
1928     //{ 19, "TryReceiveMessageQueue", "ReceiveMessageQueue", 0,                    0x002b },
1929     { 19, "TryPostMessageQueue", "PostMessageQueue", 0,                          0x058a },
1930     { 19, "GetNumberOfPostedMessages", "TryPostMessageQueue", 0,                 0x004b },
1931     { 19, "DeleteRecursiveLock", "CreateRecursiveLock", 0,                       0x0247 },
1932     { 19, "AcquireRecursiveLock", "DeleteRecursiveLock", 0,                      0x0136 }, // old vx
1933     { 19, "AcquireRecursiveLock", "DeleteRecursiveLock", 0,                      0x0026 }, // new vx
1934     { 19, "ReleaseRecursiveLock", "AcquireRecursiveLock", 0,                     0x154a }, // old vx
1935     { 19, "ReleaseRecursiveLock", "AcquireRecursiveLock", 0,                     0x002a }, // new vx
1936     { 19, "GetEventFlagValue", "ClearEventFlag", 0,                              0x0014 },
1937     //{ 19, "DeleteEventFlag", "CreateEventFlag", 0,                               0x0016 },
1938     { 19, "CheckAnyEventFlag", "CheckAllEventFlag", 0,                          -0x0004 },
1939     { 19, "CheckAllEventFlag", "WaitForEventFlag", 0,                           -0x1028 },
1940     { 19, "WaitForAnyEventFlag", "WaitForEventFlag", 0,                          0x0569 },
1941     { 19, "WaitForAllEventFlag", "WaitForAnyEventFlag", 0,                       0x1004 },
1942     { 19, "ClearEventFlag", "SetEventFlag", 0,                                   0x0167 }, // new vx
1943     { 19, "ClearEventFlag", "SetEventFlag", 0,                                   0x0165 }, // old vx
1944     { 19, "SetEventFlag", "WaitForAllEventFlag", 0,                              0x1004 },
1945     { 19, "TryTakeSemaphore", "GiveSemaphore", 0,                               -0x0619 }, // old vx
1946     { 19, "TryTakeSemaphore", "GiveSemaphore", 0,                               -0x071c }, // new vx
1947     { 19, "GetSemaphoreValue", "GiveSemaphore", 0,                               0x0035 }, // old vx
1948     { 19, "GetSemaphoreValue", "GiveSemaphore", 0,                               0x013b }, // new vx
1949     { 19, "SetHPTimerAfterNow", "SetHPTimerAfterTimeout", 0,                    -0x0223 },
1950     { 19, "CancelHPTimer", "SetHPTimerAfterTimeout", 0,                          0x09fa },
1951     { 19, "SetTimerAfter", "_GetSystemTime", 0,                                  0x0355 },
1952     { 19, "SetTimerWhen", "SetTimerAfter", 0,                                    0x0327 },
1953     { 19, "CancelTimer", "SetTimerWhen", 0,                                      0x026d }, // older vx
1954     { 19, "CancelTimer", "SetTimerWhen", 0,                                      0x021e }, // newer vx (no unused functions inbetween)
1955 
1956     { 19, "UnregisterInterruptHandler", "RegisterInterruptHandler", 0,           0x0909 },
1957     { 19, "GetSRAndDisableInterrupt", "UnregisterInterruptHandler", 0,           0x0f06 },
1958     { 19, "SetSR", "GetSRAndDisableInterrupt", 0,                                0x1003 },
1959     { 19, "EnableInterrupt", "SetSR", 0,                                         0x1508 },
1960     //{ 19, "UnregisterInterruptHandler", "RegisterInterruptHandler", 0,           0x0009 },
1961     //{ 19, "GetSRAndDisableInterrupt", "UnregisterInterruptHandler", 0,           0x0006 },
1962     //{ 19, "SetSR", "UnregisterInterruptHandler", 0,                              0x1007 },
1963     //{ 19, "EnableInterrupt", "UnregisterInterruptHandler", 0,                    0x170f },
1964     { 19, "GetDrive_TotalClusters", "GetDrive_FreeClusters", 0,                 -0x120f },
1965     { 19, "GetDrive_TotalClusters", "GetDrive_FreeClusters", 0,                 -0x130f }, // s80
1966     { 19, "GetDrive_TotalClusters", "GetDrive_FreeClusters", 0,                 -0x120e }, // ixus950
1967     { 19, "GetDrive_TotalClusters", "GetDrive_FreeClusters", 0,                 -0x1310 }, // old vx
1968     { 19, "GetDrive_ClusterSize", "GetDrive_TotalClusters", 0,                  -0x020f },
1969     { 19, "GetDrive_ClusterSize", "GetDrive_TotalClusters", 0,                  -0x0217 }, // s80
1970     { 19, "GetDrive_ClusterSize", "GetDrive_TotalClusters", 0,                  -0x0310 }, // old vx
1971 
1972     { 21, "add_ptp_handler", (char*)find_add_ptp_handler, 0 },
1973     //{ 21, "apex2us", (char*)find_apex2us, 0 },
1974     { 21, "mkdir", (char*)find_mkdir, 0 },
1975     { 21, "_pow", (char*)find_pow, 0 },
1976     { 21, "_log", (char*)find_log, 0 },
1977     { 21, "_log10", (char*)find_log10, 0 },
1978     { 21, "get_ptp_file_buf", (char*)find_get_ptp_file_buf, 0 },
1979 
1980     { 22, "closedir", (char*)find_closedir, 0 },
1981     { 22, "PT_PlaySound", (char*)find_PT_PlaySound, 0 },
1982     { 22, "ExportToEventProcedure_FW", (char*)find_ExportToEventProcedure, 0 },
1983     { 22, "RegisterEventProcedure_FW", (char*)find_RegisterEventProcedure, 0 },
1984 
1985     { 22, "set_control_event", (char*)find_set_control_event, 0 }, // vx
1986     { 22, "filesem_init", (char*)find_filesem_init, 0 }, // vx
1987     { 22, "GetCurrentMachineTime", (char*)find_getcurrentmachinetime, 0},
1988     { 22, "get_nd_value", (char*)find_get_nd_value, 0},
1989     { 22, "get_current_nd_value", (char*)find_get_current_nd_value, 0},
1990     { 22, "get_current_deltasv", (char*)find_get_current_deltasv, 0},
1991     { 22, "GetBaseSv", (char*)find_GetBaseSv, 0},
1992     { 22, "GetCurrentDriveBaseSvValue", (char*)find_GetCurrentDriveBaseSvValue, 0 }, // old vx
1993     { 22, "exmem_free", (char*)find_exmem_free, 0},
1994     { 22, "exmem_alloc", (char*)find_exmem_alloc, 0},
1995     { 22, "exmem_ufree", (char*)find_exmem_ufree, 0},
1996     { 22, "exmem_ualloc", (char*)find_exmem_ualloc, 0},
1997     { 22, "get_ptp_buf_size", (char*)find_get_ptp_buf_size, 0},
1998     { 22, "Remove", (char*)find_Remove, 0},
1999 
2000     { 23, "cameracon_set_state", "AC:PB2Rec", 8,                                 1,},
2001 
2002     //                                                                                          Vx
2003     { 100, "DebugAssert", "\nAssert: File %s Line %d\n", 0,                                     10 },
2004     { 100, "DebugAssert", "\aAssert: File %s,  Expression %s,  Line %d\n", 0,                   14 }, // ixus30,40
2005     { 100, "CreateMessageQueue", "CreateMessageQueue : call from interrupt handler", 0,         8 },
2006     { 100, "DeleteMessageQueue", "DeleteMessageQueue : call from interrupt handler", 0,         8 },
2007     { 100, "PostMessageQueue", "PostMessageQueue : call from interrupt handler", 0,             12 },
2008     { 100, "ReceiveMessageQueue", "ReceiveMessageQueue : NULL buffer address", 0,               11 },
2009     { 100, "TryReceiveMessageQueue", "TryReceiveMessageQueue : NULL buffer address", 0,         10 },
2010     { 100, "CreateEventFlag", "CreateEventFlag : call from interrupt handler", 0,               5 },
2011     { 100, "DeleteEventFlag", "DeleteEventFlag : call from interrupt handler", 0,               8 },
2012     { 100, "WaitForEventFlag", "WaitForEventFlag : call from interrupt handler", 0,             12 },
2013     { 100, "CancelHPTimer", "EventProcedure", 0,                                                101 }, // newest vx
2014     { 100, "get_current_exp", "Exp  Av %d, Tv %d, Gain %d\r",0x01000001,                        0x07 },
2015     { 100, "EnableDispatch", "EnableDispatch : call from interrupt handler", 0,                 3 },
2016     { 100, "DisableDispatch", "DisableDispatch : call from interrupt handler", 0,               3 },
2017 
2018     { 101, "DeleteSemaphore", "DeleteSemaphore", 0 },
2019     { 101, "CreateCountingSemaphore", "CreateCountingSemaphore", 0 },
2020     { 101, "TakeSemaphore", "TakeSemaphore", 0 },
2021     { 101, "GiveSemaphore", "GiveSemaphore", 0 },
2022     { 101, "CreateTask", "CreateTask", 0 },
2023     { 101, "ExitTask", "ExitTask", 0 },
2024     { 101, "PT_GetSystemTime", "PT_GetSystemTime", 0 },
2025 
2026     { 102, "PB2Rec", "AC:PB2Rec", 0,                                                            0x20 },
2027     { 102, "Rec2PB", "AC:Rec2PB", 0,                                                            0x20 },
2028     { 102, "MenuIn", "SSAPI::MenuIn", 0,                                                        0x20 },
2029     { 102, "MenuOut", "SSAPI::MenuOut", 0,                                                      0x20 },
2030 
2031     { 103, "GetDrive_FreeClusters", "AvailClusters.c", 0,                                       0x04 },
2032 
2033     { 104, "SetLogicalEventActive", "EventReciever.c", 16,                                      0x0000 },
2034     { 104, "exmem_alloc_low", "m_MemBlockArray[Type].Size == 0L", 33,                           0x0000 },
2035     { 104, "exmem_free_low", "m_MemBlockArray[Type].Size != 0L", 25,                            0x0000 },
2036 
2037     { 0, 0, 0, 0 }
2038 };
2039 
2040 // Find the named function in the 'func_list' array above, return index of entry
2041 int find_func(const char* name)
2042 {
2043     int i;
2044     for (i=0; func_list[i].name != 0; i++)
2045     {
2046         if (strcmp(name, func_list[i].name) == 0)
2047         {
2048             return i;
2049         }
2050     }
2051     return -1;  // Not found
2052 }
2053 
2054 // Get VxWorks version specific offset?
2055 int vxworks_offset(__attribute__ ((unused))firmware *fw, string_sig *sig)
2056 {
2057     return sig->vxworks_offset;
2058 }
2059 
2060 //------------------------------------------------------------------------------------------------------------
2061 
2062 // Loop through firmware looking for instances of a sig string
2063 // For each one found call the check_match function to see if it matches the sig
2064 // Return 1 if match found, else return 0
2065 int fw_string_process(firmware *fw, string_sig *sig, int (*check_match)(firmware *fw, string_sig *sig, int j), int inc_eos)
2066 {
2067     int nlen = strlen(sig->ev_name);
2068     uint32_t nm0 = *((uint32_t*)sig->ev_name);
2069     uint32_t *p;
2070     int j;
2071     BufRange *br;
2072 
2073     for (br = fw->br; br != 0; br = br->next)
2074     {
2075         for (p = br->p, j = br->off; j < br->off+br->len-nlen/4; p++, j++)
2076         {
2077             if ((nm0 == *p) && (memcmp(p+1,sig->ev_name+4,nlen-4+inc_eos) == 0))
2078             {
2079                 if (check_match(fw,sig,j))
2080                     return 1;
2081             }
2082         }
2083     }
2084 
2085     return 0;
2086 }
2087 
2088 // As above; but scan the firmware byte-by-byte rather than by words
2089 // Slower; but required when strings are not stores on 32 bit boundaries
2090 int fw_string_process_unaligned(firmware *fw, string_sig *sig, int (*check_match)(firmware *fw, string_sig *sig, int j))
2091 {
2092     int nlen = strlen(sig->ev_name);
2093     char *p;
2094     int j;
2095     BufRange *br;
2096 
2097     for (br = fw->br; br != 0; br = br->next)
2098     {
2099         for (p = (char*)br->p, j = 0; j < br->len*4-nlen; p++, j++)
2100         {
2101             if (strcmp(p,sig->ev_name) == 0)
2102             {
2103                 if (check_match(fw,sig,j+br->off*4))
2104                     return 1;
2105             }
2106         }
2107     }
2108 
2109     return 0;
2110 }
2111 
2112 // Loop through the firmware from the start, calling 'check_match' for each location
2113 // If 'check_match' returns non-zero, exit returning 1.
2114 // Otherwise returns 0 - no match found.
2115 int fw_process(firmware *fw, string_sig *sig, int (*check_match)(firmware *fw, string_sig *sig, int j))
2116 {
2117     uint32_t *p;
2118     int j;
2119     BufRange *br;
2120 
2121     for (br = fw->br; br != 0; br = br->next)
2122     {
2123         for (p = br->p, j = br->off; j < br->off+br->len; p++, j++)
2124         {
2125             if (check_match(fw,sig,j))
2126                 return 1;
2127         }
2128     }
2129 
2130     return 0;
2131 }
2132 
2133 //------------------------------------------------------------------------------------------------------------
2134 
2135 // New string / signature matching functions
2136 
2137 // Sig pattern:
2138 //      Function pointer    -   DCD func
2139 //      String              -   DCB "func"
2140 // Note: 'func' may not be the target address, the sig->offset value allows selection of another function
2141 //       called at a fixed number of instructions from the 'func' address found
2142 int match_strsig1(firmware *fw, string_sig *sig, int j)
2143 {
2144     uint32_t fadr = fwval(fw,j-1);      // function address
2145     if (idx_valid(fw,adr2idx(fw,fadr))) // is function address valid
2146     {
2147         // If function address is a B, and we are following branches, then follow the first B
2148         if (sig->offset > 1) fadr = followBranch(fw, fadr, 1);
2149         // Follow any subsequent branch at the given offset
2150         fadr = followBranch2(fw, fadr, sig->offset);
2151         fwAddMatch(fw,fadr,32,0,101);
2152         return 1;
2153     }
2154     return 0;
2155 }
2156 
2157 // Sig pattern:
2158 //      String pointer      -       DCD str
2159 //      Function pointer    -       DCD func
2160 //                ...
2161 //      String              -   str DCB "func"
2162 // Note: 'func' may not be the target address, the offset value allows selection of another function
2163 //       called at a fixed number of instructions from the 'func' address found
2164 int match_strsig2a(firmware *fw, int k, uint32_t sadr, uint32_t offset)
2165 {
2166     if (fwval(fw,k) == sadr)                // pointer to string?
2167     {
2168         uint32_t fadr = fwval(fw,k+1);      // function address
2169         if (idx_valid(fw,adr2idx(fw,fadr))) // is function address valid
2170         {
2171             uint32_t bfadr = followBranch2(fw, fadr, offset);
2172             if ((offset <= 1) || (bfadr != fadr))
2173             {
2174                 fwAddMatch(fw,bfadr,32,0,102);
2175                 return 1;
2176             }
2177         }
2178     }
2179     return 0;
2180 }
2181 int match_strsig2(firmware *fw, string_sig *sig, int j)
2182 {
2183     // Note - 'j' is byte offset in firmware not instruction index (called from fw_string_process_unaligned)
2184     return search_fw(fw, match_strsig2a, fw->base + j, sig->offset, 2);
2185 }
2186 
2187 // Sig pattern:
2188 //      Load Func Address   -   ADR Rx, func
2189 //      Load String Address -   ADR Rx, "func"
2190 //      Branch              -   BL
2191 //              ...
2192 //      String              -   DCB "func"
2193 // or
2194 //      Load Func Address   -   ADR Rx, func
2195 //                              B   loc
2196 //              ...
2197 //                          loc:
2198 //      Load String Address -   ADR    Rx, "func"
2199 //      Branch              -   BL
2200 //              ...
2201 //      String              -   DCB "func"
2202 // 'sadr' = address of "func" string
2203 // Note: 'func' may not be the target address, the offset value allows selection of another function
2204 //       called at a fixed number of instructions from the 'func' address found
2205 int match_strsig3a(firmware *fw, int k, uint32_t sadr, uint32_t offset)
2206 {
2207     if (isADR_PC(fw,k+1) &&    // ADR ?
2208         isBorBL(fw,k+2))       // B or BL ?
2209     {
2210         uint32_t padr = ADR2adr(fw,k+1);    // get address pointed to by 2nd ADR instructioin
2211         if (padr == sadr)                   // does it match target string
2212         {
2213             int j2 = k;
2214             int found = 0;
2215             if (isADR_PC(fw,k))             // ADR ?
2216                 found = 1;
2217             else
2218             {
2219                 // May be DCD block between 1st and 2nd ADR
2220                 for (j2 = k-2; j2 >= 0 && j2 >= k-4096; j2--)
2221                 {
2222                     if (isADR_PC(fw,j2) &&  // ADR ?
2223                         isB(fw,j2+1))       // B
2224                     {
2225                         uint32_t fa = idx2adr(fw,j2+1);
2226                         fa = followBranch(fw,fa,1);
2227                         if (adr2idx(fw,fa) == k+1)
2228                         {
2229                             found = 1;
2230                             break;
2231                         }
2232                     }
2233                 }
2234             }
2235             if (found)
2236             {
2237                 uint32_t fadr = ADR2adr(fw,j2);
2238                 if (offset > 1) fadr = followBranch(fw, fadr, 1);
2239                 fadr = followBranch2(fw, fadr, offset);
2240                 fwAddMatch(fw,fadr,32,0,103);
2241                 return 1;
2242             }
2243         }
2244     }
2245     return 0;
2246 }
2247 int match_strsig3(firmware *fw, string_sig *sig, int j)
2248 {
2249     return search_fw(fw, match_strsig3a, idx2adr(fw,j), sig->offset, 3);
2250 }
2251 
2252 // Sig pattern:
2253 //      Save Regs           -   STMFD
2254 //                ... (offset)
2255 //      Load String Address -   ADR Rx, "func"
2256 //                ...
2257 //      String              -   DCB "func"
2258 int match_strsig4a(firmware *fw, int k, uint32_t sadr, uint32_t offset)
2259 {
2260     if (isSTMFD(fw,k) &&        // STMFD
2261         isADR_PC(fw,k+offset))  // ADR ?
2262     {
2263         uint32_t padr = ADR2adr(fw,k+offset);
2264         if (padr == sadr)
2265         {
2266             uint32_t fadr = idx2adr(fw,k);
2267             fwAddMatch(fw,fadr,32,0,104);
2268             return 1;
2269         }
2270     }
2271     return 0;
2272 }
2273 int match_strsig4(firmware *fw, string_sig *sig, int j)
2274 {
2275     return search_fw(fw, match_strsig4a, idx2adr(fw,j), sig->offset, sig->offset+1);
2276 }
2277 
2278 // Sig pattern:
2279 //      Load Func Address   -   LDR Rx, =func
2280 //      Load String Address -   xDR Rx, "func"  (LDR or ADR)
2281 //      Branch              -   BL
2282 //              ...
2283 //      String              -   DCB "func"
2284 // or
2285 //      Load Func Address   -   LDR Rx, =func
2286 //                              B   loc
2287 //              ...
2288 //                          loc:
2289 //      Load String Address -   xDR Rx, "func"  (LDR or ADR)
2290 //      Branch              -   BL
2291 //              ...
2292 //      String              -   DCB "func"
2293 static int dryos_ofst;
2294 int match_strsig5a(firmware *fw, int k, uint32_t sadr, uint32_t offset)
2295 {
2296     if ((isADR_PC(fw,k+1) || isLDR_PC(fw,k+1)) &&   // LDR or ADR ?
2297         isBorBL(fw,k+2))                            // B or BL ?
2298     {
2299         uint32_t padr;
2300         if (isLDR_PC(fw,k+1))                       // LDR ?
2301             padr = LDR2val(fw,k+1);
2302         else
2303             padr = ADR2adr(fw,k+1);
2304         if (padr == sadr)
2305         {
2306             int j2 = k;
2307             int found = 0;
2308             if (isLDR_PC(fw,k))                     // LDR ?
2309                 found = 1;
2310             else
2311             {
2312                 for (j2 = k-2; j2 >= 0 && j2 >= k-4096; j2--)
2313                 {
2314                     if (isLDR_PC(fw,j2) &&  // LDR ?
2315                         isB(fw,j2+1))       // B
2316                     {
2317                         if (idxFollowBranch(fw,j2+1,1) == k+1)
2318                         {
2319                             found = 1;
2320                             break;
2321                         }
2322                     }
2323                 }
2324             }
2325             if (found)
2326             {
2327                 uint32_t fadr = LDR2val(fw,j2);
2328                 if (offset > 1) fadr = followBranch(fw, fadr, 1);
2329                 fadr = followBranch2(fw, fadr, offset);
2330                 if (dryos_ofst != 0)
2331                 {
2332                     uint32_t fadr2 = followBranch(fw, fadr, dryos_ofst);
2333                     if (fadr == fadr2) return 0;
2334                     fadr = fadr2;
2335                 }
2336                 fwAddMatch(fw,fadr,32,0,105);
2337                 return 1;
2338             }
2339         }
2340     }
2341     return 0;
2342 }
2343 int match_strsig5(firmware *fw, string_sig *sig, int j)
2344 {
2345     dryos_ofst = vxworks_offset(fw,sig);
2346     return search_fw(fw, match_strsig5a, idx2adr(fw,j), sig->offset, 3);
2347 }
2348 
2349 // Sig pattern:
2350 //    Function immediately preceeding string
2351 int match_strsig6(firmware *fw, __attribute__ ((unused))string_sig *sig, int j)
2352 {
2353     int j1 = find_inst_rev(fw, isSTMFD_LR, j-1, j-1);
2354     if (j1 > 0)
2355     {
2356         uint32_t fadr = idx2adr(fw,j1);
2357         fwAddMatch(fw,fadr,32,0,106);
2358         return 1;
2359     }
2360 
2361     return 0;
2362 }
2363 
2364 // Sig pattern:
2365 //      Str ref -   xDRnn Rx, =str_ptr
2366 //            ...
2367 //                  BL  func
2368 //            ...
2369 //      String      DCB "str"
2370 int match_strsig7a(firmware *fw, int k, uint32_t sadr, uint32_t offset)
2371 {
2372     if (isADR_PC_cond(fw,k) || isLDR_PC_cond(fw,k)) // LDR or ADR ?
2373     {
2374         uint32_t padr;
2375         if (isLDR_PC_cond(fw,k)) // LDR ?
2376             padr = LDR2val(fw,k);
2377         else
2378             padr = ADR2adr(fw,k);
2379         if (padr == sadr)
2380         {
2381             int j2 = find_inst(fw, isBL, k+1, 10);
2382             if (j2 > 0)
2383             {
2384                 uint32_t fa = idx2adr(fw,j2);
2385                 fa = followBranch2(fw,fa,offset);
2386                 fwAddMatch(fw,fa,32,0,107);
2387                 return 1;
2388             }
2389         }
2390     }
2391     return 0;
2392 }
2393 int match_strsig7(firmware *fw, string_sig *sig, int j)
2394 {
2395     return search_fw(fw, match_strsig7a, idx2adr(fw,j), sig->offset, 2);
2396 }
2397 
2398 // Sig pattern:
2399 //      Special case for WriteSDCard
2400 int ofst;
2401 int match_strsig8(firmware *fw, __attribute__ ((unused))string_sig *sig, int j)
2402 {
2403     int j1;
2404     for (j1=j-2; j1<j+8; j1++)
2405     {
2406         uint32_t fadr = idx2adr(fw,j1);
2407         if (fwval(fw,j1) >= fw->base)   // pointer ??
2408         {
2409             int j2;
2410             for (j2=j1-1; j2>=j1-1000 && j2>=0; j2--)
2411             {
2412                 if (isLDR_PC(fw,j2) && (LDR2adr(fw,j2) == fadr))    // LDR ?
2413                 {
2414                     if ((isSTR(fw,j2+1) && (fwOp2(fw,j2+1) == ofst)) ||    // STR ?
2415                         (isSTR(fw,j2+2) && (fwOp2(fw,j2+2) == ofst)))      // STR ?
2416                     {
2417                         fadr = fwval(fw,j1);
2418                         if (idx_valid(fw,adr2idx(fw,fadr)))
2419                         {
2420                             fwAddMatch(fw,fadr,32,0,108);
2421                             return 1;
2422                         }
2423                     }
2424                 }
2425             }
2426         }
2427     }
2428 
2429     return 0;
2430 }
2431 int find_strsig8(firmware *fw, string_sig *sig)
2432 {
2433     uint32_t fadr = 0;
2434     int srch = 20;
2435 
2436     // Find "UpdateMBROnFlash" code
2437     int j = get_saved_sig(fw,"UpdateMBROnFlash");
2438     if (j >= 0)
2439     {
2440         fadr = func_names[j].val;
2441     }
2442     else
2443     {
2444         j = get_saved_sig(fw,"MakeSDCardBootable");
2445         if (j >= 0)
2446         {
2447             fadr = func_names[j].val;
2448             srch = 32;
2449         }
2450     }
2451 
2452     if (fadr == 0) return 0;
2453 
2454     int idx = adr2idx(fw, fadr);
2455     ofst = -1;
2456 
2457     for (j=idx+srch; j<idx+srch+12; j++)
2458     {
2459         if (isLDR(fw,j) && isLDR(fw,j+1) && isLDR(fw,j+2))
2460         {
2461             ofst = fwOp2(fw,j) + fwOp2(fw,j+1) + fwOp2(fw,j+2);
2462             break;
2463         }
2464     }
2465 
2466     if (ofst == -1) return 0;
2467 
2468     return fw_string_process(fw, sig, match_strsig8, 1);
2469 }
2470 
2471 // Sig pattern:
2472 //      Func is B/BL @ offset from previous found func
2473 //          prev_func
2474 //              ... (offset)
2475 //              BL    func
2476 int find_strsig9(firmware *fw, string_sig *sig)
2477 {
2478     int j = get_saved_sig(fw,sig->ev_name);
2479     if (j >= 0)
2480     {
2481         if (func_names[j].val != 0)
2482         {
2483             int ofst = vxworks_offset(fw, sig);
2484             uint32_t fadr = followBranch(fw, func_names[j].val+ofst*4, 0xF1000001);
2485             if ((sig->offset == -1) || (fadr != func_names[j].val+ofst*4))
2486             {
2487                 uint32_t fadr2 = fadr;
2488                 if (sig->offset != -1) fadr2 = followBranch2(fw, fadr2, sig->offset);
2489                 if ((sig->offset <= 0) || (fadr2 != fadr))
2490                 {
2491                     fwAddMatch(fw,fadr2,32,0,109);
2492                     return 1;
2493                 }
2494             }
2495         }
2496     }
2497 
2498     return 0;
2499 }
2500 
2501 // Sig pattern:
2502 //      Func            -   func
2503 //            .... (offset)
2504 //      Ref to string   -       ADR Rx, str
2505 //            ....
2506 //      String          -       DCB "str"
2507 int match_strsig11(firmware *fw, string_sig *sig, int j)
2508 {
2509     int ofst = vxworks_offset(fw, sig);
2510 
2511     uint32_t sadr = idx2adr(fw,j);        // string address
2512     int j1;
2513     for (j1 = j-1; j1 >= 0; j1--)
2514     {
2515         if (isADR_PC_cond(fw,j1))   // ADR ?
2516         {
2517             uint32_t padr = ADR2adr(fw,j1);
2518             if (padr == sadr)
2519             {
2520                 uint32_t fadr = idx2adr(fw,j1-ofst);
2521                 uint32_t bfadr = followBranch(fw,fadr,sig->offset);
2522                 // special case for 'set_control_event'
2523                 int found = 0;
2524                 if (strcmp(sig->name,"set_control_event") == 0)
2525                 {
2526                     int j2 = j1 - ofst;
2527                     if (isBL_cond(fw,j2) &&                                             // BLxx
2528                         isLDR_SP(fw,j2+1) && (fwRd(fw,j2+1) == 0) &&                    // LDR R0,[SP,x]
2529                         isBL(fw,j2+2) &&                                                // BL
2530                         isMOV(fw,j2+3) && (fwRd(fw,j2+3) == 4) && (fwRn(fw,j2+3) == 0)) // LDR R4, R0
2531                     {
2532                         found = 1;
2533                     }
2534                 }
2535                 else
2536                     found = 1;
2537                 if (found && ((sig->offset == 0) || (bfadr != fadr)))
2538                 {
2539                     fwAddMatch(fw,bfadr,32,0,111);
2540                     return 1;
2541                 }
2542             }
2543         }
2544     }
2545 
2546     return 0;
2547 }
2548 
2549 //// Sig pattern:
2550 ////      Func is referenced in 'CreateJumptable'
2551 ////          LDR R1, =func
2552 ////          STR R1, [R0,nnn]
2553 ////      nnn - dryos version dependant offset
2554 //int find_strsig12(firmware *fw, string_sig *sig)
2555 //{
2556 //    int j = get_saved_sig(fw,"CreateJumptable");
2557 //
2558 //    int ofst = vxworks_offset(fw, sig);
2559 //
2560 //    if (ofst == 0) return 0;
2561 //
2562 //    if (j >= 0)
2563 //    {
2564 //        if (func_names[j].val != 0)
2565 //        {
2566 //            int idx = adr2idx(fw, func_names[j].val);
2567 //            for(; !isBX_LR(fw,idx); idx++)  // BX LR
2568 //            {
2569 //                if (((fwval(fw,idx+1) & 0xFFFFF000) == 0xE5801000) && // STR R1,[R0,nnn]
2570 //                    (fwOp2(fw,idx+1) == ofst))
2571 //                {
2572 //                    uint32_t fadr = LDR2val(fw,idx);
2573 //                    uint32_t bfadr = followBranch2(fw,fadr,sig->offset);
2574 //                    if ((sig->offset <= 1) || ((bfadr != fadr) && ((fw->buf[adr2idx(fw,fadr)] & 0xFFFF0000) == 0xE92D0000)))
2575 //                    {
2576 //                        fwAddMatch(fw,bfadr,32,0,112);
2577 //                        return 1;
2578 //                    }
2579 //                }
2580 //                else if (isB(fw,idx))    // B
2581 //                {
2582 //                    idx = adr2idx(fw,followBranch(fw,idx2adr(fw,idx),1)) - 1;
2583 //                }
2584 //            }
2585 //        }
2586 //    }
2587 //
2588 //    return 0;
2589 //}
2590 
2591 // Sig pattern:
2592 //      Func    -   func
2593 //          ... (offset)
2594 //      Str ref -       LDR Rx, =str_ptr
2595 //          ...
2596 //      Str ptr -       DCD str_ptr
2597 //          ...
2598 //      Str ptr -   str_ptr
2599 //                      DCD str
2600 //          ...
2601 //      String          DCB "str"
2602 int match_strsig13a(firmware *fw, int k, uint32_t sadr, uint32_t offset)
2603 {
2604     if (fwval(fw,k) == sadr)    // string ptr
2605     {
2606         uint32_t padr = idx2adr(fw,k);      // string ptr address
2607         int j2;
2608         for (j2 = k-1; j2 >= 0; j2--)
2609         {
2610             if (fwval(fw,j2) == padr)       // string ptr address
2611             {
2612                 uint32_t ppadr = idx2adr(fw,j2);        // string ptr ptr address
2613                 int j3;
2614                 for (j3 = j2-1; j3 >= 0; j3--)
2615                 {
2616                     if (isLDR_PC(fw,j3) && (LDR2adr(fw,j3) == ppadr))
2617                     {
2618                         uint32_t fadr = idx2adr(fw,j3-offset);
2619                         fwAddMatch(fw,fadr,32,0,113);
2620                         return 1;
2621                     }
2622                 }
2623             }
2624         }
2625     }
2626     return 0;
2627 }
2628 int match_strsig13(firmware *fw, string_sig *sig, int j)
2629 {
2630     // Note - 'j' is offset in firmware not instruction index (called from fw_string_process_unaligned)
2631     return search_fw(fw, match_strsig13a, fw->base + j, sig->offset, 1);
2632 }
2633 
2634 // Sig pattern:
2635 //                  BL  func
2636 //            ...
2637 //      Str ref -   xDR Rx, =str_ptr
2638 //            ...
2639 //      String      DCB "str"
2640 // dryos_ofst: search range limit for the previous bl instruction
2641 int match_strsig15a(firmware *fw, int k, uint32_t sadr, uint32_t offset)
2642 {
2643     if (isADR_PC_cond(fw,k) || isLDR_PC_cond(fw,k))   // LDR or ADR ?
2644     {
2645         uint32_t padr;
2646         if (isLDR_PC_cond(fw,k)) // LDR ?
2647             padr = LDR2val(fw,k);
2648         else
2649             padr = ADR2adr(fw,k);
2650         if (padr == sadr)
2651         {
2652             int j2 = find_inst_rev(fw, isBL, k-1, dryos_ofst);
2653             if (j2 > 0)
2654             {
2655                 uint32_t fa = idx2adr(fw,j2);
2656                 fa = followBranch2(fw,fa,offset);
2657                 fwAddMatch(fw,fa,32,0,115);
2658                 return 1;
2659             }
2660         }
2661     }
2662     return 0;
2663 }
2664 int match_strsig15(firmware *fw, string_sig *sig, int j)
2665 {
2666     dryos_ofst = vxworks_offset(fw,sig);
2667     if (dryos_ofst == 0) dryos_ofst = 50;
2668     return search_fw(fw, match_strsig15a, idx2adr(fw,j), sig->offset, 1);
2669 }
2670 
2671 // Sig pattern:
2672 //      Function immediately preceeding usage of hex value
2673 int match_strsig16(firmware *fw, string_sig *sig, int j)
2674 {
2675     uint32_t nm0 = *((uint32_t*)sig->ev_name);
2676 
2677     if (isADR_PC_cond(fw,j) || isLDR_PC_cond(fw,j))   // LDR or ADR ?
2678     {
2679         uint32_t padr = 0;
2680         if (isLDR_PC_cond(fw,j)) // LDR ?
2681         {
2682             int k = adr2idx(fw,LDR2adr(fw,j));
2683             if (idx_valid(fw,k))
2684                 padr = fwval(fw,k);
2685         }
2686         else
2687             padr = ADR2adr(fw,j);
2688         if (padr == nm0)
2689         {
2690             int j2 = find_inst_rev(fw, isSTMFD_LR, j-1, 50);
2691             if (j2 > 0)
2692             {
2693                 uint32_t fa = idx2adr(fw,j2);
2694                 fwAddMatch(fw,fa,32,0,116);
2695                 return 1;
2696             }
2697         }
2698     }
2699 
2700     return 0;
2701 }
2702 
2703 // Sig pattern:
2704 //      Special case for ScreenLock & ScreenUnlock
2705 int find_strsig17(firmware *fw, string_sig *sig)
2706 {
2707     int j = get_saved_sig(fw,"StartRecModeMenu");
2708 
2709     if (j >= 0)
2710     {
2711         if (func_names[j].val != 0)
2712         {
2713             int idx = adr2idx(fw, func_names[j].val);
2714             int k = 0;
2715             if (isLDR_PC(fw,idx-3) && isMOV_immed(fw,idx-2) && isB(fw,idx-1))
2716             {
2717                 k = adr2idx(fw,LDR2val(fw,idx-3));
2718             }
2719             else if (isMOV_immed(fw,idx-3) && isADR_PC(fw,idx-2) && isB(fw,idx-1))
2720             {
2721                 k = adr2idx(fw,ADR2adr(fw,idx-2));
2722             }
2723             if (k != 0)
2724             {
2725                 uint32_t fadr;
2726                 if (strcmp(sig->name,"ScreenLock") == 0)
2727                     fadr = followBranch(fw,idx2adr(fw,k+1),0x01000001);
2728                 else
2729                 {
2730                     k = find_inst(fw, isLDMFD, k+1, 60);
2731                     fadr = followBranch(fw,idx2adr(fw,k-1),0x01000001);
2732                 }
2733                 fwAddMatch(fw,fadr,32,0,117);
2734                 return 1;
2735             }
2736         }
2737     }
2738 
2739     return 0;
2740 }
2741 
2742 // Sig pattern:
2743 //      Func is offset from previously found func
2744 //          prev_func
2745 //              ... (offset, less than 0xff)
2746 //          func
2747 // vxworks_offset to be encoded as: 0xQRPP
2748 // PP) offset, 0x00...0xff, in words
2749 // Q) 'previous instruction flag': 0 for LDMFD, 1 for B
2750 // R) 'additional gap size': 0x0 ... 0xf, to skip an additional gap, in words
2751 // offset is negative if vxworks_offset is negative
2752 int find_strsig19(firmware *fw, string_sig *sig)
2753 {
2754     int j = get_saved_sig(fw,sig->ev_name);
2755     if (j >= 0)
2756     {
2757         if (func_names[j].val != 0) // address, not idx
2758         {
2759             int ofst = vxworks_offset(fw, sig);
2760             int neg = 1;
2761             if (ofst<0)
2762             {
2763                 neg=-1;
2764                 ofst=-ofst;
2765             }
2766             int addoffs = (ofst & 0xf00)>>8;
2767             uint32_t fadr = func_names[j].val+neg*(ofst&0xff)*4;
2768             int k = 0;
2769             switch ((ofst&0xf000)>>12)
2770             {
2771                 case 0: k = isLDMFD_PC(fw, adr2idx(fw, fadr)-1-addoffs); break;
2772                 case 1: k = isB(fw, adr2idx(fw, fadr)-1-addoffs); break;
2773             }
2774             if (k)
2775             {
2776                 fwAddMatch(fw,fadr,32,0,119);
2777                 return 1;
2778             }
2779         }
2780     }
2781 
2782     return 0;
2783 }
2784 // Sig pattern:
2785 //      Str ref -   xDRnn Rx, =str_ptr
2786 //            ...
2787 //                  BL  func
2788 //            ...
2789 //      String      DCB "str"
2790 // offset: interpreted as max search distance
2791 // dryos_ofst: 0 for 1st B/BL after str ref, 1 for 2nd, etc.; -1 for 1st preceding, etc...; disable with 99
2792 // based on method 7
2793 int match_strsig23a(firmware *fw, int k, uint32_t sadr, uint32_t maxdist)
2794 {
2795     if (isADR_PC_cond(fw,k) || isLDR_PC_cond(fw,k)) // LDR or ADR ?
2796     {
2797         uint32_t padr;
2798         if (isLDR_PC_cond(fw,k)) // LDR ?
2799             padr = LDR2val(fw,k);
2800         else
2801             padr = ADR2adr(fw,k);
2802         if (padr == sadr)
2803         {
2804             int j2;
2805             if (dryos_ofst < 0)
2806             {
2807                 j2 = find_Nth_inst_rev(fw, isBorBL, k, maxdist, -dryos_ofst);
2808             }
2809             else
2810             {
2811                 j2 = find_Nth_inst(fw, isBorBL, k+1, maxdist, dryos_ofst+1);
2812             }
2813             if (j2 > 0)
2814             {
2815                 uint32_t fa = idx2adr(fw,j2);
2816                 fa = followBranch2(fw,fa,0x01000001);
2817                 fwAddMatch(fw,fa,32,0,123);
2818                 return 1;
2819             }
2820         }
2821     }
2822     return 0;
2823 }
2824 int match_strsig23(firmware *fw, string_sig *sig, int j)
2825 {
2826     dryos_ofst = vxworks_offset(fw,sig);
2827 
2828     if (dryos_ofst == 99)
2829         return 0;
2830 
2831     return search_fw(fw, match_strsig23a, idx2adr(fw,j), sig->offset, 2);
2832 }
2833 
2834 // Sig pattern (Vx specific?):
2835 //      Func            -   func
2836 //            .... (offset)
2837 //      Ref to string   -       LDR Rx, pstr
2838 //            ....
2839 //      Ptr to string   -       DCD pstr
2840 // based on method 11
2841 int match_strsig100(firmware *fw, string_sig *sig, int j)
2842 {
2843     int ofst = vxworks_offset(fw, sig);
2844 
2845     uint32_t sadr = idx2adr(fw,j);        // string address
2846     int j1;
2847     for (j1 = j+256; j1 >= 0; j1--)
2848     {
2849         if (isLDR(fw,j1))   // LDR ?
2850         {
2851             uint32_t pval = LDR2val(fw,j1);
2852             if (pval == sadr)
2853             {
2854                 uint32_t fadr = idx2adr(fw,j1-ofst);
2855                 uint32_t bfadr = followBranch(fw,fadr,sig->offset);
2856                 if ((sig->offset == 0) || (bfadr != fadr))
2857                 {
2858                     fwAddMatch(fw,bfadr,32,0,1100);
2859                     return 1;
2860                 }
2861             }
2862         }
2863     }
2864 
2865     return 0;
2866 }
2867 
2868 // Sig pattern (VxWorks specific):
2869 // still needed due to ambiguous parts of code (indirect ExportToEventProcedure, RegisterEventProcedure calls)
2870 //      String               -   DCB "func"
2871 //              ...
2872 //      Load String Address  -   LDR R0, ="func"
2873 //      Load func Address    -   LDR R1, =func
2874 // these are parameters for ExportToEventProcedure, RegisterEventProcedure
2875 int match_strsig101(firmware *fw, __attribute__ ((unused))string_sig *sig, int j)
2876 {
2877     uint32_t sadr = idx2adr(fw,j);        // string address
2878     int j1;
2879     for (j1 = j+1024; j1 >= 0; j1--)
2880     {
2881         if (isLDR(fw,j1) && (fwRd(fw,j1)==0))   // LDR R0,
2882         {
2883             uint32_t pval = LDR2val(fw,j1);
2884             if (pval == sadr) // our string's address
2885             {
2886                 int j2;
2887                 for (j2 = j1+2; j2 > j1; j2--)
2888                 {
2889                     if (isLDR(fw,j2) && (fwRd(fw,j2)==1)) // LDR R1,
2890                     {
2891                         uint32_t pval2 = LDR2val(fw,j2);
2892                         fwAddMatch(fw,pval2,32,0,1101);
2893                         return 1;
2894                     }
2895                 }
2896             }
2897         }
2898     }
2899 
2900     return 0;
2901 }
2902 
2903 // Sig pattern to identify AC: functions (Vx)
2904 // Function starts directly after its debug string
2905 int match_strsig102(firmware *fw, __attribute__ ((unused))string_sig *sig, int j)
2906 {
2907     uint32_t sadr = idx2adr(fw,j);        // string address
2908     char *n = (char*)adr2ptr(fw,sadr);
2909     int nl = 0;
2910     if (n) {
2911         nl = strlen(n);
2912         nl = (((nl+3)>>2)<<2);
2913         if (nl > 0) {
2914             fwAddMatch(fw,sadr+nl,32,0,1102);
2915             return 1;
2916         }
2917     }
2918     return 0;
2919 }
2920 
2921 // Func is offset from a string, special case for GetDrive_FreeClusters
2922 //      Func            -   func
2923 //            ....
2924 //      string          -   DCB "str"
2925 int match_strsig103(firmware *fw, string_sig *sig, int j)
2926 {
2927     int ofst = vxworks_offset(fw, sig);
2928 
2929     int j1 = j+ofst;
2930     if (isSTMFD_LR(fw,j1))
2931     {
2932         // get third BL
2933         j1 = find_Nth_inst(fw,isBL,j1+1,20,3);
2934         if (j1<0)
2935             return 0;
2936         j1 = idxFollowBranch(fw,j1,0x01000001);
2937         // get first B
2938         j1 = find_Nth_inst(fw,isB,j1+1,32,1);
2939         if (j1<0)
2940             return 0;
2941         j1 = idxFollowBranch(fw,j1,0x01000001);
2942         fwAddMatch(fw,idx2adr(fw,j1),32,0,1103);
2943         return 1;
2944     }
2945     return 0;
2946 }
2947 
2948 // Sig pattern:
2949 //      Func            -   func
2950 //            .... [offset]
2951 //      Nth instruction backwards from string ref
2952 //      Ref to string   -       LDR Rx, pstr
2953 //            ....
2954 //      Ptr to string   -       DCD pstr
2955 // based on method 11
2956 // vxworks_offset to be encoded as: 0xQNPP
2957 // P) additional offset
2958 // Q) instruction to locate: 0 for STMFD_LR
2959 // N) search the instruction this many times - 1 (i.e. 0 = first instruction backwards)
2960 // prev instruction search range is limited by sig->offset
2961 // the reference to the string has to occur within 256 words (fixed range)
2962 int match_strsig104(firmware *fw, string_sig *sig, int j)
2963 {
2964     int ofst = vxworks_offset(fw, sig);
2965     int prinst = (ofst&0xf000)>>12;
2966     int ninst = ((ofst&0xf00)>>8)+1;
2967     ofst &= 0xff;
2968     void *instid;
2969     switch (prinst) {
2970         case 0:
2971         default:
2972             instid = (void*)isSTMFD_LR;
2973     }
2974 
2975     uint32_t sadr = idx2adr(fw,j);        // string address
2976     int j1;
2977     for (j1 = j+256; j1 >= 0; j1--)
2978     {
2979         if (isLDR(fw,j1))   // LDR ?
2980         {
2981             uint32_t pval = LDR2val(fw,j1);
2982             if (pval == sadr)
2983             {
2984                 int j2 = find_Nth_inst_rev(fw,instid,j1-1,sig->offset,ninst);
2985                 if (j2>0)
2986                 {
2987                     fwAddMatch(fw,idx2adr(fw,j2-ofst),32,0,1104);
2988                     return 1;
2989                 }
2990             }
2991         }
2992     }
2993 
2994     return 0;
2995 }
2996 
2997 // Call processing function based on type
2998 int find_strsig(firmware *fw, string_sig *sig)
2999 {
3000     switch (sig->type)
3001     {
3002     case 1:     return fw_string_process(fw, sig, match_strsig1, 1);
3003     case 2:     return fw_string_process_unaligned(fw, sig, match_strsig2);
3004     case 3:     return fw_string_process(fw, sig, match_strsig3, 1);
3005     case 4:     return fw_string_process(fw, sig, match_strsig4, 1);
3006     case 5:     return fw_string_process(fw, sig, match_strsig5, 1);
3007     case 6:     return fw_string_process(fw, sig, match_strsig6, 1);
3008     case 7:     return fw_string_process(fw, sig, match_strsig7, 1);
3009     case 8:     return find_strsig8(fw, sig);
3010     case 9:     return find_strsig9(fw, sig);
3011     case 11:    return fw_string_process(fw, sig, match_strsig11, 0);
3012     //case 12:    return find_strsig12(fw, sig);
3013     case 13:    return fw_string_process_unaligned(fw, sig, match_strsig13);
3014     case 15:    return fw_string_process(fw, sig, match_strsig15, 1);
3015     case 16:    return fw_process(fw, sig, match_strsig16);
3016     case 17:    return find_strsig17(fw, sig);
3017     case 19:    return find_strsig19(fw, sig);
3018     case 20:
3019         {
3020             int j = find_saved_sig(sig->ev_name);
3021             if (j >= 0)
3022             {
3023                 uint32_t fadr = followBranch2(fw,func_names[j].val,sig->offset);
3024                 fwAddMatch(fw,fadr,32,0,120);
3025                 return 1;
3026             }
3027             return 0;
3028         }
3029     case 21:    return fw_process(fw, sig, (int (*)(firmware*, string_sig*, int))(sig->ev_name));
3030     case 22:    return ((int (*)(firmware*))(sig->ev_name))(fw);
3031     case 23:    return fw_string_process(fw, sig, match_strsig23, 1);
3032     case 100:   return fw_string_process(fw, sig, match_strsig100, 0);
3033     case 101:   return fw_string_process(fw, sig, match_strsig101, 0);
3034     case 102:   return fw_string_process(fw, sig, match_strsig102, 0);
3035     case 103:   return fw_string_process(fw, sig, match_strsig103, 0);
3036     case 104:   return fw_string_process(fw, sig, match_strsig104, 0);
3037     }
3038 
3039     return 0;
3040 }
3041 
3042 //------------------------------------------------------------------------------------------------------------
3043 
3044 // Matching functions
3045 
3046 // Search using new style matching only
3047 void find_str_sig_matches(firmware *fw, const char *curr_name)
3048 {
3049     int i;
3050 
3051     int found_ev = 0;
3052 
3053     count = 0;
3054 
3055     for (i = 0; string_sigs[i].ev_name != 0 && !found_ev; i++)
3056     {
3057         if (strcmp(curr_name, string_sigs[i].name) == 0)
3058         {
3059             if (find_strsig(fw, &string_sigs[i]))
3060             {
3061                 found_ev = 1;
3062                 break;
3063             }
3064         }
3065     }
3066 
3067     if (count > 1)
3068     {
3069         qsort(matches, count, sizeof(Match), (void*)match_compare);
3070     }
3071 
3072     if (count > 0)
3073     {
3074         save_sig(curr_name, matches->ptr);
3075     }
3076 }
3077 
3078 // Search using new style matching first
3079 // If not found used old style matching
3080 void find_matches(firmware *fw, const char *curr_name)
3081 {
3082     FuncSig *sig, *s;
3083     BufRange *n;
3084     uint32_t *p;
3085     int i, j;
3086     int fail, success;
3087 
3088     int found_ev = 0;
3089 
3090     count = 0;
3091 
3092     // Already found (eventproc)?
3093     i = find_saved_sig(curr_name);
3094     if (i >= 0)
3095     {
3096         if ((func_names[i].val != 0) && (func_names[i].flags & EV_MATCH) != 0)
3097         {
3098             fwAddMatch(fw,func_names[i].val,32,0,120);
3099             found_ev = 1;
3100         }
3101     }
3102 
3103 
3104     // Try and match using 'string' based signature matching first
3105     for (i = 0; string_sigs[i].ev_name != 0 && !found_ev; i++)
3106     {
3107         if (strcmp(curr_name, string_sigs[i].name) == 0)
3108         {
3109             if (find_strsig(fw, &string_sigs[i]))
3110             {
3111                 found_ev = 1;
3112                 break;
3113             }
3114         }
3115     }
3116 
3117     // If not found see if the name is in the old style instruction compare match table
3118     // Set start value for j in next section if found
3119     if (!found_ev)
3120     {
3121         found_ev = 1;
3122         for (j=0; func_list[j].name; j++)
3123         {
3124             if (strcmp(curr_name,func_list[j].name) == 0)
3125             {
3126                 found_ev = 0;
3127                 break;
3128             }
3129         }
3130     }
3131 
3132     // Not found so far, try instruction comparison matching
3133     while (!found_ev)
3134     {
3135         sig = func_list[j].sig;
3136 
3137         for (n = fw->br; n != 0; n = n->next)
3138         {
3139             for (p = n->p, i = 0; i < n->len; p++, i++)
3140             {
3141                 fail = 0;
3142                 success = 0;
3143                 for (s = sig; s->offs != 0xFFFFFFFF; s++)
3144                 {
3145                     if ((p[s->offs] & s->mask) != s->value)
3146                         fail++;
3147                     else
3148                         success++;
3149                 }
3150                 // If sig starts with STMFD and first instruction does not match ignore it
3151                 if (((p[sig->offs] & sig->mask) != sig->value) && (sig->offs == 0) && (sig->value == 0xe92d0000)) success = 0;
3152                 if (success > fail)
3153                 {
3154                     if (s->mask == 0xFFFFFFFE)
3155                     {
3156                         int end_branch = 0;
3157                         int idx = 0;
3158                         uint32_t *p1 = 0;
3159                         if ((fw->buf[n->off+i+s->value] & 0x0F000000) == 0x0A000000)   // B
3160                         {
3161                             idx = adr2idx(fw, followBranch2(fw, idx2adr(fw,n->off+i+s->value), 0xF0000001));
3162                             if ((idx >= 0) && (idx < fw->size))
3163                             {
3164                                 end_branch = 1;
3165                                 p1 = &fw->buf[idx];
3166                             }
3167                         }
3168                         int fail2 = 0;
3169                         int success2 = 0;
3170                         //fprintf(stderr,"\t%s %d %08x %08x %d %d\n",curr_name,idx,idx2adr(fw,idx),idx2adr(fw,i+n->off),success,fail);
3171                         s++;
3172                         for (; s->offs != 0xFFFFFFFF; s++)
3173                         {
3174                             if (!end_branch || (p1[s->offs] & s->mask) != s->value){
3175                                 fail2++;
3176                             } else {
3177                                 success2++;
3178                             }
3179                         }
3180                         if (fail2 == 0)
3181                         {
3182                             success = success + fail + success2;
3183                             fail = 0;
3184                         }
3185                         else
3186                         {
3187                             success = success + success2;
3188                             fail = fail + fail2;
3189                         }
3190                         //fprintf(stderr,"\t%s %d %08x %08x %d %d\n",curr_name,idx,idx2adr(fw,idx),idx2adr(fw,i+n->off),success,fail);
3191                     }
3192                 }
3193                 if (success > fail)
3194                 {
3195                     // Special case for drive space functions, see if there is a refernce to "Mounter.c" in the function
3196                     // Increase match % if so, increase fail count if not
3197                     if ((strcmp(curr_name, "GetDrive_ClusterSize") == 0) ||
3198                         (strcmp(curr_name, "GetDrive_FreeClusters") == 0) ||
3199                         (strcmp(curr_name, "GetDrive_TotalClusters") == 0))
3200                     {
3201                         int fnd = 0;
3202                         for (s = sig; s->offs != 0xFFFFFFFF; s++)
3203                         {
3204                             if (isLDR_PC_cond(fw,n->off+i+s->offs))
3205                             {
3206                                 int m = adr2idx(fw,LDR2val(fw,n->off+i+s->offs));
3207                                 if ((m >= 0) && (m < fw->size) && (strcmp((char*)(&fw->buf[m]),"Mounter.c") == 0))
3208                                 {
3209                                     fnd = 1;
3210                                 }
3211                             }
3212                             else if (isADR_PC_cond(fw,n->off+i+s->offs))
3213                             {
3214                                 int m = adr2idx(fw,ADR2adr(fw,n->off+i+s->offs));
3215                                 if ((m >= 0) && (m < fw->size) && (strcmp((char*)(&fw->buf[m]),"Mounter.c") == 0))
3216                                 {
3217                                     fnd = 1;
3218                                 }
3219                             }
3220                         }
3221                         if (fnd)
3222                             success++;
3223                         else
3224                             fail++;
3225                     }
3226                     fwAddMatch(fw,idx2adr(fw,i+n->off),success,fail,func_list[j].ver);
3227                     if (count >= MAX_MATCHES)
3228                     {
3229                         bprintf("// WARNING: too many matches for %s!\n", func_list[j].name);
3230                         break;
3231                     }
3232                 }
3233             }
3234         }
3235 
3236         // same name, so we have another version of the same function
3237         if ((func_list[j+1].name == NULL) || (strcmp(curr_name, func_list[j+1].name) != 0))
3238         {
3239             found_ev = 1;
3240             break;
3241         }
3242         j++;
3243     }
3244 
3245     if (count > 1)
3246     {
3247         qsort(matches, count, sizeof(Match), (void*)match_compare);
3248     }
3249 
3250     if (count > 0)
3251     {
3252         save_sig(curr_name, matches->ptr);
3253     }
3254 }
3255 
3256 // Output match results for function
3257 void print_results(firmware *fw, const char *curr_name, int k)
3258 {
3259     int i;
3260     int err = 0;
3261     char line[500] = "";
3262 
3263     if (func_names[k].flags & DONT_EXPORT) return;
3264 
3265     // find best match and report results
3266     osig* ostub2 = find_sig(fw->sv->stubs,curr_name);
3267 
3268     if ((count == 0)
3269         || (matches->fail > 0)
3270         || (ostub2 && (matches->ptr != ostub2->val))
3271        )
3272     {
3273         if (!ostub2 || (ostub2->type != TYPE_IGNORE))
3274             err = 1;
3275         func_names[k].flags |= BAD_MATCH;
3276     }
3277     else
3278     {
3279         if (func_names[k].flags & UNUSED) return;
3280     }
3281 
3282     // write to header (if error) or body buffer (no error)
3283     out_hdr = err;
3284 
3285     char *macro = "NHSTUB";
3286     if (strncmp(curr_name,"task_",5) == 0 ||
3287         strncmp(curr_name,"hook_",5) == 0) macro = "   DEF";
3288 
3289     if (count == 0)
3290     {
3291         if (func_names[k].flags & OPTIONAL) return;
3292         char fmt[51] = "";
3293         sprintf(fmt, "// ERROR: %%s is not found. %%%ds//--- --- ", (int)(34-strlen(curr_name)));
3294         sprintf(line+strlen(line), fmt, curr_name, "");
3295     }
3296     else
3297     {
3298         if (ostub2 || (func_names[k].flags & UNUSED))
3299             sprintf(line+strlen(line),"//%s(%-37s,0x%08x) //%3d ", macro, curr_name, matches->ptr, matches->sig);
3300         else
3301             sprintf(line+strlen(line),"%s(%-39s,0x%08x) //%3d ", macro, curr_name, matches->ptr, matches->sig);
3302 
3303         if (matches->fail > 0)
3304             sprintf(line+strlen(line),"%2d%% ", matches->success*100/(matches->success+matches->fail));
3305         else
3306             sprintf(line+strlen(line),"    ");
3307     }
3308 
3309     if (ostub2)
3310     {
3311         if (ostub2->type == TYPE_IGNORE)
3312             sprintf(line+strlen(line),"       Overridden");
3313         else if ((count > 0) && (matches->ptr == ostub2->val))
3314             sprintf(line+strlen(line),"       == 0x%08x    ",ostub2->val);
3315         else
3316             sprintf(line+strlen(line),"   *** != 0x%08x    ",ostub2->val);
3317     }
3318     else
3319         sprintf(line+strlen(line),"                        ");
3320 
3321     for (i=strlen(line)-1; i>=0 && line[i]==' '; i--) line[i] = 0;
3322     bprintf("%s\n",line);
3323 
3324     for (i=1;i<count && matches[i].fail==matches[0].fail;i++)
3325     {
3326         if (matches[i].ptr != matches->ptr)
3327         {
3328             bprintf("// ALT: %s(%s, 0x%x) // %d %d/%d\n", macro, curr_name, matches[i].ptr, matches[i].sig, matches[i].success, matches[i].fail);
3329         }
3330     }
3331 }
3332 
3333 //------------------------------------------------------------------------------------------------------------
3334 
3335 typedef struct
3336 {
3337     uint16_t mode;
3338     char *nm;
3339 } ModeMapName;
3340 
3341 ModeMapName mmnames[] = {
3342     { 32768,"MODE_AUTO" },
3343     { 32769,"MODE_M" },
3344     { 32770,"MODE_AV" },
3345     { 32771,"MODE_TV" },
3346     { 32772,"MODE_P" },
3347 
3348     { 65535,"" }
3349 };
3350 
3351 char* mode_name(uint16_t v)
3352 {
3353     int i;
3354     for (i=0; mmnames[i].mode != 65535; i++)
3355     {
3356         if (mmnames[i].mode == v)
3357             return mmnames[i].nm;
3358     }
3359 
3360     return "";
3361 }
3362 
3363 void output_modemap(firmware *fw, int k, int l)
3364 {
3365     int cnt = 0;
3366 
3367     bprintf("%08x\n",idx2adr(fw,k));
3368     // detect table member size
3369     if (fw->buf[k] & 0xffff0000)
3370     {
3371         // 16bit entries
3372         uint16_t *p = (uint16_t*)(&fw->buf[k]);
3373         k = 0;
3374         while ((*p != 0xFFFF) && (k < l*2))
3375         {
3376             osig *m = find_sig_val(fw->sv->modemap, *p);
3377             if (!m)
3378             {
3379                 char *s = mode_name(*p);
3380                 bprintf("// Mode %5d in firmware but not in current modemap",*p);
3381                 if (strcmp(s,"") != 0)
3382                     bprintf(" (%s)",s);
3383                 bprintf("\n");
3384                 cnt++;
3385             }
3386             else
3387             {
3388                 m->pct = 100;
3389             }
3390             p++;
3391             k++;
3392         }
3393     }
3394     else
3395     {
3396         // 32bit entries (first one is 0)
3397         uint32_t *p = (uint32_t*)(&fw->buf[k]);
3398         k = 0;
3399         while (k < l)
3400         {
3401             osig *m = find_sig_val(fw->sv->modemap, *p);
3402             if (!m)
3403             {
3404                 osig *m = find_sig_val(fw->sv->modemap, (*p)&0xffff);
3405                 if (!m)
3406                 {
3407                     char *s = mode_name(*p);
3408                     if ((*p)&0xffff0000)
3409                         bprintf("// Strange mode 0x%08x in firmware but not in current modemap",*p);
3410                     else
3411                         bprintf("// Mode %d in firmware but not in current modemap",*p);
3412                     if (strcmp(s,"") != 0)
3413                         bprintf(" (%s)",s);
3414                     bprintf("\n");
3415                 }
3416                 else
3417                 {
3418                     char *s = mode_name((*p)&0xffff);
3419                     if ((*p)&0xffff0000)
3420                         bprintf("// Strange mode 0x%08x in firmware, found in modemap as %d (%s)",*p,m->val,m->nm);
3421                     else
3422                         bprintf("// Mode %d in firmware, found in modemap as %d (%s)",*p,m->val,m->nm); // impossible?
3423                     if (strcmp(s,"") != 0)
3424                         bprintf(" (%s)",s);
3425                     bprintf("\n");
3426                     m->pct = 100;
3427                 }
3428                 cnt++;
3429             }
3430             else
3431             {
3432                 m->pct = 100;
3433             }
3434             p++;
3435             k++;
3436         }
3437     }
3438     osig *m = fw->sv->modemap;
3439     while (m)
3440     {
3441         if (m->pct != 100)    // not matched above?
3442         {
3443             bprintf("// Current modemap entry not found in firmware - %-24s %5d\n",m->nm,m->val);
3444             cnt++;
3445         }
3446         m = m->nxt;
3447     }
3448     if (cnt == 0)
3449     {
3450         bprintf("// No problems found with modemap table.\n");
3451     }
3452 }
3453 
3454 int find_modelist(firmware *fw, uint32_t fadr)
3455 {
3456     uint32_t j1;
3457     int k1, k2;
3458     // flashparamstable 1st entry
3459     j1 = fwval(fw,adr2idx(fw,fadr));
3460     k1 = adr2idx(fw,j1);
3461     if (k1<0)
3462         return 0;
3463     k2 = find_inst_rev(fw,isLDMFD_PC,k1-1,50);
3464     if (k2<0)
3465     {
3466         // newest vx models
3467         k2 = find_Nth_inst_rev(fw,isMOV,k1-1,16,2);
3468     }
3469     if (k2<0)
3470         return 0;
3471     k1 = find_inst_rev(fw,isLDR,k2,5);
3472     if (k1<0)
3473         return 0;
3474     j1 = LDR2val(fw,k1);
3475     k1 = adr2idx(fw,j1);
3476     if (k1<0)
3477         return 0;
3478     j1 = fwval(fw,k1);
3479     k1 = adr2idx(fw,j1);
3480     if (k1<0)
3481         return 0;
3482     k1 = find_inst_rev(fw,isMOV,k1-1,120);
3483     if (k1<0)
3484         return 0;
3485     if (fwval(fw,k1) != 0xe1a0f00e) // mov pc, lr
3486         return 0;
3487     k1--;
3488     if (!(isLDR(fw,k1) && (fwRd(fw,k1)==0))) // ldr r0,
3489         return 0;
3490     k2 = k1;
3491     j1 = LDR2val(fw,k1);
3492     k1 = adr2idx(fw,j1);
3493     if (k1<0)
3494         return 0;
3495 
3496     bprintf("// Firmware modemap table found @%08x -> ",idx2adr(fw,k1));
3497     output_modemap(fw,k1,k2-k1);
3498     return 1;
3499 
3500 }
3501 
3502 static uint32_t FlashParamsTable_address = 0;
3503 
3504 int match_FlashParamsTable2(firmware *fw, int k, uint32_t v1, __attribute__ ((unused))uint32_t v2)
3505 {
3506     if (fw->buf[k] == v1)
3507     {
3508         FlashParamsTable_address = idx2adr(fw,k);
3509         return 1;
3510     }
3511     return 0;
3512 }
3513 
3514 int match_FlashParamsTable(firmware *fw, int k, __attribute__ ((unused))uint32_t v1, __attribute__ ((unused))uint32_t v2)
3515 {
3516     if ((fw->buf[k] > fw->base) && (fw->buf[k+1] == 0x00010000) && ((fw->buf[k+2] == 0xFFFF0000)||(fw->buf[k+2] == 0xFFFF0002)))
3517     {
3518         if (search_fw(fw, match_FlashParamsTable2, idx2adr(fw,k), 0, 1))
3519             return 1;
3520     }
3521     // ixus30, 40
3522     if ((fw->buf[k+1] > fw->base) && (fw->buf[k] == 0x00000000) && (fw->buf[k+2] == 0x00000001) &&
3523         (fw->buf[k+3] == 0x00000000) && (fw->buf[k+4] == 0xffffffff))
3524     {
3525         if (search_fw(fw, match_FlashParamsTable2, idx2adr(fw,k), 0, 1))
3526             return 1;
3527     }
3528     return 0;
3529 }
3530 
3531 void find_modemap(firmware *fw)
3532 {
3533     out_hdr = 1;
3534 
3535     // Find 'FlashParamsTable'
3536     search_fw(fw, match_FlashParamsTable, 0, 0, 1);
3537     // Find 'modelist'
3538     // get flashparamstable 1st entry -> jump to that address -> search backwards 1st ldmfd_pc (mov pc,lr in newest vx) ->
3539     // search backwards ldr address -> jump to that address (this is the propertytable, not researched) ->
3540     // get 1st entry -> jump to that address -> search backwards 1st mov pc,lr ->
3541     // get modemaptable address from the prev ldr
3542     // old vx mode entries are 32 bit, all newer cameras have 16 bit entries
3543     if (FlashParamsTable_address != 0)
3544     {
3545         add_blankline();
3546         bprintf("// Check of modemap from 'platform/CAMERA/shooting.c':\n");
3547         find_modelist(fw,FlashParamsTable_address);
3548     }
3549 }
3550 
3551 //------------------------------------------------------------------------------------------------------------
3552 
3553 int find_FileAccessSem(firmware *fw)
3554 {
3555     void print_stubs_min(firmware *fw, const char *name, uint32_t fadr, uint32_t atadr);
3556     int s1 = find_str(fw, "FileSem.c");
3557     if (s1 < 0)
3558         return 0;
3559     s1 = find_inst(fw, isLDR_PC, s1+2, 16);
3560     if (s1 < 0)
3561         return 0;
3562     uint32_t u1 = LDR2val(fw, s1);
3563     if (u1 > fw->memisostart)
3564         return 0;
3565     print_stubs_min(fw,"fileio_semaphore",u1,idx2adr(fw,s1));
3566     return 1;
3567 }
3568 
3569 //------------------------------------------------------------------------------------------------------------
3570 
3571 int find_DebugAssert_argcount(firmware *fw)
3572 {
3573     int s1 = find_str_ref(fw, "Memory.c");
3574     if (s1 < 0)
3575         return 0;
3576     int k = isLDR_PC(fw, s1);
3577     if (!k)
3578         return 0;
3579     k = fwRd(fw, s1);
3580     if (k > 0)
3581         bprintf("//#define CAM_3ARG_DebugAssert 1\n");
3582     return 1;
3583 }
3584 
3585 /*
3586 int match_CAM_UNCACHED_BIT(firmware *fw, int k, int v)
3587 {
3588     if ((fw->buf[k] & 0x0FFFF000) == 0x03C00000)    // BIC
3589     {
3590         uint32_t fadr = ALUop2(fw,k);
3591         bprintf("//#undef  CAM_UNCACHED_BIT\n");
3592         bprintf("//#define CAM_UNCACHED_BIT  0x%08x // Found @0x%08x\n",fadr,idx2adr(fw,k));
3593     }
3594 
3595     return 0;
3596 }
3597 */
3598 
3599 // Search for things that go in 'platform_camera.h'
3600 void find_platform_vals(firmware *fw)
3601 {
3602     int k,k1;
3603 
3604     out_hdr = 1;
3605     add_blankline();
3606 
3607     bprintf("// Values below go in 'platform_camera.h':\n");
3608 
3609 /*
3610     bprintf("//#define CAM_DRYOS         1\n");
3611     if (fw->dryos_ver >= 39)
3612         bprintf("//#define CAM_DRYOS_2_3_R39 1 // Defined for cameras with DryOS version R39 or higher\n");
3613     if (fw->dryos_ver >= 47)
3614         bprintf("//#define CAM_DRYOS_2_3_R47 1 // Defined for cameras with DryOS version R47 or higher\n");
3615 
3616     // Find 'RAW' image size
3617     uint32_t raw_width = 0;
3618     uint32_t raw_height = 0;
3619     uint32_t kw=0, kh=0;
3620 
3621     k = find_str_ref(fw, "\r[%ld] AdjDrvType[%02ld] -> DrvType[%02");
3622     if (k >= 0)
3623     {
3624         // Width
3625         for (k1 = k-1; k1 >= k-20; k1--)
3626         {
3627             if ((fw->buf[k1] & 0x0FFF0FFF) == 0x058D0034)           // STRxx Rn, [SP,#0x34]
3628             {
3629                 if ((fw->buf[k1-1] & 0x0FFF0000) == 0x03A00000)     // MOVxx Rn, #YYY
3630                 {
3631                     raw_width = ALUop2(fw, k1-1);
3632                     kw = k1-1;
3633                 }
3634                 else if ((fw->buf[k1-2] & 0x0FFF0000) == 0x03A00000)// MOVxx Rn, #YYY
3635                 {
3636                     raw_width = ALUop2(fw, k1-2);
3637                     kw = k1-2;
3638                 }
3639                 else if (isLDR_PC_cond(fw,k1-1))
3640                 {
3641                     raw_width = LDR2val(fw,k1-1);
3642                     kw = k1-1;
3643                 }
3644                 else if (isLDR_PC_cond(fw,k1-2))
3645                 {
3646                     raw_width = LDR2val(fw,k1-2);
3647                     kw = k1-2;
3648                 }
3649             }
3650         }
3651         // Height
3652         for (k1 = k-1; k1 >= k-20; k1--)
3653         {
3654             if ((fw->buf[k1] & 0x0FFF0FFF) == 0x058D0030)           // STRxx Rn, [SP,#0x30]
3655             {
3656                 if ((fw->buf[k1-1] & 0x0FFF0000) == 0x03A00000)     // MOVxx Rn, #YYY
3657                 {
3658                     raw_height = ALUop2(fw, k1-1);
3659                     kh = k1-1;
3660                 }
3661                 else if ((fw->buf[k1-2] & 0x0FFF0000) == 0x03A00000)// MOVxx Rn, #YYY
3662                 {
3663                     raw_height = ALUop2(fw, k1-2);
3664                     kh = k1-2;
3665                 }
3666                 else if (isLDR_PC_cond(fw,k1-1))
3667                 {
3668                     raw_height = LDR2val(fw,k1-1);
3669                     kh = k1-1;
3670                 }
3671                 else if (isLDR_PC_cond(fw,k1-2))
3672                 {
3673                     raw_height = LDR2val(fw,k1-2);
3674                     kh = k1-2;
3675                 }
3676                 if ((fw->buf[k1-1] & 0x0FFF0000) == 0x02400000)     // SUBxx Rn, #YYY
3677                 {
3678                     raw_height = raw_width - ALUop2(fw, k1-1);
3679                     kh = k1-1;
3680                 }
3681             }
3682         }
3683     }
3684 
3685     if ((raw_width == 0) && (raw_height == 0))
3686     {
3687         k = find_str_ref(fw, " CrwAddress %lx, CrwSize H %ld V %ld\r");
3688         if (k >= 0)
3689         {
3690             // Width
3691             for (k1=k-1; k1>=k-5; k1--)
3692             {
3693                 if ((fw->buf[k1] & 0xFFFFF000) == 0xE3A02000)       // MOV R2, #nnn
3694                 {
3695                     raw_width = ALUop2(fw,k1);
3696                     kw = k1;
3697                 }
3698                 else
3699                 if (isLDR_PC(fw,k1) && ((fw->buf[k1]& 0x0000F000) == 0x00002000))   // LDR R2, =nnn
3700                 {
3701                     raw_width = LDR2val(fw,k1);
3702                     kw = k1;
3703                 }
3704             }
3705             // Height
3706             for (k1=k-1; k1>=k-5; k1--)
3707             {
3708                 if ((fw->buf[k1] & 0xFFFFF000) == 0xE3A03000)       // MOV R3, #nnn
3709                 {
3710                     raw_height = ALUop2(fw,k1);
3711                     kh = k1;
3712                 }
3713                 else
3714                 if (isLDR_PC(fw,k1) && ((fw->buf[k1]& 0x0000F000) == 0x00003000))   // LDR R3, =nnn
3715                 {
3716                     raw_height = LDR2val(fw,k1);
3717                     kh = k1;
3718                 }
3719                 else
3720                 if ((fw->buf[k1] & 0xFFFFF000) == 0xE2423000)       // SUB R3, R2, #nnn
3721                 {
3722                     raw_height = raw_width - ALUop2(fw,k1);
3723                     kh = k1;
3724                 }
3725             }
3726         }
3727     }
3728 
3729     if (raw_width != 0)
3730     {
3731         bprintf("//#define CAM_RAW_ROWPIX    %d // Found @0x%08x\n",raw_width,idx2adr(fw,kw));
3732     }
3733     else
3734     {
3735         bprintf("//#define CAM_RAW_ROWPIX    *** Not Found ***\n");
3736     }
3737     if (raw_height != 0)
3738     {
3739         bprintf("//#define CAM_RAW_ROWS      %d // Found @0x%08x\n",raw_height,idx2adr(fw,kh));
3740     }
3741     else
3742     {
3743         bprintf("//#define CAM_RAW_ROWS      *** Not Found ***\n");
3744     }
3745 
3746     // Find 'CAM_UNCACHED_BIT'
3747     search_saved_sig(fw, "FreeUncacheableMemory", match_CAM_UNCACHED_BIT, 0, 0, 8);
3748 */
3749 
3750     // Find 'PARAM_CAMERA_NAME'
3751     if (FlashParamsTable_address != 0)
3752     {
3753         k1 = adr2idx(fw,FlashParamsTable_address);
3754         for (k=k1; k<k1+20; k++)
3755         {
3756             uint32_t fadr = fwval(fw,k);
3757             int k2 = adr2idx(fw,fadr);
3758             if (idx_valid(fw,k2))
3759             {
3760                 uint32_t sadr = fwval(fw,k2);
3761                 k2 = adr2idx(fw,sadr);
3762                 if (idx_valid(fw,k2))
3763                 {
3764                     char *s = adr2ptr(fw,sadr);
3765                     if (((fw->cam != 0) && (strcmp(s,fw->cam) == 0)) || (strcmp(s,"Unknown") == 0))
3766                     {
3767                         bprintf("//#define PARAM_CAMERA_NAME %d // Found @0x%08x\n",k-k1,fadr);
3768                         break;
3769                     }
3770                 }
3771             }
3772         }
3773     }
3774 
3775     find_DebugAssert_argcount(fw);
3776 }
3777 
3778 //------------------------------------------------------------------------------------------------------------
3779 
3780 uint32_t find_viewport_address(firmware *fw, int *kout)
3781 {
3782     int k, k1;
3783 
3784     // find viewwport address for 'vid_get_viewport_fb'
3785     k = find_str_ref(fw, "VRAM Address  : %p\r");
3786     if (k >= 0)
3787     {
3788         for (k1=k-1; k1>k-8; k1--)
3789         {
3790             if (isLDR(fw,k1) && isLDR(fw,k1+1))
3791             {
3792                 uint32_t v1 = LDR2val(fw,k1);
3793                 uint32_t v2 = LDR2val(fw,k1+1);
3794                 if (v2 > v1) v1 = v2;
3795                 *kout = k1;
3796                 return v1;
3797             }
3798         }
3799     }
3800 
3801     *kout = -1;
3802     return 0;
3803 }
3804 
3805 int match_vid_get_bitmap_fb(firmware *fw, int k, __attribute__ ((unused))int v)
3806 {
3807     if (isBL(fw,k-1) && // BL
3808         isLDR_PC(fw,k))
3809     {
3810         uint32_t v1 = LDR2val(fw,k);
3811         bprintf("//void *vid_get_bitmap_fb()        { return (void*)0x%08x; }             // Found @0x%08x\n",v1,idx2adr(fw,k));
3812         return 1;
3813     }
3814     else
3815     if (isBL(fw,k-1) && // BL
3816         (isLDR_PC(fw,k+1)))
3817     {
3818         uint32_t v1 = LDR2val(fw,k+1);
3819         bprintf("//void *vid_get_bitmap_fb()        { return (void*)0x%08x; }             // Found @0x%08x\n",v1,idx2adr(fw,k));
3820         return 1;
3821     }
3822 
3823     return 0;
3824 }
3825 
3826 int match_get_flash_params_count(firmware *fw, int k, __attribute__ ((unused))int v)
3827 {
3828     if ((fw->buf[k] & 0xFFF00FFF) == 0xE3C00901)    // BIC Rn, Rn, #0x4000
3829     {
3830         uint32_t r = (fw->buf[k] & 0x0000F000)<<4;       // Register
3831         int n;
3832         for (n=k+1; n<k+20; n++)
3833         {
3834             if (((fw->buf[n] & 0xFFF00000) == 0xE3500000) && ((fw->buf[n] & 0x000F0000) == r))  // CMP, Rn #val
3835             {
3836                 // the found value needs to be increased by one (BLS instruction follows)
3837                 bprintf("//int get_flash_params_count(void) { return 0x%02x; }                          // Found @0x%08x\n",(fw->buf[n]&0xFFF)+1,idx2adr(fw,n));
3838                 return 1;
3839             }
3840         }
3841     }
3842 
3843     return 0;
3844 }
3845 
3846 // based on match_get_flash_params_count
3847 int match_uiprop_count(firmware *fw, int k, __attribute__ ((unused))int v)
3848 {
3849     uint32_t uic = 0;
3850     int j = -1;
3851     if (isB(fw, k+6))
3852     {
3853         j = idxFollowBranch(fw,k+6,0x01000001);
3854     }
3855     if (j > 0)
3856     {
3857         int m;
3858         for (m=j; m<j+32; m++)
3859         {
3860             if (isLDMFD_PC(fw,m)) break;
3861             if (isCMP(fw,m))
3862             {
3863                 uint32_t v1 = ALUop2(fw,m);
3864                 if ((v1 > 0x10)&&(v1 < 0xa0))
3865                 {
3866                     uic = v1+1; // BLS follows this CMP instruction
3867                     j = m;
3868                     break;
3869                 }
3870             }
3871         }
3872     }
3873 
3874     if (uic == 0) return 0;
3875 
3876     char *name = "uiprop_count";
3877     osig *o = find_sig(fw->sv->stubs_min,name);
3878     if (o)
3879     {
3880         bprintf("//DEF_CONST(%-34s,0x%08x) // Found @0x%08x",name,uic,idx2adr(fw,j));
3881         if (uic != o->val)
3882         {
3883             bprintf(", ** != ** stubs_min = 0x%08x (%s)",o->val,o->sval);
3884         }
3885         else
3886         {
3887             bprintf(",          stubs_min = 0x%08x (%s)",o->val,o->sval);
3888         }
3889     }
3890     else
3891     {
3892         bprintf("DEF_CONST(%-34s,0x%08x) // Found @0x%08x",name,uic,idx2adr(fw,j));
3893     }
3894     bprintf("\n");
3895     return 1;
3896 }
3897 
3898 int isMOVLRPC(firmware *fw, int offset)
3899 {
3900     return (fwval(fw,offset) == 0xE1A0E00F); // MOV LR, PC
3901 }
3902 
3903 int match_imager_active(firmware *fw, int k, __attribute__ ((unused))int v)
3904 {
3905     int gotit = 0;
3906     int reg = -1;
3907     int o = 0;
3908     uint32_t adr,where;
3909     if (fwval(fw,k) == 0xe49df004) // POP {PC}
3910     {
3911         int k1 = find_inst_rev(fw, isBL, k-1, 10);
3912         if (k1 == -1)
3913             return 0;
3914         uint32_t a;
3915         int k2 = k1 - 8;
3916         for (k1=k1-1;k1>=k2;k1--)
3917         {
3918             if (isLDR(fw,k1) || isADR(fw,k1))
3919             {
3920                 if (isADR(fw,k1))
3921                 {
3922                     a = ADR2adr(fw, k1);
3923                 }
3924                 else
3925                 {
3926                     a = LDR2val(fw, k1);
3927                 }
3928                 if ((a>fw->base) && ((a&3) == 0))
3929                 {
3930                     int k3 = adr2idx(fw, a);
3931                     if (isSTMFD_LR(fw,k3))
3932                     {
3933                         k3 = find_inst(fw, isMOVLRPC, k3+1, 6);
3934                         if (k3 != -1)
3935                         {
3936                             int k4;
3937                             for(k4=5; k4>0; k4--)
3938                             {
3939                                 if (isSTR_cond(fw,k3+k4))
3940                                 {
3941                                     reg = fwRn(fw,k3+k4);
3942                                     o = fwval(fw,k3+k4) & 0xff; // offset, should be around 4
3943                                     where = idx2adr(fw,k3+k4);
3944                                 }
3945                                 if (reg>=0 && isLDR_cond(fw,k3+k4) && fwRd(fw,k3+k4)==reg)
3946                                 {
3947                                     adr = LDR2val(fw,k3+k4);
3948                                     if (adr < fw->memisostart)
3949                                     {
3950                                         gotit = 1;
3951                                         break;
3952                                     }
3953                                 }
3954                             }
3955                             if (gotit)
3956                                 break;
3957                         }
3958                     }
3959                 }
3960             }
3961         }
3962     }
3963     if (gotit)
3964     {
3965         bprintf("DEF(%-40s,0x%08x) // Found @0x%08x (0x%x + %i)\n","imager_active",adr+o,where,adr,o);
3966         return 1;
3967     }
3968     return 0;
3969 }
3970 
3971 // Search for things that go in 'lib.c'
3972 void find_lib_vals(firmware *fw)
3973 {
3974     //int k,k1;
3975 
3976     out_hdr = 1;
3977     add_blankline();
3978 
3979     bprintf("// Values below go in 'lib.c':\n");
3980 /*
3981     // Find 'vid_get_bitmap_fb'
3982     search_saved_sig(fw, "DispCon_ShowBitmapColorBar", match_vid_get_bitmap_fb, 0, 1, 30);
3983 
3984     // find 'vid_get_viewport_fb'
3985     uint32_t v = find_viewport_address(fw,&k);
3986     if (k >= 0)
3987     {
3988         bprintf("//void *vid_get_viewport_fb()      { return (void*)0x%08x; }             // Found @0x%08x\n",v,idx2adr(fw,k));
3989     }
3990 
3991     // find 'vid_get_viewport_fb_d'
3992     static int fbd[3][3] =
3993     {
3994         { -2, -3,  1 },
3995         {  1,  3,  4 },
3996         { -1, -2,  1 },
3997     };
3998     int sadr = find_str(fw, "ImagePlayer.c");
3999     k = find_nxt_str_ref(fw, sadr, -1);
4000     int found = 0;
4001     while ((k >= 0) && !found)
4002     {
4003         int f;
4004         for (f=0; f<3 && !found; f++)
4005         {
4006             if (isLDR(fw,k+fbd[f][0]) && isLDR(fw,k+fbd[f][1]) && isLDR(fw,k+fbd[f][2]))
4007             {
4008                 int reg = fw->buf[k+fbd[f][2]] & 0x000F0000;    // Index register used
4009                 int ka = 0;
4010                 if (((fw->buf[k+fbd[f][0]] & 0x0000F000) << 4) == reg)      { ka = k+fbd[f][0]; }
4011                 else if (((fw->buf[k+fbd[f][1]] & 0x0000F000) << 4) == reg) { ka = k+fbd[f][1]; }
4012                 if (ka > 0)
4013                 {
4014                     uint32_t adr = LDR2val(fw,ka);
4015                     for (k1=k+2; k1<k+20; k1++)
4016                     {
4017                         if (isSTR(fw,k1) && ((fw->buf[k1] & 0x000F0000) == reg))
4018                         {
4019                             uint32_t ofst = fw->buf[k1] & 0x00000FFF;
4020                             bprintf("DEF(%-40s,0x%08x) // Found 0x%04x (@0x%08x) + 0x%02x (@0x%08x)\n","viewport_fb_d",adr+ofst,adr,idx2adr(fw,ka),ofst,idx2adr(fw,k1));
4021                             bprintf("//void *vid_get_viewport_fb_d()    { return (void*)(*(int*)(0x%04x+0x%02x)); } // Found @0x%08x & 0x%08x\n",adr,ofst,idx2adr(fw,ka),idx2adr(fw,k1));
4022                             found = 1;
4023                             break;
4024                         }
4025                     }
4026                 }
4027             }
4028         }
4029         k = find_nxt_str_ref(fw, sadr, k);
4030     }
4031 
4032     // find 'camera_jpeg_count_str'
4033     k = find_str_ref(fw, "9999");
4034     if (k >= 0)
4035     {
4036         if (isLDR(fw,k-1) && isBL(fw,k+1))
4037         {
4038             uint32_t v1 = LDR2val(fw,k-1);
4039             bprintf("DEF(%-40s,0x%08x) // Found @0x%08x\n","jpeg_count_str",v1,idx2adr(fw,k-1));
4040             bprintf("//char *camera_jpeg_count_str()    { return (char*)0x%08x; }             // Found @0x%08x\n",v1,idx2adr(fw,k-1));
4041         }
4042     }
4043 
4044     // find 'hook_raw_size'
4045     k = find_str_ref(fw, "CRAW BUFF SIZE  %p");
4046     if (k >= 0)
4047     {
4048         if (isLDR(fw,k-1))
4049         {
4050             uint32_t craw_bufsize = LDR2val(fw,k-1);
4051             bprintf("//long hook_raw_size()             { return 0x%08x; }                    // Found @0x%08x\n",craw_bufsize,idx2adr(fw,k-1));
4052         }
4053     }
4054 */
4055     // Find value for 'get_flash_params_count'
4056     search_saved_sig(fw, "GetParameterData", match_get_flash_params_count, 0, 0, 30);
4057 }
4058 
4059 //------------------------------------------------------------------------------------------------------------
4060 
4061 void print_stubs_min(firmware *fw, const char *name, uint32_t fadr, uint32_t atadr)
4062 {
4063     osig *o = find_sig(fw->sv->stubs_min,name);
4064     if (o)
4065     {
4066         bprintf("//DEF(%-40s,0x%08x) // Found @0x%08x",name,fadr,atadr);
4067         if (fadr != o->val)
4068         {
4069             bprintf(", ** != ** stubs_min = 0x%08x (%s)",o->val,o->sval);
4070         }
4071         else
4072         {
4073             bprintf(",          stubs_min = 0x%08x (%s)",o->val,o->sval);
4074         }
4075     }
4076     else
4077     {
4078         bprintf("DEF(%-40s,0x%08x) // Found @0x%08x",name,fadr,atadr);
4079     }
4080     bprintf("\n");
4081 }
4082 
4083 uint32_t exm_typ_tbl=0, exm_typ_cnt=0;
4084 int print_exmem_types(firmware *fw)
4085 {
4086     if (exm_typ_tbl==0 || exm_typ_cnt==0)
4087         return 1;
4088     bprintf("// EXMEM types:\n");
4089     int ii = adr2idx(fw, exm_typ_tbl);
4090     uint32_t n;
4091     for (n=0; n<exm_typ_cnt; n++)
4092     {
4093         bprintf("// %s %i\n",adr2ptr(fw, fwval(fw,ii+n)),n);
4094     }
4095     bprintf("\n");
4096     return 0;
4097 }
4098 
4099 int find_exmem_alloc_table(firmware *fw)
4100 {
4101     int i = get_saved_sig(fw,"exmem_assert");
4102     if (i < 0)
4103     {
4104         return 0;
4105     }
4106     i = adr2idx(fw, func_names[i].val);
4107     uint32_t u;
4108     int n;
4109     for (n=1; n<16; n++)
4110     {
4111         if ( ((fwval(fw,i+n)&0xffff0000)==0xe59f0000) ) // ldr rx, [pc, #imm]
4112         {
4113             u = LDR2val(fw, i+n);
4114             if (u>fw->base && u<fw->base+fw->size*4-4 && (u&3)==0)
4115             {
4116                 break;
4117             }
4118         }
4119         u = 0;
4120     }
4121     if (u)
4122     {
4123         exm_typ_tbl = u;
4124         int ii = adr2idx(fw, exm_typ_tbl);
4125         char* extyp;
4126         for (n=0; n<32; n++)
4127         {
4128             if ( (fwval(fw,ii+n)!=0) && isASCIIstring(fw, fwval(fw,ii+n)) )
4129             {
4130                 extyp = adr2ptr(fw, fwval(fw,ii+n));
4131                 if ( strncmp(extyp,"EXMEM",5)==0 )
4132                 {
4133                     exm_typ_cnt++;
4134                 }
4135             }
4136             else
4137             {
4138                 break;
4139             }
4140         }
4141     }
4142 
4143     for (n=1; n<54; n++)
4144     {
4145         if ( ((fwval(fw,i+n)&0xffff0000)==0xe59f0000) ) // ldr rx, [pc, #imm]
4146         {
4147             u = LDR2val(fw, i+n);
4148             if (u>fw->data_start && u<fw->data_start+fw->data_len*4 && (fwRd(fw,i+n)>3))
4149             {
4150                 break;
4151             }
4152         }
4153         u = 0;
4154     }
4155     if (u)
4156     {
4157         print_stubs_min(fw,"exmem_alloc_table",u,idx2adr(fw,i+n));
4158     }
4159     if (exm_typ_tbl)
4160     {
4161         print_stubs_min(fw,"exmem_types_table",exm_typ_tbl,exm_typ_tbl);
4162     }
4163     if (exm_typ_cnt)
4164     {
4165         bprintf("DEF_CONST(%-34s,0x%08x)\n","exmem_type_count",exm_typ_cnt);
4166     }
4167     return 0;
4168 }
4169 
4170 int match_levent_table(firmware *fw, int k, __attribute__ ((unused))uint32_t v1, __attribute__ ((unused))uint32_t v2)
4171 {
4172     if ((fw->buf[k] > fw->base) && (fw->buf[k+1] == 0x00000800) && (fw->buf[k+2] == 0x00000002))
4173     {
4174         print_stubs_min(fw,"levent_table",idx2adr(fw,k),idx2adr(fw,k));
4175 #ifdef PRINT_LEVENT_TABLE
4176         uint32_t levent_tbl = idx2adr(fw,k);
4177         void write_levent_table_dump(firmware*, uint32_t);
4178         write_levent_table_dump(fw, levent_tbl);
4179 #endif
4180     }
4181     return 0;
4182 }
4183 
4184 int match_movie_status(firmware *fw, int k, __attribute__ ((unused))uint32_t v1, __attribute__ ((unused))uint32_t v2)
4185 {
4186     if (isLDR_PC(fw, k) &&                              // LDR R0, =base
4187         ((fw->buf[k+1] & 0xFE0F0000) == 0xE20F0000) &&  // ADR R1, =sub
4188         isSTR(fw, k+2) &&                               // STR R1, [R0,N]
4189         (fw->buf[k+3] == 0xE3A01003) &&                 // MOV R1, 3
4190         isSTR(fw, k+4) &&                               // STR R1, [R0,ofst]
4191         (LDR2val(fw,k) < fw->base))
4192     {
4193         uint32_t base = LDR2val(fw,k);
4194         uint32_t ofst = fw->buf[k+4] & 0x00000FFF;
4195         print_stubs_min(fw,"movie_status",base+ofst,idx2adr(fw,k));
4196         return 1;
4197     }
4198     else
4199     if (isLDR_PC(fw, k) &&                              // LDR R1, =sub
4200         isLDR_PC(fw, k+1) &&                            // LDR R0, =base
4201         isSTR(fw, k+2) &&                               // STR R1, [R0,N]
4202         (fw->buf[k+3] == 0xE3A01003) &&                 // MOV R1, 3
4203         isSTR(fw, k+4) &&                               // STR R1, [R0,ofst]
4204         (LDR2val(fw,k+1) < fw->base))
4205     {
4206         uint32_t base = LDR2val(fw,k+1);
4207         uint32_t ofst = fw->buf[k+4] & 0x00000FFF;
4208         print_stubs_min(fw,"movie_status",base+ofst,idx2adr(fw,k));
4209         return 1;
4210     }
4211     else
4212     if (isLDR_PC(fw, k) &&                                      // LDR Rx, =base
4213         isLDR(fw, k+1) && (fwRd(fw,k) == fwRn(fw,k+1)) &&       // LDR R0, [Rx, ...]
4214         isCMP(fw, k+2) && (fwRd(fw,k+2) == fwRd(fw,k+1)) &&     // CMP R0, #...
4215         (fwval(fw,k+3) == 0x03A00005) &&
4216         isSTR_cond(fw, k+4) && (fwRn(fw,k+4) == fwRd(fw,k)) &&  // STRxx R0, [Rx,ofst]
4217         (LDR2val(fw,k) < fw->base))
4218     {
4219         uint32_t base = LDR2val(fw,k);
4220         uint32_t ofst = fwOp2(fw,k+4);
4221         print_stubs_min(fw,"movie_status",base+ofst,idx2adr(fw,k));
4222         return 1;
4223     }
4224     return 0;
4225 }
4226 
4227 int match_full_screen_refresh(firmware *fw, int k, __attribute__ ((unused))uint32_t v1, __attribute__ ((unused))uint32_t v2)
4228 {
4229     if (((fw->buf[k] & 0xFF1FF000) == 0xE51F0000) &&    // LDR R0, =base
4230         (fw->buf[k+1] == 0xE5D01000) &&                 // LDRB R1, [R0]
4231         (fw->buf[k+2] == 0xE3811002) &&                 // ORR R1, R1, #2
4232         (fw->buf[k+3] == 0xE5C01000) &&                 // STRB R1, [R0]
4233         isBX_LR(fw,k+4))                                // BX LR
4234     {
4235         uint32_t base = LDR2val(fw,k);
4236         print_stubs_min(fw,"full_screen_refresh",base,idx2adr(fw,k));
4237     }
4238     return 0;
4239 }
4240 
4241 int match_canon_shoot_menu_active(firmware *fw, int k, __attribute__ ((unused))uint32_t v1, __attribute__ ((unused))uint32_t v2)
4242 {
4243     if (((fw->buf[k]   & 0xFF1FF000) == 0xE51F1000) &&  // LDR R1, =base
4244         ((fw->buf[k+1] & 0xFFFFF000) == 0xE5D10000) &&  // LDRB R0, [R1, #n]
4245         (fw->buf[k+2] == 0xE2800001) &&                 // ADD R0, R0, #1
4246         ((fw->buf[k+3] & 0xFFFFF000) == 0xE5C10000) &&  // STRB R0, [R1, #n]
4247         (isB(fw,k+4)))                                  // B
4248     {
4249         uint32_t base = LDR2val(fw,k);
4250         uint32_t ofst = fw->buf[k+1] & 0x00000FFF;
4251         print_stubs_min(fw,"canon_shoot_menu_active",base+ofst,idx2adr(fw,k));
4252     }
4253     else
4254     if (((fw->buf[k]   & 0xFF1FF000) == 0xE51F0000) &&  // LDR R0, =base
4255         ((fw->buf[k+1] & 0xFFFFF000) == 0xE5D01000) &&  // LDRB R1, [R0, #n]
4256         (fw->buf[k+2] == 0xE2811001) &&                 // ADD R1, R1, #1
4257         ((fw->buf[k+3] & 0xFFFFF000) == 0xE5C01000) &&  // STRB R1, [R0, #n]
4258         (isB(fw,k+4)))                                  // B
4259     {
4260         uint32_t base = LDR2val(fw,k);
4261         uint32_t ofst = fw->buf[k+1] & 0x00000FFF;
4262         print_stubs_min(fw,"canon_shoot_menu_active",base+ofst,idx2adr(fw,k));
4263     }
4264     return 0;
4265 }
4266 
4267 int match_playrec_mode(firmware *fw, int k, __attribute__ ((unused))uint32_t v1, __attribute__ ((unused))uint32_t v2)
4268 {
4269     if (((fw->buf[k]    & 0xFF1FF000) == 0xE51F1000) && // LDR R1, =base
4270         ((fw->buf[k+1]  & 0xFFFFF000) == 0xE5810000) && // STR R0, [R1, #n]
4271         ((fw->buf[k+3]  & 0xFF1FF000) == 0xE51F0000) && // LDR R0, =base
4272         ((fw->buf[k+4]  & 0xFFFFF000) == 0xE5900000) && // LDR R0, [R0, #n]
4273         ((fw->buf[k+6]  & 0xFF1FF000) == 0xE51F1000) && // LDR R1, =base
4274         ((fw->buf[k+9]  & 0xFF1FF000) == 0xE51F0000) && // LDR R0, =base
4275         ((fw->buf[k+12] & 0xFF1FF000) == 0xE51F1000) && // LDR R1, =base
4276         ((fw->buf[k+15] & 0xFF1FF000) == 0xE51F0000) && // LDR R0, =base
4277         ((fw->buf[k+18] & 0xFF1FF000) == 0xE51F1000) && // LDR R1, =base
4278         (LDR2val(fw,k) == LDR2val(fw,k+3)) &&
4279         (LDR2val(fw,k) == LDR2val(fw,k+6)) &&
4280         (LDR2val(fw,k) == LDR2val(fw,k+9)) &&
4281         (LDR2val(fw,k) == LDR2val(fw,k+12)) &&
4282         (LDR2val(fw,k) == LDR2val(fw,k+15)) &&
4283         (LDR2val(fw,k) == LDR2val(fw,k+18)))
4284     {
4285         uint32_t base = LDR2val(fw,k);
4286         uint32_t ofst = fw->buf[k+1] & 0x00000FFF;
4287         print_stubs_min(fw,"playrec_mode",base+ofst,idx2adr(fw,k));
4288     }
4289     return 0;
4290 }
4291 
4292 int match_some_flag_for_af_scan(firmware *fw, int k, __attribute__ ((unused))uint32_t v1, __attribute__ ((unused))uint32_t v2)
4293 {
4294     if (isB(fw,k)   &&  // B loc
4295         isB(fw,k+1) &&  // B loc
4296         isB(fw,k+2) &&  // B loc
4297         isB(fw,k+3) &&  // B loc
4298         isB(fw,k+4) &&  // B loc
4299         isB(fw,k+5) &&  // B loc
4300         isB(fw,k+6) &&  // B loc
4301         isB(fw,k+7) &&  // B loc
4302         (followBranch(fw,idx2adr(fw,k),1) != followBranch(fw,idx2adr(fw,k+1),1)) &&
4303         (followBranch(fw,idx2adr(fw,k),1) == followBranch(fw,idx2adr(fw,k+2),1)) &&
4304         (followBranch(fw,idx2adr(fw,k),1) == followBranch(fw,idx2adr(fw,k+3),1)) &&
4305         (followBranch(fw,idx2adr(fw,k),1) != followBranch(fw,idx2adr(fw,k+4),1)) &&
4306         (followBranch(fw,idx2adr(fw,k),1) != followBranch(fw,idx2adr(fw,k+5),1)) &&
4307         (followBranch(fw,idx2adr(fw,k),1) == followBranch(fw,idx2adr(fw,k+6),1)) &&
4308         (followBranch(fw,idx2adr(fw,k),1) == followBranch(fw,idx2adr(fw,k+7),1)) &&
4309         (isLDR_PC(fw,adr2idx(fw,followBranch(fw,idx2adr(fw,k),1)))))    // LDR R0, =base
4310     {
4311         uint32_t base = LDR2val(fw,adr2idx(fw,followBranch(fw,idx2adr(fw,k),1)));
4312         if (base < fw->base)
4313             print_stubs_min(fw,"some_flag_for_af_scan",base,followBranch(fw,idx2adr(fw,k),1));
4314     }
4315     return 0;
4316 }
4317 
4318 int match_palette_data(firmware *fw, int k, __attribute__ ((unused))uint32_t v1, __attribute__ ((unused))uint32_t v2)
4319 {
4320     if ((fw->buf[k] == 0) && (fw->buf[k+1] == 0x00FF0000) &&
4321         (fw->buf[k+577] == 1) && (fw->buf[k+578] == 0x00FF0000) &&
4322         (fw->buf[k+1154] == 2) && (fw->buf[k+1155] == 0x00FF0000))
4323     {
4324         return idx2adr(fw,k);
4325     }
4326     else if ((fw->buf[k] == 0) && (fw->buf[k+1] == 0x00FF0000) &&
4327              (fw->buf[k+513] == 1) && (fw->buf[k+514] == 0x00FF0000) &&
4328              (fw->buf[k+1026] == 2) && (fw->buf[k+1027] == 0x00FF0000))
4329     {
4330         return idx2adr(fw,k);
4331     }
4332     return 0;
4333 }
4334 
4335 int match_palette_buffer_offset(firmware *fw, int k)
4336 {
4337     int idx2 = idxFollowBranch(fw, k, 0x01000001);
4338     if (isLDR(fw, idx2+2) && isBL(fw, idx2+3))
4339     {
4340         uint32_t palette_size = LDR2val(fw,idx2+2);
4341         if (palette_size >= 0x400)
4342         {
4343             bprintf("// Offset from start of palette_buffer to color data = %d (Found @0x%08x)\n",palette_size-0x400,idx2adr(fw,idx2+2));
4344             return 1;
4345         }
4346     }
4347     else if (isADR(fw, idx2+2) && isBL(fw, idx2+3))
4348     {
4349         uint32_t palette_size = ALUop2(fw,idx2+2);
4350         if (palette_size >= 0x400)
4351         {
4352             bprintf("// Offset from start of palette_buffer to color data = %d (Found @0x%08x)\n",palette_size-0x400,idx2adr(fw,idx2+2));
4353             return 1;
4354         }
4355     }
4356     return 0;
4357 }
4358 
4359 int match_palette_data3(firmware *fw, int k, uint32_t palette_data, __attribute__ ((unused))uint32_t v2)
4360 {
4361     if (isLDR_PC(fw, k) && (LDR2val(fw,k) == palette_data) && isLDR_PC(fw,k-1) && isLDR_PC(fw,k-6) && isLDR(fw,k-5))
4362     {
4363         uint32_t palette_control = LDR2val(fw,k-6);
4364         int ptr_offset = fwOp2(fw,k-5);
4365         uint32_t fadr = find_inst_rev(fw, isSTMFD_LR, k-7, 30);
4366         if (fadr > 0)
4367         {
4368             int k1 = search_fw(fw, find_B, fadr, 0, 1);
4369             if ((k1 > 0) && isLDR_PC(fw,k1-2) && isLDR(fw,k1-1) && (LDR2val(fw,k1-2) == palette_control))
4370             {
4371                 int active_offset = fwOp2(fw,k1-1);
4372                 print_stubs_min(fw,"active_palette_buffer",palette_control+active_offset,idx2adr(fw,k1-1));
4373                 print_stubs_min(fw,"palette_buffer_ptr",palette_control+ptr_offset,idx2adr(fw,k-5));
4374                 if (isBL(fw,k+8))
4375                 {
4376                     fadr = followBranch(fw, idx2adr(fw,k+8), 0x01000001);
4377                     int idx = adr2idx(fw, fadr);
4378                     if (isLDR(fw, idx+2) && isBL(fw, idx+3))
4379                     {
4380                         uint32_t palette_size = LDR2val(fw,idx+2);
4381                         if (palette_size >= 0x400)
4382                         {
4383                             bprintf("// Offset from start of palette_buffer to color data = %d (Found @0x%08x)\n",palette_size-0x400,idx2adr(fw,idx+2));
4384                         }
4385                     }
4386                 }
4387                 return 1;
4388             }
4389         }
4390     }
4391     return 0;
4392 }
4393 
4394 int match_palette_data2(firmware *fw, int k, uint32_t v1, uint32_t v2)
4395 {
4396     if (isLDR(fw,k) && (LDR2val(fw,k) == v1))
4397     {
4398         int k1;
4399         for (k1=k+1; k1<k+20; k1++)
4400         {
4401             if (isBL(fw,k1) && isLDMFD(fw,k1+2))
4402             {
4403                 uint32_t fadr = followBranch(fw, idx2adr(fw,k1), 0x01000001);
4404                 int idx = adr2idx(fw, fadr);
4405                 int k2;
4406                 for (k2=idx; k2<idx+40; k2++)
4407                 {
4408                     if (isSTR(fw,k2) && isLDMFD(fw,k2+1))
4409                     {
4410                         int ptr_offset = fwval(fw,k2) & 0xFFF;
4411                         print_stubs_min(fw,"palette_buffer_ptr",v2+ptr_offset,idx2adr(fw,k2));
4412                         int found = 0;
4413                         for (k=idx; (k<idx+16) && !found; k++)
4414                         {
4415                             if (isBL(fw,k) && isCMP(fw,k+1) && isADR_PC(fw,k+2))
4416                             {
4417                                 fadr = ADR2adr(fw,k+2);
4418                                 idx = adr2idx(fw, fadr);
4419                                 int k3;
4420                                 for (k3=idx; (k3<idx+16) && !found; k3++)
4421                                 {
4422                                     if (isBL(fw,k3))
4423                                     {
4424                                         if (match_palette_buffer_offset(fw,k3))
4425                                             return 1;
4426                                     }
4427                                 }
4428                             }
4429                         }
4430                         return 1;
4431                     }
4432                 }
4433             }
4434             else if (isLDR_cond(fw,k1) && isLDMFD(fw,k1+2) && isBL(fw,k1-2))
4435             {
4436                 int ptr_offset = fwval(fw,k1) & 0xFFF;
4437                 print_stubs_min(fw,"palette_buffer_ptr",v2+ptr_offset,idx2adr(fw,k1));
4438                 match_palette_buffer_offset(fw, k1-2);
4439                 return 1;
4440             }
4441         }
4442     }
4443     return 0;
4444 }
4445 
4446 int match_SavePaletteData(firmware *fw, int idx, int palette_data)
4447 {
4448     if (isBL(fw,idx+13))
4449     {
4450         uint32_t fadr = followBranch(fw, idx2adr(fw,idx+13), 0x01000001);
4451         idx = adr2idx(fw, fadr);
4452         if (isLDR(fw,idx) && isLDR(fw,idx+1) && isB(fw,idx+2))
4453         {
4454             uint32_t palette_control = LDR2val(fw,idx);
4455             print_stubs_min(fw,"palette_control",palette_control,idx2adr(fw,idx));
4456             int active_offset = fwval(fw,idx+1) & 0xFFF;
4457             print_stubs_min(fw,"active_palette_buffer",palette_control+active_offset,idx2adr(fw,idx+1));
4458             fadr = followBranch(fw,idx2adr(fw,idx+2),1);
4459             idx = adr2idx(fw, fadr);
4460             if (isLDR(fw,idx+17) && isLDR(fw,idx+18) && isLDR(fw,idx+12) && (LDR2val(fw,idx+12) == palette_control))
4461             {
4462                 if (isLDR(fw,idx+13))
4463                 {
4464                     int ptr_offset = fwval(fw,idx+13) & 0xFFF;
4465                     print_stubs_min(fw,"palette_buffer_ptr",palette_control+ptr_offset,idx2adr(fw,idx+13));
4466                 }
4467                 int palette_buffer;
4468                 if ((fwval(fw,idx+18) & 0x0000F000) == 0)
4469                 {
4470                     palette_buffer = LDR2val(fw,idx+17);
4471                     print_stubs_min(fw,"palette_buffer",palette_buffer,idx2adr(fw,idx+17));
4472                 }
4473                 else
4474                 {
4475                     palette_buffer = LDR2val(fw,idx+18);
4476                     print_stubs_min(fw,"palette_buffer",palette_buffer,idx2adr(fw,idx+18));
4477                 }
4478                 if (isBL(fw,idx+26))
4479                 {
4480                     fadr = followBranch(fw, idx2adr(fw,idx+26), 0x01000001);
4481                     idx = adr2idx(fw, fadr);
4482                     if (isLDR(fw, idx+2) && isBL(fw, idx+3))
4483                     {
4484                         uint32_t palette_size = LDR2val(fw,idx+2);
4485                         if (palette_size >= 0x400)
4486                         {
4487                             bprintf("// Offset from start of palette_buffer to color data = %d (Found @0x%08x)\n",palette_size-0x400,idx2adr(fw,idx+2));
4488                         }
4489                     }
4490                 }
4491             }
4492         }
4493         else if (isLDR(fw,idx) && isLDR(fw,idx+6) && isLDR(fw,idx+7) && isBX(fw,idx+8))
4494         {
4495             int active_offset = -1;
4496             if ((fwval(fw,idx+6) & 0x0000F000) == 0)
4497                 active_offset = fwval(fw,idx+6) & 0xFFF;
4498             else if ((fwval(fw,idx+7) & 0x0000F000) == 0)
4499                 active_offset = fwval(fw,idx+7) & 0xFFF;
4500             if (active_offset >= 0)
4501             {
4502                 uint32_t palette_control = LDR2val(fw,idx);
4503                 //print_stubs_min(fw,"palette_control",palette_control,idx2adr(fw,idx));
4504                 print_stubs_min(fw,"active_palette_buffer",palette_control+active_offset,idx2adr(fw,idx+1));
4505                 search_fw(fw, match_palette_data2, palette_data, palette_control, 1);
4506             }
4507         }
4508         return 1;
4509     }
4510 
4511     return 0;
4512 }
4513 
4514 int match_viewport_address3(firmware *fw, int k, uint32_t v1, __attribute__ ((unused))uint32_t v2)
4515 {
4516     if (isLDR_PC(fw,k) && (LDR2val(fw,k) == v1))
4517     {
4518         // Scan back to start of function
4519         int k1 = find_inst_rev(fw, isSTMFD_LR, k-1, 1000);
4520         if (k1 > 0)
4521         {
4522             // Check if function sig matches what we want
4523             if (isLDR_PC(fw,k1+1) && isLDR_PC(fw,k1+2) && isLDR(fw,k1+3) &&
4524                 (fwRd(fw,k1+1) == fwRn(fw,k1+3)))
4525             {
4526                 uint32_t a = LDR2val(fw,k1+1);
4527                 print_stubs_min(fw,"viewport_buffers",v1,idx2adr(fw,k));
4528                 print_stubs_min(fw,"active_viewport_buffer",a,idx2adr(fw,k1+1));
4529                 return 1;
4530             }
4531             else
4532             if (isLDR_PC(fw,k1+1) && isLDR_PC(fw,k1+3) && isLDR(fw,k1+4) &&
4533                 (fwRd(fw,k1+1) == fwRn(fw,k1+4)))
4534             {
4535                 uint32_t a = LDR2val(fw,k1+1);
4536                 print_stubs_min(fw,"viewport_buffers",v1,idx2adr(fw,k));
4537                 print_stubs_min(fw,"active_viewport_buffer",a,idx2adr(fw,k1+1));
4538                 return 1;
4539             }
4540             else
4541             if (isLDR_PC(fw,k1+1) && isLDR_PC(fw,k1+4) && isLDR(fw,k1+5) &&
4542                 (fwRd(fw,k1+1) == fwRn(fw,k1+5)))
4543             {
4544                 uint32_t a = LDR2val(fw,k1+1);
4545                 print_stubs_min(fw,"viewport_buffers",v1,idx2adr(fw,k));
4546                 print_stubs_min(fw,"active_viewport_buffer",a,idx2adr(fw,k1+1));
4547                 return 1;
4548             }
4549         }
4550     }
4551     return 0;
4552 }
4553 
4554 int match_viewport_address2(firmware *fw, int k, uint32_t v1, __attribute__ ((unused))uint32_t v2)
4555 {
4556     if (fw->buf[k] == v1)
4557     {
4558         if (search_fw(fw, match_viewport_address3, v1, 0, 1))
4559             return 1;
4560     }
4561     return 0;
4562 }
4563 
4564 int match_viewport_address(firmware *fw, int k, uint32_t v1, __attribute__ ((unused))uint32_t v2)
4565 {
4566     if (fw->buf[k] == v1)
4567     {
4568         // Find location in firmware that points to viewport address
4569         if (search_fw(fw, match_viewport_address2, idx2adr(fw,k), 0, 1))
4570             return 1;
4571     }
4572     return 0;
4573 }
4574 
4575 int match_physw_status(firmware *fw, int k, __attribute__ ((unused))int v)
4576 {
4577     if (isLDR_PC(fw,k))
4578     {
4579         print_stubs_min(fw,"physw_status",LDR2val(fw,k),idx2adr(fw,k));
4580     }
4581 
4582     return 0;
4583 }
4584 
4585 int match_physw_run(firmware *fw, int k, __attribute__ ((unused))int v)
4586 {
4587     if (isLDR_PC(fw,k))
4588     {
4589         uint32_t base = LDR2val(fw,k);
4590         uint32_t fadr = followBranch(fw, idx2adr(fw,k+1), 1);
4591         uint32_t ofst = fw->buf[adr2idx(fw,fadr)] & 0x00000FFF;
4592         print_stubs_min(fw,"physw_run",base+ofst,idx2adr(fw,k));
4593 
4594         ofst = fw->buf[k+2] & 0x00000FFF;
4595         print_stubs_min(fw,"physw_sleep_delay",base+ofst,idx2adr(fw,k));
4596     }
4597 
4598     return 0;
4599 }
4600 
4601 int match_canon_menu_active(firmware *fw, int k, __attribute__ ((unused))int v)
4602 {
4603     if (isLDR_PC(fw,k))
4604     {
4605         uint32_t base = LDR2val(fw,k);
4606         int k1;
4607         for (k1=k+1; k1<k+5; k1++)
4608         {
4609             if (isLDR(fw,k1))
4610             {
4611                 uint32_t ofst = fw->buf[k1] & 0x00000FFF;
4612                 print_stubs_min(fw,"canon_menu_active",base+ofst,idx2adr(fw,k));
4613             }
4614         }
4615     }
4616 
4617     return 0;
4618 }
4619 
4620 int match_zoom_busy(firmware *fw, int k, __attribute__ ((unused))int v)
4621 {
4622     if (isBL(fw,k))
4623     {
4624         int idx1 = idxFollowBranch(fw,k,0x01000001);
4625         int k1;
4626         for (k1=idx1; k1<idx1+50; k1++)
4627         {
4628             if ((fw->buf[k1] & 0xFFFF0000) == 0xE8BD0000)   // LDMFD
4629             {
4630                 uint32_t fadr = 0;
4631                 if (isADR_PC(fw,k1+1))
4632                 {
4633                     fadr = ADR2adr(fw,k1+1);
4634                 }
4635                 else if (isADR_PC(fw,k1+2))
4636                 {
4637                     fadr = ADR2adr(fw,k1+2);
4638                 }
4639                 else if (isADR_PC(fw,k1-3))
4640                 {
4641                     fadr = ADR2adr(fw,k1-3);
4642                 }
4643                 else if (isLDR_PC(fw,k1+1))
4644                 {
4645                     fadr = LDR2val(fw,k1+1);
4646                 }
4647                 else if (isLDR_PC(fw,k1+2))
4648                 {
4649                     fadr = LDR2val(fw,k1+2);
4650                 }
4651                 if (fadr != 0)
4652                 {
4653                     int idx2 = adr2idx(fw,fadr);
4654                     if (isLDR_PC(fw,idx2+1) && isLDR(fw,idx2+2))
4655                     {
4656                         int base = LDR2val(fw,idx2+1);
4657                         int ofst = fw->buf[idx2+2] & 0xFFF;
4658                            print_stubs_min(fw,"zoom_busy",base+ofst-4,fadr);
4659                         break;
4660                     }
4661                 }
4662             }
4663         }
4664     }
4665 
4666     return 0;
4667 }
4668 
4669 int match_focus_busy(firmware *fw, int k, __attribute__ ((unused))int v)
4670 {
4671     if ((fw->buf[k] & 0xFFFF0000) == 0xE8BD0000)   // LDMFD
4672     {
4673         int k1 = 0;
4674         if (isBL(fw,k-2))
4675         {
4676             k1 = idxFollowBranch(fw,k-2,0x01000001);
4677         }
4678         if (isBL(fw,k-1))
4679         {
4680             k1 = idxFollowBranch(fw,k-1,0x01000001);
4681         }
4682         if (k1 != 0)
4683         {
4684             if (isLDR_PC(fw,k1+1) && isLDR(fw,k1+3))
4685             {
4686                 int base = LDR2val(fw,k1+1);
4687                 int ofst = fw->buf[k1+3] & 0xFFF;
4688                    print_stubs_min(fw,"focus_busy",base+ofst-4,idx2adr(fw,k1));
4689                 return 1;
4690             }
4691         }
4692     }
4693 
4694     return 0;
4695 }
4696 
4697 int match_bitmap_buffer2(firmware *fw, int k, int v)
4698 {
4699     uint32_t screen_lock = idx2adr(fw,k);
4700     if (isBL(fw,v) && (followBranch(fw,idx2adr(fw,v),0x01000001) == screen_lock) && isBL(fw,v+2) && isBL(fw,v+3))
4701     {
4702         uint32_t fadr = followBranch2(fw,idx2adr(fw,v+3),0x01000001);
4703         int k1 = adr2idx(fw,fadr);
4704         if (isLDR_PC(fw,k1+1))
4705         {
4706             uint32_t reg = (fwval(fw,k1+1) & 0x0000F000) >> 12;
4707             uint32_t adr = LDR2val(fw,k1+1);
4708             int k2;
4709             for (k2=k1; k2<k1+32; k2++)
4710             {
4711                 if (isLDR_PC(fw,k2) && isLDR(fw,k2+1) && (((fwval(fw,k2+1) & 0x000F0000) >> 16) == reg))
4712                 {
4713                     uint32_t bitmap_buffer = LDR2val(fw,k2);
4714                     if (bitmap_buffer == (adr + 0x1C))
4715                     {
4716                         uint32_t active_bitmap_buffer = adr + (fwval(fw,k2+1) & 0xFFF);
4717                         print_stubs_min(fw,"bitmap_buffer",bitmap_buffer,idx2adr(fw,k2));
4718                         print_stubs_min(fw,"active_bitmap_buffer",active_bitmap_buffer,idx2adr(fw,k2+1));
4719                     }
4720                 }
4721             }
4722         }
4723     }
4724 
4725     return 0;
4726 }
4727 
4728 int match_bitmap_buffer(firmware *fw, int k, __attribute__ ((unused))int v)
4729 {
4730     search_saved_sig(fw, "ScreenLock", match_bitmap_buffer2, k, 0, 1);
4731     return 0;
4732 }
4733 
4734 int match_raw_buffer(firmware *fw, int k, uint32_t rb1, __attribute__ ((unused))uint32_t v2)
4735 {
4736     if (((fwval(fw,k) == rb1) && (fwval(fw,k+4) == rb1) && (fwval(fw,k-2) != 1)) ||
4737         ((fwval(fw,k) == rb1) && (fwval(fw,k+4) == rb1) && (fwval(fw,k+20) == rb1)))
4738     {
4739         uint32_t rb2 = fwval(fw,k+1);
4740         if ((rb1 != rb2) && (rb2 > 0))
4741         {
4742             bprintf("// Camera has 2 RAW buffers @ 0x%08x & 0x%08x\n", rb1, rb2, idx2adr(fw,k));
4743             bprintf("//  Note: active buffer --> raw_buffers[active_raw_buffer]\n");
4744             bprintf("//        other buffer  --> raw_buffers[active_raw_buffer^1]\n");
4745             print_stubs_min(fw,"raw_buffers",idx2adr(fw,k),idx2adr(fw,k));
4746         }
4747         return rb2;
4748     }
4749     else if ((fwval(fw,k) == rb1) && (fwval(fw,k-2) == 2) && (fwval(fw,k-7) == rb1))
4750     {
4751         uint32_t rb2 = fwval(fw,k+3);
4752         if ((rb1 != rb2) && (rb2 > 0))
4753         {
4754             bprintf("// Camera has 2 RAW buffers @ 0x%08x & 0x%08x\n", rb1, rb2, idx2adr(fw,k));
4755             bprintf("//  Note: active buffer --> raw_buffers[ active_raw_buffer   *3]\n");
4756             bprintf("//        other buffer  --> raw_buffers[(active_raw_buffer^1)*3]\n");
4757             print_stubs_min(fw,"raw_buffers",idx2adr(fw,k),idx2adr(fw,k));
4758         }
4759         return rb2;
4760     }
4761     return 0;
4762 }
4763 
4764 int match_cameracon_state(firmware *fw, int k, __attribute__ ((unused))int v)
4765 {
4766     /*
4767      * expect
4768      * ldr     r3, =const
4769      * mov     r5, r0
4770      * cmp     ip, #0xa
4771      * mov     r2, #0
4772      * ldr     r0, ="CameraConState.c"
4773      * mov     r1, #const
4774      * str     r5, [r3]
4775      *
4776      * regs seem to be the same on all cams with this code
4777      */
4778     if (isLDR_PC(fw,k))
4779     {
4780         int rd = fwRd(fw,k);
4781         if(rd != 3) {
4782             return 0;
4783         }
4784         uint32_t base = LDR2val(fw,k);
4785         k += 6;
4786         uint32_t ofst = fw->buf[k] & 0x00000FFF;
4787         if (isSTR(fw,k) && fwRd(fw,k) == 5 && fwRn(fw,k) == rd && ofst == 0)
4788         {
4789             print_stubs_min(fw,"cameracon_state",base,idx2adr(fw,k));
4790         }
4791     }
4792 
4793     return 0;
4794 }
4795 
4796 
4797 uint32_t frsp_buf = 0;
4798 uint32_t frsp_buf_at = 0;
4799 int find_DoMovieFrameCapture_buf(firmware *fw)
4800 {
4801     uint32_t uncached_adr = 0x10000000; // true for all vx cams
4802     int k = get_saved_sig(fw,"DoMovieFrameCapture");
4803     int ka = get_saved_sig(fw,"ClearEventFlag");
4804     if (k < 0 || ka < 0)
4805         return 0;
4806     k = adr2idx(fw, func_names[k].val);
4807     ka = adr2idx(fw, func_names[ka].val);
4808     if (k && ka)
4809     {
4810         int k2 = find_inst(fw,isBL,k,14);
4811         if (k2 == -1 || idxFollowBranch(fw,k2,0x01000001) != ka)
4812             return 0;
4813         int k1 = k;
4814         int reg = -1;
4815         while (k1<k2)
4816         {
4817             k1++;
4818             if (reg < 0 && isLDR_PC(fw,k1))
4819             {
4820                 uint32_t v = LDR2val(fw,k1);
4821                 if (v>uncached_adr && v<uncached_adr+fw->maxram && (v&3)==0)
4822                 {
4823                     frsp_buf = v;
4824                     frsp_buf_at = idx2adr(fw,k1);
4825                     break;
4826                 }
4827             }
4828             if (isMOV_immed(fw,k1) && ALUop2a(fw,k1)>uncached_adr)
4829             {
4830                 reg = fwRd(fw,k1);
4831                 frsp_buf = ALUop2a(fw,k1);
4832                 frsp_buf_at = idx2adr(fw, k1);
4833             }
4834             if (reg<0)
4835                 continue;
4836             if ((fwval(fw,k1)&0xfffff000) == (0xe2800000+(reg<<12)+(reg<<16))) // ADD Rx, Rx, #imm
4837             {
4838                 frsp_buf += ALUop2a(fw,k1);
4839                 frsp_buf_at = idx2adr(fw, k1);
4840             }
4841         }
4842     }
4843     if (!frsp_buf) // ixus30/40
4844     {
4845         k = get_saved_sig(fw,"WBInteg.DoCaptMovieFrame_FW");
4846         if (k < 0)
4847             return 0;
4848         k = adr2idx(fw, func_names[k].val);
4849         ka = find_inst(fw,isLDR_PC,k,6);
4850         if (ka < 0)
4851             return 0;
4852         uint32_t v = LDR2val(fw,ka);
4853         if (v>uncached_adr && v<uncached_adr+fw->maxram && (v&3)==0)
4854         {
4855             frsp_buf = v;
4856             frsp_buf_at = idx2adr(fw,ka);
4857         }
4858     }
4859     return 0;
4860 }
4861 
4862 // Search for things that go in 'stubs_min.S'
4863 void find_stubs_min(firmware *fw)
4864 {
4865     //int k,k1;
4866 
4867     out_hdr = 1;
4868     add_blankline();
4869 
4870     bprintf("// Values below can be overridden in 'stubs_min.S':\n");
4871 
4872     // Find 'levent_table'
4873     search_fw(fw, match_levent_table, 0, 0, 1);
4874 
4875     // Find 'FlashParamsTable'
4876     if (FlashParamsTable_address != 0)
4877         print_stubs_min(fw,"FlashParamsTable",FlashParamsTable_address,FlashParamsTable_address);
4878 
4879     find_FileAccessSem(fw);
4880 /*
4881     // Find 'physw_status'
4882     search_saved_sig(fw, "kbd_read_keys", match_physw_status, 0, 0, 5);
4883 
4884     // Find 'physw_run' & 'physw_sleep_delay'
4885     search_saved_sig(fw, "task_PhySw", match_physw_run, 0, 0, 5);
4886 
4887     // Find 'movie_status'
4888     search_fw(fw, match_movie_status, 0, 0, 1);
4889 
4890     // Find 'video_compression_rate'
4891     uint32_t sadr = find_str(fw, "CompressionRateAdjuster.c");
4892     k = find_nxt_str_ref(fw, sadr, -1);
4893     int found = 0;
4894     while ((k >= 0) && !found)
4895     {
4896         int f = find_inst_rev(fw, isSTMFD_LR, k-1, 100);
4897         if (f != -1)
4898         {
4899             f = search_fw(fw, find_BL, f, 0, 1);
4900             if (f > 0)
4901             {
4902                 f--;
4903                 if ((fwval(fw,f) & 0xFFF00000) == 0xE2400000)     // SUB
4904                 {
4905                     int src = fwRn(fw,f);
4906                     for (k1 = f-1; (k1 > f-10) && !found; k1--)
4907                     {
4908                         if (isLDR_PC(fw,k1) && (fwRd(fw,k1) == src))
4909                         {
4910                             uint32_t v = LDR2val(fw,k1) - ALUop2(fw,f);
4911                             print_stubs_min(fw,"video_compression_rate",v,idx2adr(fw,k1));
4912                             found = 1;
4913                         }
4914                     }
4915                 }
4916             }
4917         }
4918         k = find_nxt_str_ref(fw, sadr, k);
4919     }
4920 
4921     // Find 'full_screen_refresh'
4922     search_fw(fw, match_full_screen_refresh, 0, 0, 1);
4923 
4924     // Find 'canon_menu_active'
4925     search_saved_sig(fw, "StartRecModeMenu", match_canon_menu_active, 0, 0, 5);
4926 
4927     // Find 'canon_shoot_menu_active'
4928     search_fw(fw, match_canon_shoot_menu_active, 0, 0, 1);
4929 
4930     // Find 'playrec_mode'
4931     int found_playrec_mode = 0;
4932     k = find_str_ref(fw, "AFFChg");
4933     if ((k >= 0) && isBL(fw,k+6))
4934     {
4935         k = idxFollowBranch(fw, k+6, 0x01000001);
4936         if (isLDR_PC(fw,k) && isLDR(fw,k+1))
4937         {
4938             uint32_t base = LDR2val(fw,k);
4939             uint32_t ofst = fw->buf[k+1] & 0x00000FFF;
4940             print_stubs_min(fw,"playrec_mode",base+ofst,idx2adr(fw,k));
4941             found_playrec_mode = 1;
4942         }
4943     }
4944     if (!found_playrec_mode)
4945     {
4946         search_fw(fw, match_playrec_mode, 0, 0, 1);
4947     }
4948 
4949     // Find 'zoom_status'
4950     int found_zoom_status = 0;
4951 
4952     k = find_str_ref(fw, "m_ZoomState            :%d\n");
4953     if (k >= 0)
4954     {
4955         if (isLDR(fw,k-1))
4956         {
4957             uint32_t ofst = fw->buf[k-1] & 0x00000FFF;
4958             uint32_t reg = (fw->buf[k-1] & 0x000F0000) >> 16;
4959             uint32_t ldr_inst = 0xE51F0000 | (reg << 12);
4960             for (k1=k-2; k1>k-20; k1--)
4961             {
4962                 if ((fw->buf[k1] & 0xFF1FF000) == ldr_inst)
4963                 {
4964                     uint32_t base = LDR2val(fw,k1);
4965                     print_stubs_min(fw,"zoom_status",base+ofst,idx2adr(fw,k));
4966                     found_zoom_status = 1;
4967                     break;
4968                 }
4969             }
4970         }
4971     }
4972 
4973     if (!found_zoom_status)
4974     {
4975         for (k=0; k<fw->size; k++)
4976         {
4977             if (((fw->buf[k] & 0xFF1FF000) == 0xE51F0000) &&    // LDR R0, =base
4978                 (fw->buf[k+1] == 0xE5D00000) &&                 // LDRB R0, [R0]
4979                 (fw->buf[k+2] == 0xE1B00000) &&                 // MOVS R0, R0
4980                 (fw->buf[k+3] == 0x13A00001) &&                 // MOVNE R0, #1
4981                 isBX_LR(fw,k+4))                                // BX LR
4982             {
4983                 uint32_t base = LDR2val(fw,k);
4984                 print_stubs_min(fw,"zoom_status",base,idx2adr(fw,k));
4985                 found_zoom_status = 1;
4986                 //break;
4987             }
4988         }
4989     }
4990 
4991     if (!found_zoom_status)
4992     {
4993         k = find_str_ref(fw, "TerminateDeliverToZoomController");
4994         if (k >= 0)
4995         {
4996             for (k1=0; k1<5; k1++)
4997             {
4998                 if (isLDR_PC(fw,k+k1))
4999                 {
5000                     uint32_t base = LDR2val(fw,k+k1);
5001                     print_stubs_min(fw,"zoom_status",base+0x20,idx2adr(fw,k+k1));
5002                     found_zoom_status = 1;
5003                     break;
5004                 }
5005             }
5006         }
5007     }
5008 
5009     // Find 'some_flag_for_af_scan'
5010     search_fw(fw, match_some_flag_for_af_scan, 0, 0, 1);
5011 
5012     // focus_len_table
5013     if (fw->sv->min_focus_len != 0)
5014     {
5015         int found = 0, pos = 0, len = 0, size = 0;
5016         for (k=0; k<fw->size; k++)
5017         {
5018             if (fw->buf[k] == fw->sv->min_focus_len)
5019             {
5020                 int mul = 1;
5021                 if ((fw->buf[k+1] == 100) && (fw->buf[k+2] == 0)) mul = 3;
5022                 if ((fw->buf[k+1] == 100) && (fw->buf[k+2] != 0)) mul = 2;
5023                 if ((fw->buf[k+1] ==   0) && (fw->buf[k+2] != 0)) mul = 2;
5024                 for (k1 = k + mul; (k1 < fw->size) && (fw->buf[k1] > fw->buf[k1-mul]) && (fw->buf[k1] > fw->sv->min_focus_len) && (fw->buf[k1] < fw->sv->max_focus_len); k1 += mul) ;
5025                 if (fw->buf[k1] == fw->sv->max_focus_len)
5026                 {
5027                     if ((found == 0) || ((size < mul) && (len < ((k1 - k) / mul) + 1)))
5028                     {
5029                         found = 1;
5030                         pos = k;
5031                         len = ((k1 - k) / mul) + 1;
5032                         size = mul;
5033                     }
5034                 }
5035             }
5036         }
5037         if (found == 1)
5038         {
5039             bprintf("// focus_len_table contains zoom focus lengths for use in 'get_focal_length' (main.c).\n");
5040             if (size == 1)
5041                 bprintf("// each entry contains 1 int value, which is the the zoom focus length.\n",size);
5042             else
5043                 bprintf("// each entry contains %d int value(s), the first is the zoom focus length.\n",size);
5044             bprintf("// there are %d entries in the table - set NUM_FL to %d\n",len,len);
5045             print_stubs_min(fw,"focus_len_table",idx2adr(fw,pos),idx2adr(fw,pos));
5046         }
5047     }
5048 
5049     // Find 'zoom_busy'
5050     search_saved_sig(fw, "ResetZoomLens", match_zoom_busy, 0, 0, 5);
5051 
5052     // Find 'focus_busy'
5053     search_saved_sig(fw, "ResetFocusLens", match_focus_busy, 0, 0, 25);
5054 
5055     // Find 'recreview_hold'
5056     k = find_str_ref(fw, "ShootCon_NotifyStartReviewHold");
5057     if (k >= 0)
5058     {
5059         for (k1=k; k1<k+20; k1++)
5060         {
5061             if (isLDR_PC(fw,k1) && ((fw->buf[k1+1] & 0xFFFF0FFF) == 0xE3A00001) && isSTR(fw,k1+2) &&
5062                 ((fw->buf[k1+1] & 0x0000F000) == (fw->buf[k1+2] & 0x0000F000)) &&
5063                 ((fw->buf[k1] & 0x0000F000) == ((fw->buf[k1+2] & 0x000F0000) >> 4)))
5064             {
5065                 uint32_t base = LDR2val(fw,k1);
5066                 int ofst = fw->buf[k1+2] & 0x00000FFF;
5067                 print_stubs_min(fw,"recreview_hold",base+ofst,idx2adr(fw,k1));
5068                 break;
5069             }
5070         }
5071     }
5072 
5073     // Find palette colour data
5074     uint32_t palette_data = search_fw(fw, match_palette_data, 0, 0, 1);
5075 
5076     // Find 'palette buffer' info
5077     if (palette_data)
5078     {
5079         bprintf("// Palette colour tables  found @ 0x%08x\n", palette_data);
5080         if (search_saved_sig(fw, "SavePaletteData", match_SavePaletteData, palette_data, 0, 1) == 0)
5081         {
5082             search_fw(fw, match_palette_data3, palette_data, 0, 1);
5083         }
5084     }
5085 
5086     // Find 'bitmap buffer' info
5087     search_saved_sig(fw, "GUISrv_StartGUISystem", match_bitmap_buffer, 0, 0, 50);
5088 
5089     // Get viewport address
5090     uint32_t v = find_viewport_address(fw,&k);
5091     if (k >= 0)
5092     {
5093         search_fw(fw, match_viewport_address, v, 0, 1);
5094     }
5095 
5096     // find 1st RAW buffer address
5097     k = find_str_ref(fw, "CRAW BUFF       %p");
5098     if (k >= 0)
5099     {
5100         int rb1_idx;
5101         uint32_t rb1 =0, rb2 = 0;
5102         if (isLDR(fw,k-1))
5103         {
5104             rb1 = LDR2val(fw,k-1);
5105             rb1_idx = k - 1;
5106         }
5107         else if (isMOV_immed(fw,k-1))
5108         {
5109             rb1 = ALUop2(fw,k-1);
5110             rb1_idx = k - 1;
5111         }
5112         else if (isMOV(fw,k-1) && (fwRd(fw,k-1) == 1))
5113         {
5114             int reg = fwval(fw,k-1) & 0xF;
5115             for (k1=k-2; k1>k-50; k1--)
5116             {
5117                 if (isLDR(fw,k1) && (fwRd(fw,k1) == reg))
5118                 {
5119                     rb1 = LDR2val(fw,k1);
5120                     rb1_idx = k1;
5121                     break;
5122                 }
5123             }
5124         }
5125         if (rb1 > 0)
5126         {
5127             found = 0;
5128             rb2 = search_fw(fw, match_raw_buffer, rb1, 0, 5);
5129             if ((rb2 > 0) && (rb1 != rb2))
5130             {
5131                 // Find 'active_raw_buffer'
5132                 sadr = find_str(fw, "SsImgProcBuf.c");
5133                 k = find_nxt_str_ref(fw, sadr, -1);
5134                 while ((k >= 0) && !found)
5135                 {
5136                     int f = find_inst_rev(fw, isSTMFD_LR, k-1, 100);
5137                     if (f != -1)
5138                     {
5139                         int e = find_inst(fw, isLDMFD_PC, f+1, 200);
5140                         for (k1 = f+1; k1 < e; k1++)
5141                         {
5142                             if (
5143                                 (
5144                                     ((fwval(fw,k1)   & 0xFFF00FFF) == 0xE2400001) &&    // SUB Rx, Rn, #1
5145                                     isLDR(fw,k1+1) &&                                   // LDR Ry, [Rz,
5146                                     ((fwval(fw,k1+2) & 0xFFF00000) == 0xE1500000) &&    // CMP Rx, Ry
5147                                     (((fwRd(fw,k1) == fwRd(fw,k1+2)) && (fwRd(fw,k1+1) == fwRn(fw,k1+2))) ||
5148                                      ((fwRd(fw,k1) == fwRn(fw,k1+2)) && (fwRd(fw,k1+1) == fwRd(fw,k1+2)))) &&
5149                                     ((fwval(fw,k1+3) & 0xFFF00FFF) == 0x12800001) &&    // ADDNE Ry, Ry, #1
5150                                     ((fwRd(fw,k1+3) == fwRn(fw,k1+3)) && (fwRd(fw,k1+3) == fwRd(fw,k1+1))) &&
5151                                     ((fwval(fw,k1+4) & 0xFFF00FFF) == 0x03A00000) &&    // MOVEQ Ry, #0
5152                                     (fwRd(fw,k1+4) == fwRd(fw,k1+1)) &&
5153                                     isSTR(fw,k1+5) &&                                   // STR Ry, [Rz,
5154                                     ((fwRd(fw,k1+5) == fwRd(fw,k1+1)) && (fwRn(fw,k1+5) == fwRn(fw,k1+1)) && (fwOp2(fw,k1+5) == fwOp2(fw,k1+1)))
5155                                 ) ||
5156                                 (
5157                                     ((fwval(fw,k1)   & 0xFFF00FFF) == 0xE2400001) &&    // SUB Rx, Rn, #1
5158                                     isLDR(fw,k1+1) &&                                   // LDR Ry, [Rz,
5159                                     ((fwval(fw,k1+3) & 0xFFF00000) == 0xE1500000) &&    // CMP Rx, Ry
5160                                     (((fwRd(fw,k1) == fwRd(fw,k1+3)) && (fwRd(fw,k1+1) == fwRn(fw,k1+3))) ||
5161                                      ((fwRd(fw,k1) == fwRn(fw,k1+3)) && (fwRd(fw,k1+1) == fwRd(fw,k1+3)))) &&
5162                                     ((fwval(fw,k1+4) & 0xFFF00FFF) == 0x12800001) &&    // ADDNE Ry, Ry, #1
5163                                     ((fwRd(fw,k1+4) == fwRn(fw,k1+4)) && (fwRd(fw,k1+4) == fwRd(fw,k1+1))) &&
5164                                     ((fwval(fw,k1+5) & 0xFFF00FFF) == 0x03A00000) &&    // MOVEQ Ry, #0
5165                                     (fwRd(fw,k1+5) == fwRd(fw,k1+1)) &&
5166                                     isSTR(fw,k1+7) &&                                   // STR Ry, [Rz,
5167                                     ((fwRd(fw,k1+7) == fwRd(fw,k1+1)) && (fwRn(fw,k1+7) == fwRn(fw,k1+1)) && (fwOp2(fw,k1+7) == fwOp2(fw,k1+1)))
5168                                 )
5169                                )
5170                             {
5171                                 int ofst = fwOp2(fw,k1+1);
5172                                 int reg = fwRn(fw,k1+1);
5173                                 int k2;
5174                                 for (k2 = f+1; (k2 < e) && !found; k2++)
5175                                 {
5176                                     if (isLDR_PC(fw,k2) && (fwRd(fw,k2) == reg))
5177                                     {
5178                                         uint32_t base = LDR2val(fw,k2);
5179                                         print_stubs_min(fw,"active_raw_buffer",base+ofst,idx2adr(fw,k1));
5180                                         found = 1;
5181                                         break;
5182                                     }
5183                                 }
5184                             }
5185                         }
5186                     }
5187                     k = find_nxt_str_ref(fw, sadr, k);
5188                 }
5189             }
5190             if (!found)
5191             {
5192                 bprintf("// Camera appears to have only 1 RAW buffer @ 0x%08x (Found @0x%08x)\n", rb1, idx2adr(fw,rb1_idx));
5193             }
5194         }
5195     }
5196 */
5197 
5198     // Find exmem allocation table
5199     find_exmem_alloc_table(fw);
5200 
5201     // Find imager_active
5202     search_saved_sig(fw, "ImagerActivate", match_imager_active, 0/*v*/, 0, 30);
5203 
5204 
5205 //    find_DoMovieFrameCapture_buf(fw);
5206 //    if (frsp_buf)
5207 //    {
5208 //        print_stubs_min(fw,"frsp_buf",frsp_buf,frsp_buf_at);
5209 //    }
5210 
5211     // Find UI property count
5212     search_saved_sig(fw, "PTM_SetCurrentItem", match_uiprop_count, 0, 0, 30);
5213 
5214     search_saved_sig(fw, "cameracon_set_state", match_cameracon_state, 0, 3, 1);
5215 }
5216 
5217 //------------------------------------------------------------------------------------------------------------
5218 
5219 int find_ctypes(firmware *fw, int k)
5220 {
5221     static unsigned char ctypes[] =
5222     {
5223         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x60, 0x60, 0x60, 0x60, 0x60, 0x20, 0x20,
5224         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
5225         0x48, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
5226         0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
5227         0x10, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5228         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x10, 0x10, 0x10, 0x10, 0x10,
5229         0x10, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 2, 2, 2, 2, 2, 2, 2, 2, 2,
5230         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0x10, 0x10, 0x10, 0x10, 0x20
5231     };
5232 
5233     if ((uint32_t)k < (fw->size*4 - sizeof(ctypes)))
5234     {
5235         if (memcmp(((char*)fw->buf)+k,ctypes,sizeof(ctypes)) == 0)
5236         {
5237             bprintf("DEF(ctypes, 0x%08x)\n", fw->base + k);
5238             return 1;
5239         }
5240     }
5241     return 0;
5242 }
5243 
5244 int match_nrflag3(firmware *fw, int k, uint32_t v1, __attribute__ ((unused))uint32_t v2)
5245 {
5246     if (isBL(fw,k) && (idxFollowBranch(fw,k,0x01000001) == (int)v1))
5247     {
5248         // Found call to function, work out R3 value passed in
5249         int ofst1 = 0;
5250         int k3, k4 = 0;
5251         for (k3=k; k3>k-30; k3--)
5252         {
5253             if ((fwval(fw,k3) & 0x0F0FF000) == 0x020D3000)       // Dest = R3, Src = SP = skip
5254                 break;
5255             if ((fwval(fw,k3) & 0xFF0FF000) == 0xE2033000)       // ADD/SUB R3,R3,x
5256             {
5257                 k4 = k3;
5258                 if ((fwval(fw,k3) & 0x00F00000) == 0x00400000)   // SUB
5259                     ofst1 -= (fwval(fw,k3) & 0x00000FFF);
5260                 else
5261                     ofst1 += (fwval(fw,k3) & 0x00000FFF);
5262             }
5263             if (isLDR_PC(fw,k3) && (fwRd(fw,k3) == 3))
5264             {
5265                 uint32_t ofst2 = LDR2val(fw,k3);
5266                 if (ofst2 > (fw->data_len*4 + fw->data_start)) // has to be in the preinited data section
5267                     return 0;
5268                 bprintf("\n// For capt_seq.c\n");
5269                 if (ofst1 == 0)
5270                 {
5271                     bprintf("DEF(_nrflag,0x%04x) // Found @ %08x (0x%04x)\n",ofst2,idx2adr(fw,k3),ofst2);
5272                     bprintf("//static long *nrflag = (long*)(0x%04x);       // Found @ %08x\n",ofst2,idx2adr(fw,k3));
5273                 }
5274                 else if (ofst1 < 0)
5275                 {
5276                     bprintf("DEF(_nrflag,0x%04x) // Found @ %08x (0x%04x) & %08x (-0x%02x)\n",ofst2+ofst1,idx2adr(fw,k3),ofst2,idx2adr(fw,k),-ofst1);
5277                     bprintf("//static long *nrflag = (long*)(0x%04x-0x%02x);  // Found @ %08x & %08x\n",ofst2,-ofst1,idx2adr(fw,k3),idx2adr(fw,k4));
5278                 }
5279                 else
5280                 {
5281                     bprintf("DEF(_nrflag,0x%04x) // Found @ %08x (0x%04x) & %08x (+0x%02x)\n",ofst2+ofst1,idx2adr(fw,k3),ofst2,idx2adr(fw,k),ofst1);
5282                     bprintf("//static long *nrflag = (long*)(0x%04x+0x%02x);  // Found @ %08x & %08x\n",ofst2,ofst1,idx2adr(fw,k3),idx2adr(fw,k4));
5283                 }
5284                 return 1;
5285             }
5286         }
5287     }
5288     return 0;
5289 }
5290 
5291 int match_nrflag(firmware *fw, int idx, __attribute__ ((unused))int v)
5292 {
5293     int k1, k2, k3;
5294     int found = 0;
5295 
5296     if (isLDR(fw, idx+1) && isLDR(fw, idx+2))
5297     {
5298         k3 = idx+2;
5299         int ofst2 = LDR2val(fw, k3);
5300 
5301         for (k1=k3+1; k1<k3+8; k1++)
5302         {
5303             if (isB(fw, k1))
5304             {
5305                 k2 = idxFollowBranch(fw,k1,0x01000001);
5306                 if (isSTR(fw, k2))
5307                 {
5308                     found = 1;
5309                     break;
5310                 }
5311                 k2++;
5312                 if (isSTR(fw, k2))
5313                 {
5314                     found = 1;
5315                     break;
5316                 }
5317             }
5318         }
5319 
5320         if (found)
5321         {
5322             int ofst1 = fw->buf[k2] & 0x00000FFF;
5323             bprintf("\n// For capt_seq.c\n");
5324             bprintf("DEF(_nrflag,0x%04x) // Found @ %08x (0x%04x) & %08x (+0x%02x)\n",ofst2+ofst1,idx2adr(fw,k3),ofst2,idx2adr(fw,k2),ofst1);
5325             bprintf("//static long *nrflag = (long*)(0x%04x+0x%02x);  // Found @ %08x & %08x\n",ofst2,ofst1,idx2adr(fw,k3),idx2adr(fw,k2));
5326             bprintf("//#define NR_AUTO (0)                          // have to explictly reset value back to 0 to enable auto\n");
5327         }
5328     }
5329 
5330     return found;
5331 }
5332 
5333 int match_nrflag2(firmware *fw, int k, __attribute__ ((unused))int v)
5334 {
5335     // Found NR_GetDarkSubType function, now follow first BL call.
5336     if (isBL(fw,k))
5337     {
5338         k = idxFollowBranch(fw,k,0x01000001);
5339         return search_fw(fw, match_nrflag3, k, 0, 1);
5340     }
5341 
5342     return 0;
5343 }
5344 
5345 // find LEDs, Vx specific
5346 
5347 // ADD Rx, Rx, #0x220000
5348 int isADD_0x220000(firmware *fw, int offset)
5349 {
5350     return ((fwval(fw,offset) & 0xfff00fff) == (0xe2800822));
5351 }
5352 
5353 typedef struct {
5354     uint32_t addr;  // LED GPIO address
5355     int reg;        // register used to assemble the address
5356     int offs;       // offset in the LED table
5357 } LED_s;
5358 
5359 int find_leds(firmware *fw)
5360 {
5361     int j1, j2, m, n;
5362     LED_s led;
5363     int k1 = find_str_ref(fw,"LEDCon");
5364     if (k1<0)
5365         return 0;
5366     k1 = find_inst_rev(fw,isSTMFD_LR,k1,96);
5367     if (k1<0)
5368         return 0;
5369     j1 = find_inst(fw,isBL,k1,80);
5370     j2 = find_Nth_inst(fw,isBL,k1,80,3);
5371     if ((j1<0) || (j2<0))
5372         return 0;
5373     // 1st and 3rd BL is memory allocation
5374     if (followBranch(fw,idx2adr(fw,j1),0x01000001) != followBranch(fw,idx2adr(fw,j2),0x01000001))
5375         return 0;
5376     k1 = find_Nth_inst(fw,isBL,k1,80,2);
5377     // LED table initializer func
5378     k1 = idxFollowBranch(fw,k1,0x01000001);
5379     if (k1<0)
5380         return 0;
5381     bprintf("// LED table init @ 0x%x\n",idx2adr(fw,k1));
5382     j2 = 1;
5383     while (1)
5384     {
5385         j1 = find_Nth_inst(fw,isADD_0x220000,k1,40,j2);
5386         if (j1>0)
5387         {
5388             led.reg = fwRd(fw,j1);
5389             led.addr = 0x220000;
5390             led.offs = 0;
5391             n = j1-1;
5392             while (!isSTMFD_LR(fw,n))
5393             {
5394                 if ((fwval(fw,n)&0xfffff000) == (0xe2800000+(led.reg<<12)+(led.reg<<16))) // ADD Rx, Rx, #0xc00000yz
5395                 {
5396                     if ( ALUop2a(fw,n) >= 0xc0000000 )
5397                     {
5398                         led.addr += ALUop2a(fw,n);
5399                     }
5400                 }
5401                 else if ((fwval(fw,n)&0xfffff000) == (0xe3a00000+(led.reg<<12))) // MOV Rx, #imm
5402                 {
5403                     led.addr += ALUop2a(fw,n);
5404                     m = n+1;
5405                     while (!isLDMFD_PC(fw,m))
5406                     {
5407                         if ((fwval(fw,m)&0xfff0f000) == (0xe5800000+(led.reg<<12))) // STR Rx, [Ry, imm]
5408                         {
5409                             led.offs = fwval(fw,m) & 0xfff;
5410                             break;
5411                         }
5412                         m++;
5413                     }
5414                     if (led.offs != 0)
5415                         break;
5416                 }
5417                 n--;
5418             }
5419             // output data if valid
5420             if (led.offs != 0)
5421             {
5422                 bprintf("// LED #%i: 0x%08x, offset 0x%x\n",j2, led.addr, led.offs);
5423             }
5424             j2++;
5425         }
5426         else
5427         {
5428             break;
5429         }
5430     }
5431     bprintf("\n");
5432     return 0;
5433 }
5434 
5435 // Search for things
5436 void find_other_vals(firmware *fw)
5437 {
5438     out_hdr = 1;
5439     add_blankline();
5440 
5441     bprintf("// Misc stuff\n");
5442     add_blankline();
5443     print_exmem_types(fw);
5444     find_leds(fw);
5445 
5446     // Look for nrflag (for capt_seq.c)
5447     search_saved_sig(fw, "NR_GetDarkSubType", match_nrflag2, 0, 0, 20);
5448 }
5449 
5450 //------------------------------------------------------------------------------------------------------------
5451 
5452 void print_kval(firmware *fw, uint32_t tadr, int tsiz, int tlen, uint32_t ev, const char *name, char *sfx)
5453 {
5454     int tidx = adr2idx(fw,tadr);
5455     int k, kval = 0;
5456     for (k=0; k<tlen; k+=tsiz)
5457     {
5458         if (fw->buf[tidx+k+1] == ev)
5459         {
5460             kval = fw->buf[tidx+k];
5461             tadr = idx2adr(fw,tidx+k);
5462             break;
5463         }
5464     }
5465     if (kval > 0)
5466     {
5467         char fn[100],