CHDK Wiki
Advertisement

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
Advertisement