void * save_crashdump(void *arg) { struct mic_info *mic = (struct mic_info *)arg; struct mpssd_info *mpssdi = (struct mpssd_info *)mic->data; int cdfd = -1; int procfd = -1; void *addr = NULL; ssize_t bytes; ssize_t total_bytes = 0; ssize_t dirlimit; ssize_t diractual; struct tm *tm = NULL; char pathname[PATH_MAX]; time_t t; pid_t pid1 = 0; char *state; char *save; struct stat sbuf; struct statvfs vbuf; int err; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); if ((dirlimit = atoi(CD_LIMIT) * (1024 * 1024 * 1024ULL)) == 0) { mpsslog(PWARN, "%s: [SaveCrashDump] Dump disabled\n", mic->name); goto reboot; } if (stat(CD_DIR, &sbuf) < 0) { if (mkdir(CD_DIR, 0755) < 0) { mpsslog(PWARN, "%s: [SaveCrashDump] Avborted - create directory %s failed: %s\n", mic->name, CD_DIR, strerror(errno)); goto reboot; } diractual = dirlimit; } else { /* Check size of crash directory with configured limits */ if ((diractual = get_dir_size(mic, CD_DIR)) < 0) { mpsslog(PINFO, "%s: [SaveCrashDump] Avborted - get directory %s size failed: %s\n", mic->name, CD_DIR, strerror(errno)); goto reboot; } } if (diractual > dirlimit) { mpsslog(PINFO, "%s: [SaveCrashDump] Avborted - %s current size 0x%lx configured limit 0x%lx\n", mic->name, CD_DIR, diractual, dirlimit); goto reboot; } /* Open core dump file with time details embedded in file name */ time(&t); if ((tm = localtime(&t)) == 0) { mpsslog(PERROR, "%s: [SaveCrashdump] Aborted - get system date failed\n", mic->name); goto reboot; } /* Create crash directories if not done already */ snprintf(pathname, PATH_MAX - 1, "%s/%s", CD_DIR, mic->name); if (mkdir(pathname, 0755) && errno != EEXIST) { mpsslog(PERROR, "%s: [SaveCrashDump] Aborted - create directory %s failed %s\n", mic->name, pathname, strerror(errno)); goto reboot; } if (statvfs(pathname, &vbuf) < 0) { mpsslog(PERROR, "%s: [SaveCrashDump] Aborted - cannot read free disk size of %s: %s\n", mic->name, pathname, strerror(errno)); goto reboot; } if (CD_MIN_DISK > (vbuf.f_bsize * vbuf.f_bfree)) { mpsslog(PERROR, "%s: [SaveCrashDump] Aborted - free disk space less than required 32Gb\n", mic->name); goto reboot; } /* Open vmcore entry for crashed card */ snprintf(pathname, PATH_MAX - 1, "/proc/mic_vmcore/%s", mic->name); if ((procfd = open(pathname, O_RDONLY)) < 0) { mpsslog(PERROR, "%s: [SaveCrashdump] Aborted - open %s failed: %s\n", mic->name, pathname, strerror(errno)); goto reboot; } snprintf(pathname, PATH_MAX - 1, "%s/%s/vmcore-%d-%d-%d-%d:%d:%d", CD_DIR, mic->name, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); if ((cdfd = open(pathname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { mpsslog(PERROR, "%s: [SaveCrashDump] Aborted - open %s failed %s\n", mic->name, pathname, strerror(errno)); goto cleanup1; } mpsslog(PINFO, "%s: [SaveCrashDump] Capturing uOS kernel crash dump\n", mic->name); /* Read from the proc entry and write to the core dump file */ do { if (lseek(cdfd, CD_READ_CHUNK, SEEK_CUR) < 0) { mpsslog(PERROR, "%s: [SaveCrashDump] Aborted lseek failed %s\n", mic->name, strerror(errno)); remove(pathname); goto cleanup2; } bytes = write(cdfd, "", 1); if (bytes != 1) { mpsslog(PERROR, "%s: [SaveCrashDump] Aborted write failed %s\n", mic->name, strerror(errno)); remove(pathname); goto cleanup2; } if ((addr = mmap(NULL, CD_READ_CHUNK, PROT_READ|PROT_WRITE, MAP_SHARED, cdfd, total_bytes)) == MAP_FAILED) { mpsslog(PERROR, "%s: [SaveCrasdDump] Aborted mmap failed %s\n", mic->name, strerror(errno)); remove(pathname); goto cleanup2; } if ((bytes = read(procfd, addr, CD_READ_CHUNK)) < 0) { mpsslog(PERROR, "%s: [SaveCrashDump] Aborted read failed %s\n", mic->name, strerror(errno)); remove(pathname); munmap(addr, CD_READ_CHUNK); goto cleanup2; } total_bytes += bytes; munmap(addr, CD_READ_CHUNK); if (ftruncate(cdfd, total_bytes + 1) < 0) { mpsslog(PERROR, "%s: [SaveCrashDump] Aborted ftruncate failed %s\n", mic->name, strerror(errno)); remove(pathname); goto cleanup2; } } while (bytes == CD_READ_CHUNK); mpsslog(PNORM, "%s: [SaveCrashDump] Completed raw dump size 0x%lx\n", mic->name, total_bytes); mpsslog(PNORM, "%s: [SaveCrashDump] Gzip started\n", mic->name); pid1 = gzip(pathname); /* Initiate compression of the file and reset MIC in parallel */ cleanup2: close(cdfd); cleanup1: close(procfd); reboot: if ((err = mpss_setsysfs(mic->name, "state", "reset:force")) != 0) { mpsslog(PINFO, "%s: [SaveCrashDump] Failed to set state sysfs - cannot reset: %s\n", mic->name, strerror(err)); goto done; } if ((state = mpss_readsysfs(mic->name, "state")) == NULL) { mpsslog(PINFO, "%s: [SaveCrashDump] Failed to read state sysfs - state of reset unknown\n", mic->name); goto done; } while (strcmp(state, "ready") && strcmp(state, "reset failed")) { if (!strcmp(state, "online") || !strcmp(state, "booting")) { mpsslog(PINFO, "%s: [SaveCrashDump] External entity has already rebooted card\n", mic->name); free(state); goto done; } mpsslog(PINFO, "%s: [SaveCrashDump] Waiting for reset\n", mic->name); sleep(2); save = state; if ((state = mpss_readsysfs(mic->name, "state")) == NULL) { mpsslog(PWARN, "%s: [SaveCrashDump] wait for ready failed to read state sysfs - try again\n", mic->name); state = save; } else { free(save); } } if (strcmp(state, "ready")) { mpsslog(PERROR, "%s: [SaveCrashDump] Failed to reset card. Aborting reboot\n", mic->name); free(state); goto done; } if (pid1 && (pid1 < 0 || ((waitpid(pid1, NULL, 0)) < 0))) remove(pathname); if (autoreboot(mic)) { while (pthread_mutex_lock(&start_lock) != 0); start_count++; while (pthread_mutex_lock(&mpssdi->pth_lock) != 0); pthread_create(&mpssdi->boot_pth, NULL, boot_mic, mic); while (pthread_mutex_unlock(&mpssdi->pth_lock) != 0); while (pthread_mutex_unlock(&start_lock) != 0); } done: pthread_exit(NULL); }
void checkAutoFlashing(unsigned long startAddr, int len) { int i=0; unsigned long head_offset=0, srcAddr, burnLen; unsigned short sum=0; unsigned char sum1=0; int skip_header=0; int reboot=0; IMG_HEADER_T Header ; //avoid unalign problem int skip_check_signature=0; unsigned long burn_offset =0; //mark_dual #ifdef CONFIG_RTL_FLASH_DUAL_IMAGE_ENABLE check_dualbank_setting(0); //must do check image to get current boot_bank....... #endif while( (head_offset + sizeof(IMG_HEADER_T)) < len){ sum=0; sum1=0; memcpy(&Header, ((char *)startAddr + head_offset), sizeof(IMG_HEADER_T)); if (!skip_check_signature) { for(i=0 ;i < MAX_SIG_TBL ; i++) { if(!memcmp(Header.signature, (char *)sign_tbl[i].signature, sign_tbl[i].sig_len)) break; } if(i == MAX_SIG_TBL){ head_offset += Header.len + sizeof(IMG_HEADER_T); continue ; } #ifdef CONFIG_BOOT_CODE_SIZE_CHECK if(!memcmp(Header.signature, BOOT_SIGNATURE, SIG_LEN)){ // - checksum len if((Header.len-2) > CONFIG_BOOT_CODE_SIZE){ prom_printf("bootcode is too big\n"); return; } } #endif skip_header = sign_tbl[i].skip ; if(skip_header){ srcAddr = startAddr + head_offset + sizeof(IMG_HEADER_T); burnLen = Header.len; // +checksum }else{ srcAddr = startAddr + head_offset ; burnLen = Header.len + sizeof(IMG_HEADER_T) ; } reboot |= sign_tbl[i].reboot; prom_printf("\n%s upgrade.\n", sign_tbl[i].comment); } else { if(!memcmp(Header.signature, BOOT_SIGNATURE, SIG_LEN)){ #ifdef CONFIG_BOOT_CODE_SIZE_CHECK // - checksum len if((Header.len-2) > CONFIG_BOOT_CODE_SIZE){ prom_printf("bootcode is too big\n"); return; } #endif skip_header = 1; }else { unsigned char *pRoot =((unsigned char *)startAddr) + head_offset + sizeof(IMG_HEADER_T); if (!memcmp(pRoot, SQSH_SIGNATURE, SIG_LEN)) skip_header = 1; else skip_header = 0; } if(skip_header){ srcAddr = startAddr + head_offset + sizeof(IMG_HEADER_T); burnLen = Header.len ; // +checksum }else{ srcAddr = startAddr + head_offset ; burnLen = Header.len + sizeof(IMG_HEADER_T) ; } } if(skip_check_signature || memcmp(Header.signature, WEB_SIGNATURE, 3)){ //calculate checksum if(!memcmp(Header.signature, ALL1_SIGNATURE, SIG_LEN) || !memcmp(Header.signature, ALL2_SIGNATURE, SIG_LEN)) { for (i=0; i< Header.len+sizeof(IMG_HEADER_T); i+=2) { sum += *((unsigned short *)(startAddr+ head_offset + i)); } } else { unsigned char x=0,y=0; unsigned short temp=0; for (i=0; i< Header.len; i+=2) { #if defined(RTL8196B) || defined(RTL8198) #if 1 //sum +=*((unsigned short *)(startAddr+ head_offset + sizeof(IMG_HEADER_T) + i)); memcpy(&temp, (startAddr+ head_offset + sizeof(IMG_HEADER_T) + i), 2); // for alignment issue sum+=temp; #else x=*((unsigned char *)(startAddr+ head_offset + sizeof(IMG_HEADER_T) + i)); y=*((unsigned char *)(startAddr+ head_offset + sizeof(IMG_HEADER_T) + i+1)); sum+=(y|x<<8)&0xFFFF; #endif #else sum += *((unsigned short *)(startAddr+ head_offset + sizeof(IMG_HEADER_T) + i)); #endif //#if defined(RTL8196B) || defined(RTL8198) } } if ( sum ) { prom_printf("%s imgage checksum error at %X!\n" , Header.signature, startAddr+head_offset); return ; } if(!memcmp(Header.signature, ALL1_SIGNATURE, SIG_LEN)){ head_offset += sizeof(IMG_HEADER_T); continue; } if(!memcmp(Header.signature, ALL2_SIGNATURE, SIG_LEN)){ skip_check_signature = 1; head_offset += sizeof(IMG_HEADER_T); continue; } }else { //web page use different checksum algorimth for (i=0; i< Header.len; i++) sum1 += *((unsigned char *)(startAddr+ head_offset + sizeof(IMG_HEADER_T) + i)); if ( sum1 ) { prom_printf("%s imgage checksum error at %X!\n" , Header.signature, startAddr+head_offset); return ; } } prom_printf("checksum Ok !\n"); prom_printf("burn Addr =0x%x! srcAddr=0x%x len =0x%x \n", Header.burnAddr, srcAddr, burnLen); #ifdef CONFIG_RTL_FLASH_DUAL_IMAGE_ENABLE if(!memcmp(Header.signature, FW_SIGNATURE, SIG_LEN) || !memcmp(Header.signature, FW_SIGNATURE_WITH_ROOT, SIG_LEN)) { IMG_HEADER_T header_t, *header_p; header_p = &header_t; burn_offset = sel_burnbank_offset(); prom_printf("burn_offset = %x !\n",burn_offset); memcpy(header_p, ((char *)srcAddr), sizeof(IMG_HEADER_T)); header_p->burnAddr = get_next_bank_mark(); //prom_printf("2 header_p->burn = 0x%x \n", header_p->burnAddr); memcpy(((char *)srcAddr), header_p, sizeof(IMG_HEADER_T)); } else if(!memcmp(Header.signature, ROOT_SIGNATURE, SIG_LEN)) { burn_offset = sel_burnbank_offset(); prom_printf("burn_offset = %x !\n",burn_offset); } #endif int trueorfaulse = 0; #ifdef CONFIG_SPI_FLASH #ifdef SUPPORT_SPI_MIO_8198_8196C if(Header.burnAddr+burn_offset+burnLen > spi_flash_info[0].chip_size) { if(spi_flw_image_mio_8198(0,Header.burnAddr+burn_offset, srcAddr, spi_flash_info[0].chip_size-(Header.burnAddr+burn_offset))&& spi_flw_image_mio_8198(1,0, srcAddr+spi_flash_info[0].chip_size-(Header.burnAddr+burn_offset), Header.burnAddr+burn_offset+burnLen-spi_flash_info[0].chip_size)) trueorfaulse = 1; } else if(spi_flw_image_mio_8198(0,Header.burnAddr+burn_offset, srcAddr, burnLen)) trueorfaulse = 1; #else if(spi_flw_image(0,Header.burnAddr+burn_offset, srcAddr, burnLen)) #endif #else if (flashwrite(Header.burnAddr+burn_offset, srcAddr, burnLen)) #endif if(trueorfaulse) prom_printf("\nFlash Write Successed!\n%s", "<RealTek>"); else{ prom_printf("\nFlash Write Failed!\n%s", "<RealTek>"); return ; } head_offset += Header.len + sizeof(IMG_HEADER_T); } //while if(reboot){ autoreboot(); } }