CHDK Wiki
(add canon basic loader)
 
(Adding categories)
Line 152: Line 152:
   
 
</source>
 
</source>
  +
[[Category:CanonBasic]]
  +
[[Category:Development]]
  +
[[Category:Scripts]]

Revision as of 07:02, 20 September 2010

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)

' bootbin is the image to load
DIM bootbin = "A/MAIN.BIN"
DIM lcdmsg=0
DIM msgstr=0

PRIVATE SUB RegisterProcs()
	' ExecuteEventProcedure does is not registered by default on vx
	' Newer cams seem to have this as an alias for System.Create()
	SystemEventInit()
	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
' 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