CHDK Wiki
(where to get a main.bin)
 
Line 1: Line 1:
 
==Canon basic binary loader==
 
==Canon basic binary loader==
 
This script loads and boots the specified ARM binary. The binary should be unencoded, and loadable at 0x1900
 
This script loads and boots the specified ARM binary. The binary should be unencoded, and loadable at 0x1900
  +
  +
After a CHDK build, a suitable binary can be found at <tt>loader/&lt;camera&gt;/main.bin</tt>.
   
 
Tested on a540 (vxworks) and D10 (dryos)
 
Tested on a540 (vxworks) and D10 (dryos)

Latest revision as of 21:02, 15 April 2012

Canon basic binary loader

This script loads and boots the specified ARM binary. The binary should be unencoded, and loadable at 0x1900

After a CHDK build, a suitable binary can be found at loader/<camera>/main.bin.

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