// 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); }
static void native_machine_shutdown(void) { smp_send_stop(); }
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++; } }