Esempio n. 1
0
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);
}
Esempio n. 2
0
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();
	}
		
}