Canon Basic/Scripts/Loader
Talk0
538pages on
this wiki
this wiki
< Canon Basic
Canon basic binary loader
This script loads and boots the specified ARM binary. The binary should be unencoded, and loadable at 0x1900
Tested on a540 (vxworks) and D10 (dryos)
Free memory must be > the size of the binary. This may be a problem on some cameras, especially if CHDK is already running and there are images on the camera.
original discussion thread with background information http://chdk.setepontos.com/index.php?topic=5648.0
' bootbin is the image to load. It must be an unencoded arm binary DIM bootbin = "A/MAIN.BIN" DIM lcdmsg=0 DIM msgstr=0 PRIVATE SUB RegisterProcs() ' Newest cams (Dryos rel 43 and later) only have System.Create() ' on older dryos cams SystemEventInit is an alias for System.Create() ' ExecuteEventProcedure does is not registered by default on vx, ' but calling an unregistered is not fatal if System.Create() = -1 then SystemEventInit() end if if ExecuteEventProcedure("UI_RegistDebugEventProc") = -1 then ExecuteEventProcedure("UI.CreatePublic") end if ExecuteEventProcedure("DispDev_EnableEventProc") END SUB PRIVATE SUB InitMsg() lcdmsg = ExecuteEventProcedure("LCDMsg_Create") ' not default black if lcdmsg >= 0 then LCDMsg_ChangeColor(lcdmsg,2) LCDMsg_SetStr(lcdmsg,"started") end if msgstr = AllocateMemory(80) ' truncate log msgfile = Fopen_Fut("A/CBLOADER.LOG","w") if msgfile <> 0 then Fclose_Fut(msgfile) end if END SUB PRIVATE SUB PutMsg(msg) if lcdmsg >= 0 then LCDMsg_SetStr(lcdmsg,msg) end if msgfile = Fopen_Fut("A/CBLOADER.LOG","a") if msgfile <> 0 then Fwrite_Fut(msg,strlen(msg),1,msgfile) Fwrite_Fut("\n",1,1,msgfile) Fclose_Fut(msgfile) end if END SUB ' put some ARM code in a buffer ' this should be in uncacheable memory, but function is not available on older cams ' in practice, loading the main image should ensure all this is flushed out ' pad binary to > 4k or so if needed ' can't use strings with \xHH because older cams don't support ' parameters: ' R0 source address ' R1 size ' never returns, saves nothing on the stack PRIVATE SUB MakeLoader() buf = AllocateMemory(76) p = buf *p = 0xee113f10 ' MRC p15, 0, R3, c1, c0, 0 p = p + 4 *p = 0xe3c33a01 ' BIC R3, R3, #0x1000 // icache bit p = p + 4 *p = 0xe3c33004 ' BIC R3, R3, #0x4 // dcache bit p = p + 4 *p = 0xee013f10 ' MCR p15, 0, R3, c1, c0, 0 p = p + 4 *p = 0xe3a03000 ' MOV R3, #0 p = p + 4 *p = 0xee073f9a ' MCR p15, 0, R3,c7,c10, 4 // drain write buffer p = p + 4 *p = 0xee073f15 ' MCR p15, 0, R3,c7,c5 // flush icache p = p + 4 *p = 0xee073f16 ' MCR p15, 0, R3,c7,c6 // flush dcache p = p + 4 *p = 0xe10f4000 ' MRS R4, CPSR p = p + 4 *p = 0xe3844080 ' ORR R4, R4, #0x80 p = p + 4 *p = 0xe12ff004 ' MSR CPSR_cxsf, R4 // disable IRQs p = p + 4 *p = 0xee195f11 ' MRC p15, 0, R5, c9, c1, 0 // read data TCM config p = p + 4 *p = 0xe1a05625 ' MOV R5, R5, LSR#12 // clear the lower 12 bits p = p + 4 *p = 0xe7935605 ' LDR R5, [R3, R5, LSL#12] // R3 is still 0 p = p + 4 *p = 0xe1a02001 ' MOV R2, R1 p = p + 4 *p = 0xe1a01000 ' MOV R1, R0 p = p + 4 *p = 0xe3a00c19 ' MOV R0, #0x1900 p = p + 4 *p = 0xe3a03c19 ' MOV R3, #0x1900 p = p + 4 *p = 0xe12fff35 ' BLX R5 MakeLoader = buf END SUB PRIVATE SUB LoadNBoot() loader = MakeLoader() fd = Open(bootbin,0) IF fd = -1 THEN PutMsg("bootbin size fail") EXIT SUB END IF imgsize = Lseek(fd,0,2) Close(fd) imgbuf = AllocateMemory(imgsize) IF imgbuf = 0 THEN sprintf(msgstr,"alloc %d fail",imgsize) PutMsg(msgstr) EXIT SUB END IF fd = Fopen_Fut(bootbin,"r") IF fd = 0 THEN sprintf(msgstr,"open %s fail",bootbin) PutMsg(msgstr) EXIT SUB END IF rcnt = Fread_Fut(imgbuf,1,imgsize,fd) Fclose_Fut(fd) IF rcnt <> imgsize THEN sprintf(msgstr,"read %d fail",imgsize) PutMsg(msgstr) FreeMemory(imgbuf) EXIT SUB END IF sprintf(msgstr,"%s %d",bootbin,imgsize) PutMsg(msgstr) Wait(500) ' register the start of loader as a function ExportToEventProcedure("loader_func",loader) DispCon_TurnOffDisplay() ' if starting is very slow, watchdog can hit before loading is complete ' but may stay on indefinitely if we crash StopWDT() loader_func(imgbuf,imgsize) ' if loader_func could return, we could try to restore 'StartWDT() 'DispCon_TurnOnDisplay() END SUB PRIVATE SUB Initialize() RegisterProcs() InitMsg() LoadNBoot() END SUB