Source

Magic Lantern / reboot.c

Full commit
/*
 * This program is very simple: attempt to reboot into the normal
 * firmware RAM image after startup.
 */
#include "arm-mcr.h"


asm(
".text"
"_start:\n"
".global _start\n"
"	ldr pc, [pc,#4]\n"	// 0x120
".ascii \"gaonisoy\"\n"		// 0x124, 128
".word 0x800130\n"		// 0x12C
"MRS     R0, CPSR\n"
"BIC     R0, R0, #0x3F\n"	// Clear I,F,T
"ORR     R0, R0, #0xD3\n"	// Set I,T, M=10011 == supervisor
"MSR     CPSR, R0\n"
"	ldr sp, =0x1900\n"	// 0x130
"	mov fp, #0\n"
"	b cstart\n"
);


/** Include the relocatable shim code */
extern uint8_t blob_start;
extern uint8_t blob_end;

asm(
	".text\n"
	".align 12\n" // 2^12 == 4096 bytes
	".globl blob_start\n"
	"blob_start:\n"
	".incbin \"5d-hack.bin\"\n" // 
	".align 12\n"
	"blob_end:\n"
	".globl blob_end\n"
);



/**** Hacks ****/

/*
	// Disable the bitmap drawing routine
	volatile uint32_t * draw_bitmap = (void*)( 0xffb08bbc - ROMBASEADDR + RESTARTSTART );
	draw_bitmap[0] = 0xe3a00001;
	draw_bitmap[1] = 0xe12fff1e;
*/

/*
	// Add a spin loop somewhere early in setup
	volatile uint32_t * startup = (uint32_t*) 0x00050894;
	*startup = 0xeafffffe;
*/

/*
	// Disable AGC by always returning the same level
	const uint32_t audio_level = 40;
	const uint32_t instr = 0xe3e02000 | audio_level;
	*(volatile uint32_t*)( 0xFF972628 - ROMBASEADDR + RESTARTSTART ) = instr;
*/


void
__attribute__((noreturn))
cstart( void )
{
#if 0
	// Poke the DMA space.  Why?  I don't know.
	volatile uint32_t * dma_space = (void*) 0xC0000000;
	dma_space[ 0 ] = 0xD9C5D9C5;

	volatile uint32_t * dma = (uint32_t*) 0xC0200000;
	dma[ 0x10C / 4 ] = -1;
	dma[ 0x0C / 4 ] = -1;
	dma[ 0x1C / 4 ] = -1;
	dma[ 0x2C / 4 ] = -1;
	dma[ 0x3C / 4 ] = -1;
	dma[ 0x4C / 4 ] = -1;
	dma[ 0x5C / 4 ] = -1;
	dma[ 0x6C / 4 ] = -1;
	dma[ 0x7C / 4 ] = -1;
	dma[ 0x8C / 4 ] = -1;
	dma[ 0xAC / 4 ] = -1;
	dma[ 0xBC / 4 ] = -1;
	dma[ 0xCC / 4 ] = -1;
	dma[ 0xEC / 4 ] = -1;
	dma[ 0xFC / 4 ] = -1;
#endif

#if 1
	set_i_tcm( 0x40000006 );
	set_control_reg( read_control_reg() | 0x10000 );

	// Install the memory regions
	setup_memory_region( 0, 0x0000003F );
	setup_memory_region( 1, 0x0000003D );
	setup_memory_region( 2, 0xE0000039 );
	setup_memory_region( 3, 0xC0000039 );
	setup_memory_region( 4, 0xFF80002D );
	setup_memory_region( 5, 0x00000039 );
	setup_memory_region( 6, 0xF780002D );
	setup_memory_region( 7, 0x00000000 );

	set_d_cache_regions( 0x70 );
	set_i_cache_regions( 0x70 );
	set_d_buffer_regions( 0x70 );
	set_d_rw_regions( 0x3FFF );
	set_i_rw_regions( 0x3FFF );
	set_control_reg( read_control_reg() | 0xC000107D );

	select_normal_vectors();
#endif

	// Copy the copy-and-restart blob somewhere
	// there is a bug in that we are 0x120 bytes off from
	// where we should be, so we must offset the blob start.
	blob_memcpy(
		(void*) RESTARTSTART,
		&blob_start + 0x120,
		&blob_end + 0x120
	);
	clean_d_cache();
	flush_caches();

	// Jump into the newly relocated code
	void __attribute__((noreturn))(*copy_and_restart)(void)
		= (void*) RESTARTSTART;

	void __attribute__((noreturn))(*firmware_start)(void)
		= (void*) ROMBASEADDR;

	if( 1 )
		copy_and_restart();
	else
		firmware_start();

	// Unreachable
	while(1)
		;


#if 0
	// Disable the bitmap drawing routine
	volatile uint32_t * draw_bitmap = (void*) 0xffb08bbc;
	draw_bitmap[0] = 0xe3a00001;
	draw_bitmap[1] = 0xe12fff1e;

	// Add a spin loop somewhere early in setup
	volatile uint32_t * startup = (uint32_t*) 0xff810894;
	//volatile uint32_t * startup = (uint32_t*) 0xf8010894;
	*startup = 0xeafffffe;

	if( *startup == 0xe52de004 ) // 0xeafffffe )
		while(1)
			;
#endif


#ifdef BLINK_LED
	while(1)
	{
		volatile uint16_t * led = (void*) 0xE0000000;
		int i;

		const uint32_t on_cmd = 0x180e0001;
		const uint32_t off_cmd = 0x180e0000;

		led[3] = (on_cmd >> 24) & 0xFF;
		led[2] = (on_cmd >> 16) & 0xFF;
		led[1] = (on_cmd >>  8) & 0xFF;
		led[0] = (on_cmd >>  0) & 0xFF;

		for( i=0 ; i<0x200000 ; i++ )
			asm( "nop\n nop\n" );

		led[3] = (off_cmd >> 24) & 0xFF;
		led[2] = (off_cmd >> 16) & 0xFF;
		led[1] = (off_cmd >>  8) & 0xFF;
		led[0] = (off_cmd >>  0) & 0xFF;

		for( i=0 ; i<0x200000 ; i++ )
			asm( "nop\n nop\n" );
	}
#endif // BLINK_LED
		

#if 0
	//void __attribute__((noreturn))(*restart_vector)( void ) = (void*) (new_image + 0xC/4);
	void __attribute__((noreturn))(*restart_vector)( void ) = firmware_start;
	restart_vector();

#if 0
	char * msg	= (void*) (0xFF800000 + 0x10794);
	//char * msg	= (void*) (0x41f00000 + 0xf85e3);
	msg[0] = 'C';
	msg[1] = 'i';
	msg[2] = 'n';
	msg[3] = 'e';

/*
	msg[4] = 'm';
	msg[5] = 'a';
	msg[6] = '5';
	msg[7] = 'd';
	msg[8] = '.';
	msg[9] = 'c';
	msg[10] = 'o';
	msg[11] = 'm';

	// Disable AGC by always returning the same level
	const uint32_t audio_level = 40;
	const uint32_t instr = 0xe3e02000 | audio_level;
	*(volatile uint32_t*) 0xFF972628 = instr;

*/


/*
	// Rewrite the DMA device parameters
	uint32_t i;
	volatile uint32_t * device = (void*) 0xC0200000;
	const uint32_t ffffffff = ~0;
	device[ 67 ] = ffffffff;
	for( i = 3 ; i < 64 ; i += 4 )
		device[ i ] = ffffffff;
*/
#endif
	// Spin in an early setup routine
	// *(volatile uint32_t*) 0xff81000c = 0xea000006;

	// Disable the firmware update menu
	// *(volatile uint32_t*) 0xffbe6624 = 0xe12fff1e;


	void (* dst_void)(void)	= (void*) 0xFF810000;
	//void (* dst_void)(void)	= (void*) 0xF8010000;
	asm __volatile__(
                
/*
                 "LDR     R1, =0xC0200000\n"
                 "MVN     R0, #0\n"
                 "STR     R0, [R1,#0x10C]\n"
                 "STR     R0, [R1,#0xC]\n"
                 "STR     R0, [R1,#0x1C]\n"
                 "STR     R0, [R1,#0x2C]\n"
                 "STR     R0, [R1,#0x3C]\n"
                 "STR     R0, [R1,#0x4C]\n"
                 "STR     R0, [R1,#0x5C]\n"
                 "STR     R0, [R1,#0x6C]\n"
                 "STR     R0, [R1,#0x7C]\n"
                 "STR     R0, [R1,#0x8C]\n"
                 "STR     R0, [R1,#0x9C]\n"
                 "STR     R0, [R1,#0xAC]\n"
                 "STR     R0, [R1,#0xBC]\n"
                 "STR     R0, [R1,#0xCC]\n"
                 "STR     R0, [R1,#0xDC]\n"
                 "STR     R0, [R1,#0xEC]\n"
                 "STR     R0, [R1,#0xFC]\n"
*/
                 "MOV     R0, #0x78\n"
                 "MCR     p15, 0, R0,c1,c0\n"
                 "MOV     R0, #0\n"
                 "MCR     p15, 0, R0,c7,c10, 4\n"
                 "MCR     p15, 0, R0,c7,c5\n"
                 "MCR     p15, 0, R0,c7,c6\n"
                 "MOV     R0, #0x40000006\n"
                 "MCR     p15, 0, R0,c9,c1\n"
                 "MCR     p15, 0, R0,c9,c1, 1\n"
                 "MRC     p15, 0, R0,c1,c0\n"
                 "ORR     R0, R0, #0x50000\n"
                 "MCR     p15, 0, R0,c1,c0\n"
                 "LDR     R0, =0x12345678\n"
                 "MOV     R1, #0x40000000\n"
                 "STR     R0, [R1,#0xFFC]\n"
                 "MOV     R0, %0\n"              // new jump-vector
                 "LDMFD   SP!, {R4,LR}\n"
                 "BX      R0\n"
		: : "r"(dst_void) : "r0"
	);


#if 0
		"mov r0, #0;"
		"mcr p15, 0, r0, c7, c7, 0;"	// clear I+D cache
		"mcr p15, 0, r0, c7, c10, 4;"	// drain write buffer
		"mcr p15, 0, r0, c8, c7, 0;"	// invalidate tlbs

		"MOV     R0, #0x80000006\n"
		"MCR     p15, 0, R0,c9,c1\n"
		"MCR     p15, 0, R0,c9,c1, 1\n"
		"MRC     p15, 0, R0,c1,c0\n"
		"ORR     R0, R0, #0x50000\n"
		"MCR     p15, 0, R0,c1,c0\n"
		"LDR     R0, =0x12345678\n"
		"MOV     R1, #0x80000000\n"
		"STR     R0, [R1,#0xFFC]\n"

/*
		// Read cache settings
		"mrc p15, 0, r0, c1, c0, 0;"
		"bic r0, r0, #0x1000;"		// disable I cache
		"bic r0, r0, #0x0007;"		// disable dache, mmu and align
		"mcr p15, 0, r0, c1, c0, 0;"
		"nop;"
		"mov	pc, %0;"
		"MCR     p15, 0, R0,c7,c10, 4\n"
		"MCR     p15, 0, R0,c7,c5\n"  
		"MCR     p15, 0, R0,c7,c6\n"
		"MOV     R0, #0x80000006\n"
		"MCR     p15, 0, R0,c9,c1\n"
		"MCR     p15, 0, R0,c9,c1, 1\n"
		"MRC     p15, 0, R0,c1,c0\n"
		"ORR     R0, R0, #0x50000\n"
		"MCR     p15, 0, R0,c1,c0\n"
		"LDR     R0, =0x12345678\n"
		"MOV     R1, #0x80000000\n"
		"STR     R0, [R1,#0xFFC]\n"
*/
		"BX      %0"
		: : "r"(dst_void) : "r0"
	);
#endif
#endif

	// Not reached
	while(1)
		;
}