// NAND flash bcm image 
// return: 
// 0 - ok
// !0 - the sector number fail to be flashed (should not be 0)
static int nandImageSet( int flash_start_addr, char *string, int img_size)
{
    int sts = -1;
    int blk = 0;
    int i;
    struct mtd_info *mtd  = NULL;
    struct mtd_info *mtd0 = get_mtd_device_nm("rootfs");
    struct mtd_info *mtd1 = get_mtd_device_nm("nvram");

    if( mtd0 && mtd1 )
    {
        // Disable other tasks from this point on
#if defined(CONFIG_SMP)
        smp_send_stop();
        udelay(20);
#endif
        local_bh_disable();

        if( *(unsigned short *) string == JFFS2_MAGIC_BITMASK )
            mtd = mtd0; /* only flash file system */
        else
        {
            mtd = mtd1; /* flash first boot block and then file system */

            /* Copy NVRAM data to block to be flashed so it is preserved. */
            memcpy(string + NVRAM_DATA_OFFSET, (unsigned char *)&bootNvramData,
                sizeof(NVRAM_DATA));
        }

        sts = blk = 0;
        while( sts == 0 )
        {
            /* block_is bad returns 0 if block is not bad */
            if( mtd->block_isbad(mtd, blk) == 0 )
            {
                unsigned char oobbuf[64]; /* expected to be a max size */
                struct mtd_oob_ops ops;

                ops.ooblen = mtd->oobsize;
                ops.ooboffs = 0;
                ops.datbuf = NULL;
                ops.oobbuf = oobbuf;
                ops.len = 0;
                ops.mode = MTD_OOB_PLACE;

                /* Read and save the spare area. */
                sts = mtd->read_oob(mtd, blk, &ops);
                if( sts == 0 )
                {
                    struct erase_info erase;

                    /* Erase the flash block. */
                    memset(&erase, 0x00, sizeof(erase));
                    erase.addr = blk;
                    erase.len = mtd->erasesize;
                    erase.mtd = mtd;

                    sts = mtd->erase(mtd, &erase);
                    if( sts == 0 )
                    {
                        /* Function local_bh_disable has been called and this
                         * is the only operation that should be occurring.
                         * Therefore, spin waiting for erase to complete.
                         */
                        for(i = 0; i < 10000 && erase.state != MTD_ERASE_DONE &&
                            erase.state != MTD_ERASE_FAILED; i++ )
                        {
                            udelay(100);
                        }

                        if( erase.state != MTD_ERASE_DONE )
                            sts = -1;
                    }

                    if( sts == 0 )
                    {
                        ops.ooblen = mtd->oobsize;
                        ops.ooboffs = 0;
                        ops.datbuf = NULL;
                        ops.oobbuf = oobbuf;
                        ops.len = 0;
                        ops.mode = MTD_OOB_PLACE;

                        /* Restore the spare area. */
                        sts = mtd->write_oob(mtd, blk, &ops);

                        /* Write out a block of the image if there is still
                         * image left to flash.
                         */
                        if( sts == 0 && blk < img_size )
                        {
                            int retlen = 0;

                            /* Write a block of the image to flash. */
                            sts = mtd->write(mtd, blk, mtd->erasesize, &retlen,
                                string);

                            string += mtd->erasesize;
                            printk(".");

                            if( retlen != mtd->erasesize )
                                sts = -1;

                            if( sts )
                                printk("nandImageSet - Block 0x%8.8x. Error writing"
                                    " block.\n", blk);
                        }
                        else
                            if( sts )
                                printk("nandImageSet - Block 0x%8.8x. Error writing"
                                    " spare area.\n", blk);
                    }
                    else
                        printk("nandImageSet - Block 0x%8.8x. Error erasing "
                            "block.\n", blk);
                }
                else
                    printk("nandImageSet - Block 0x%8.8x. Error read spare area.\n",
                        blk);
            }

            if( mtd == mtd1 )
            {
                /* The first raw, boot block was flashed.  Change to rootfs. */
                img_size -= mtd->erasesize;
                mtd = mtd0;
                blk = 0;
            }
            else
            {
                /* Update to next block, stop when all blocks flashed. */
                blk += mtd->erasesize;
                if( blk >= mtd->size )
                    break;
            }
        }

        local_bh_enable();

        if( sts )
            sts = (blk > mtd->erasesize) ? blk / mtd->erasesize : 1;
    }

    if( mtd0 )
        put_mtd_device(mtd0);

    if( mtd1 )
        put_mtd_device(mtd1);

    return sts;
}
// flash bcm image 
// return: 
// 0 - ok
// !0 - the sector number fail to be flashed (should not be 0)
int kerSysBcmImageSet( int flash_start_addr, char *string, int size)
{
    int sts;
    int sect_size;
    int blk_start;
    int savedSize = size;
    int whole_image = 0;

    if( bootFromNand )
        return( nandImageSet( flash_start_addr, string, size ) );

    if (flash_start_addr == FLASH_BASE)
        whole_image = 1;

#if defined(DEBUG_FLASH)
    printk("kerSysBcmImageSet: flash_start_addr=0x%x string=%p len=%d whole_image=%d\n",
           flash_start_addr, string, size, whole_image);
#endif

    blk_start = flash_get_blk(flash_start_addr);
    if( blk_start < 0 )
        return( -1 );

    // Disable other tasks from this point on
#if defined(CONFIG_SMP)
    smp_send_stop();
    udelay(20);
#endif
    local_bh_disable();

    /* write image to flash memory */
    do 
    {
        sect_size = flash_get_sector_size(blk_start);

        flash_sector_erase_int(blk_start);     // erase blk before flash

        if (sect_size > size) 
        {
            if (size & 1) 
                size++;
            sect_size = size;
        }
        
        if (flash_write_buf(blk_start, 0, string, sect_size) != sect_size) {
            break;
        }

        printk(".");
        blk_start++;
        string += sect_size;
        size -= sect_size; 
    } while (size > 0);

    if (whole_image && savedSize > fInfo.flash_rootfs_start_offset)
    {
        // If flashing a whole image, erase to end of flash.
        int total_blks = flash_get_numsectors();
        while( blk_start < total_blks )
        {
            flash_sector_erase_int(blk_start);
            printk(".");
            blk_start++;
        }
    }

    printk("\n\n");

    if( size == 0 ) 
        sts = 0;  // ok
    else  
        sts = blk_start;    // failed to flash this sector

    local_bh_enable();

    return sts;
}
/*
 * Halting simply requires that the secondary CPUs stop performing any
 * activity (executing tasks, handling interrupts). smp_send_stop()
 * achieves this.
 */
void machine_halt(void)
{
	local_irq_disable();
	smp_send_stop();
	while (1);
}
Beispiel #4
0
static void native_machine_shutdown(void)
{
	smp_send_stop();
}
Beispiel #5
0
NORET_TYPE void panic(const char * fmt, ...)
{
	long i;
	static char buf[1024];
	va_list args;
#if defined(CONFIG_S390)
	unsigned long caller = (unsigned long) __builtin_return_address(0);
#endif

	/*
	 * It's possible to come here directly from a panic-assertion and not
	 * have preempt disabled. Some functions called from here want
	 * preempt to be disabled. No point enabling it later though...
	 */
	preempt_disable();
             
	bust_spinlocks(1);
	va_start(args, fmt);
	vsnprintf(buf, sizeof(buf), fmt, args);
	va_end(args);
	printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
	bust_spinlocks(0);

	/*
	 * If we have crashed and we have a crash kernel loaded let it handle
	 * everything else.
	 * Do we want to call this before we try to display a message?
	 */
	crash_kexec(NULL);

#ifdef CONFIG_SMP
	/*
	 * Note smp_send_stop is the usual smp shutdown function, which
	 * unfortunately means it may not be hardened to work in a panic
	 * situation.
	 */
	smp_send_stop();
#endif

	atomic_notifier_call_chain(&panic_notifier_list, 0, buf);

	if (!panic_blink)
		panic_blink = no_blink;
	if (panic_timeout > 0) {
		/*
	 	 * Delay timeout seconds before rebooting the machine. 
		 * We can't use the "normal" timers since we just panicked..
	 	 */
		printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
		for (i = 0; i < panic_timeout*1000; ) {
			touch_nmi_watchdog();
			i += panic_blink(i);
			mdelay(1);
			i++;
		}
		/*	This will not be a clean reboot, with everything
		 *	shutting down.  But if there is a chance of
		 *	rebooting the system it will be rebooted.
		 */
		emergency_restart();
	}
#ifdef __sparc__
	{
		extern int stop_a_enabled;
		/* Make sure the user can actually press Stop-A (L1-A) */
		stop_a_enabled = 1;
		printk(KERN_EMERG "Press Stop-A (L1-A) to return to the boot prom\n");
	}
#endif
#if defined(CONFIG_S390)
	disabled_wait(caller);
#endif
             
        rk28_panic_reset(); /* HSL@RK,20091118 */
	local_irq_enable();
	for (i = 0;;) {
		touch_softlockup_watchdog();
		i += panic_blink(i);
		mdelay(1);
		i++;
	}
}