示例#1
0
static void 
do_exec(int argc, char *argv[])
{
    unsigned long oldints;
    bool wait_time_set;
    int  wait_time, res;
    bool cmd_line_set;
    struct option_info opts[4];
    code_fun entry;
    char line[8];
    char *cmd_line;
    int num_options;

    entry = (code_fun)entry_address;  // Default from last 'load' operation
    init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, 
              (void **)&wait_time, (bool *)&wait_time_set, "wait timeout");
    init_opts(&opts[1], 'c', true, OPTION_ARG_TYPE_STR, 
              (void **)&cmd_line, (bool *)&cmd_line_set, "kernel command line");
    num_options = 2;

    if (!scan_opts(argc, argv, 1, opts, num_options, (void *)&entry, 
                   OPTION_ARG_TYPE_NUM, "starting address"))
    {
        return;
    }
    if (entry == (unsigned long)NO_MEMORY) {
        diag_printf("Can't execute Linux - invalid entry address\n");
        return;
    }
    if (cmd_line_set) {
	memcpy((char*)CYGHWR_REDBOOT_AM33_LINUX_CMD_ADDRESS,"cmdline:",8);
        strncpy((char*)CYGHWR_REDBOOT_AM33_LINUX_CMD_ADDRESS+8,cmd_line,256);
	*(char*)(CYGHWR_REDBOOT_AM33_LINUX_CMD_ADDRESS+8+256) = 0;
    }
    else {
	*(char*)(CYGHWR_REDBOOT_AM33_LINUX_CMD_ADDRESS+256) = 0;
    }

    if (wait_time_set) {
        diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
                    (void *)entry, wait_time);
        res = _rb_gets(line, sizeof(line), wait_time*1000);
        if (res == _GETS_CTRLC) {
            return;
        }
    }

#ifdef CYGPKG_IO_ETH_DRIVERS
    eth_drv_stop();
#endif

    HAL_DISABLE_INTERRUPTS(oldints);
    HAL_DCACHE_SYNC();
    HAL_ICACHE_DISABLE();
    HAL_DCACHE_DISABLE();
    HAL_DCACHE_SYNC();
    HAL_ICACHE_INVALIDATE_ALL();
    HAL_DCACHE_INVALIDATE_ALL();
    (*entry)();
}
//
// Execute a Linux kernel - this is a RedBoot CLI command
//
static void 
do_exec(int argc, char *argv[])
{
    unsigned long entry;
    bool wait_time_set, cmd_line_set;
    int  wait_time;
    char *cmd_line;
    char *cline;
    struct option_info opts[2];
    hal_virtual_comm_table_t *__chan;
    int baud_rate;

    bd_t *board_info;
    CYG_INTERRUPT_STATE oldints;
    unsigned long sp = CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE;
    
    init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, 
              (void *)&wait_time, (bool *)&wait_time_set, "wait timeout");
    init_opts(&opts[1], 'c', true, OPTION_ARG_TYPE_STR, 
              (void *)&cmd_line, (bool *)&cmd_line_set, "kernel command line");
    entry = entry_address;  // Default from last 'load' operation
    if (!scan_opts(argc, argv, 1, opts, 2, (void *)&entry, OPTION_ARG_TYPE_NUM, 
                   "[physical] starting address")) {
        return;
    }
    if (entry == (unsigned long)NO_MEMORY) {
        diag_printf("Can't execute Linux - invalid entry address\n");
        return;
    }

    // Determine baud rate on current console
    __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
    baud_rate = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_GETBAUD);
    if (baud_rate <= 0) {
        baud_rate = CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD;
    }

    // Make a little space at the top of the stack, and align to
    // 64-bit boundary.
    sp = (sp-128) & ~7;  // The Linux boot code uses this space for FIFOs
    
    // Copy the commandline onto the stack, and set the SP to just below it.
    if (cmd_line_set) {
	int len,i;

	// get length of string
	for( len = 0; cmd_line[len] != '\0'; len++ );

	// decrement sp by length of string and align to
	// word boundary.
	sp = (sp-(len+1)) & ~3;

	// assign this SP value to command line start
	cline = (char *)sp;

	// copy command line over.
	for( i = 0; i < len; i++ )
	    cline[i] = cmd_line[i];
	cline[len] = '\0';

    } else {
        cline = (char *)NULL;
    }
    
    // Set up parameter struct at top of stack
    sp = sp-sizeof(bd_t);
    board_info = (bd_t *)sp;
    memset(board_info, sizeof(*board_info), 0);
    
    board_info->bi_tag		= 0x42444944;
    board_info->bi_size		= sizeof(*board_info);
    board_info->bi_revision	= 1;
    board_info->bi_bdate	= 0x06012002;
    board_info->bi_memstart	= CYGMEM_REGION_ram;
    board_info->bi_memsize	= CYGMEM_REGION_ram_SIZE;
    board_info->bi_baudrate     = baud_rate;
    board_info->bi_cmdline      = cline;
#ifdef CYGPKG_REDBOOT_NETWORKING
    memcpy(board_info->bi_enetaddr, __local_enet_addr, sizeof(enet_addr_t));
#endif
    // Call platform specific code to fill in the platform/architecture specific details
    plf_redboot_linux_exec(board_info);

    // adjust SP to 64 byte boundary, and leave a little space
    // between it and the commandline for PowerPC calling
    // conventions.
	
    sp = (sp-64)&~63;

    if (wait_time_set) {
        int script_timeout_ms = wait_time * 1000;
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
        unsigned char *hold_script = script;
        script = (unsigned char *)0;
#endif
        diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
                    (void *)entry, wait_time);
        while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
            int res;
            char line[80];
            res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
            if (res == _GETS_CTRLC) {
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
                script = hold_script;  // Re-enable script
#endif
                return;
            }
            script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
        }
    }

#ifdef CYGPKG_IO_ETH_DRIVERS
    eth_drv_stop();
#endif

    // Disable interrupts
    HAL_DISABLE_INTERRUPTS(oldints);

    // Put the caches to sleep.
    HAL_DCACHE_SYNC();
    HAL_ICACHE_DISABLE();
    HAL_DCACHE_DISABLE();
    HAL_DCACHE_SYNC();
    HAL_ICACHE_INVALIDATE_ALL();
    HAL_DCACHE_INVALIDATE_ALL();

//    diag_printf("entry %08x, sp %08x, info %08x, cmd line %08x, baud %d\n",
//		entry, sp, board_info, cline, baud_rate);
//    breakpoint();
    
    // Call into Linux
    __asm__ volatile (        
	               // Start by disabling MMU - the mappings are
	               // 1-1 so this should not cause any problems
	               "mfmsr	3\n"
		       "li      4,0xFFFFFFCF\n"
		       "and	3,3,4\n"
		       "sync\n"
		       "mtmsr	3\n"
		       "sync\n"

		       // Now set up parameters to jump into linux

		       "mtlr	%0\n"		// set entry address in LR
		       "mr	1,%1\n"		// set stack pointer
		       "mr	3,%2\n"		// set board info in R3
		       "mr	4,%3\n"		// set command line in R4
		       "blr          \n"	// jump into linux
		       :
		       : "r"(entry),"r"(sp),"r"(board_info),"r"(cline)
		       : "r3", "r4"
	             
	             );
}
示例#3
0
文件: main.c 项目: cilynx/dd-wrt
void
do_go(int argc, char *argv[])
{
    int i, cur, num_options;
    unsigned long entry;
    unsigned long oldints;
    bool wait_time_set;
    int  wait_time, res;
    bool cache_enabled = false;
#ifdef CYGPKG_IO_ETH_DRIVERS
    bool stop_net = false;
#endif
    struct option_info opts[3];
    char line[8];
    hal_virtual_comm_table_t *__chan;

    __mem_fault_handler = 0; // Let GDB handle any faults directly
    entry = entry_address;  // Default from last 'load' operation
    init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, 
              (void *)&wait_time, (bool *)&wait_time_set, "wait timeout");
    init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, 
              (void *)&cache_enabled, (bool *)0, "go with caches enabled");
    num_options = 2;
#ifdef CYGPKG_IO_ETH_DRIVERS
    init_opts(&opts[2], 'n', false, OPTION_ARG_TYPE_FLG, 
              (void *)&stop_net, (bool *)0, "go with network driver stopped");
    num_options++;
#endif

    CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");

    if (!scan_opts(argc, argv, 1, opts, num_options, (void *)&entry, OPTION_ARG_TYPE_NUM, "starting address"))
    {
        return;
    }
    if (entry == (unsigned long)NO_MEMORY) {
        diag_printf("No entry point known - aborted\n");
        return;
    }
    if (wait_time_set) {
        int script_timeout_ms = wait_time * 1000;
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
        unsigned char *hold_script = script;
        script = (unsigned char *)0;
#endif
        diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
                    (void *)entry, wait_time);
        while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
            res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
            if (res == _GETS_CTRLC) {
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
                script = hold_script;  // Re-enable script
#endif
                return;
            }
            script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
        }
    }

    // Mask interrupts on all channels
    cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
    for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS;  i++) {
	CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
	__chan = CYGACC_CALL_IF_CONSOLE_PROCS();
	CYGACC_COMM_IF_CONTROL( *__chan, __COMMCTL_IRQ_DISABLE );
    }
    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);

    __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
    CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_ENABLE_LINE_FLUSH);

#ifdef CYGPKG_IO_ETH_DRIVERS
    if (stop_net)
	eth_drv_stop();
#endif
	
    HAL_DISABLE_INTERRUPTS(oldints);
    HAL_DCACHE_SYNC();
    if (!cache_enabled) {
	HAL_ICACHE_DISABLE();
	HAL_DCACHE_DISABLE();
	HAL_DCACHE_SYNC();
    }
    HAL_ICACHE_INVALIDATE_ALL();
    HAL_DCACHE_INVALIDATE_ALL();
    // set up a temporary context that will take us to the trampoline
    HAL_THREAD_INIT_CONTEXT((CYG_ADDRESS)workspace_end, entry, trampoline, 0);

    // switch context to trampoline
    HAL_THREAD_SWITCH_CONTEXT(&saved_context, &workspace_end);

    // we get back here by way of return_to_redboot()

    // undo the changes we made before switching context
    if (!cache_enabled) {
	HAL_ICACHE_ENABLE();
	HAL_DCACHE_ENABLE();
    }

    CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DISABLE_LINE_FLUSH);

    HAL_RESTORE_INTERRUPTS(oldints);

    diag_printf("\nProgram completed with status %d\n", return_status);
}