/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ int load_565rle_image(char *filename) { struct fb_info *info; int fd, count, err = 0; unsigned max; unsigned short *data, *ptr; char *bits; pixel_set_t pixel_set; info = registered_fb[0]; if (!info) { printk(KERN_WARNING "%s: Can not access framebuffer\n", __func__); return -ENODEV; } switch (info->var.bits_per_pixel) { case 16: pixel_set = memset16; break; case 32: pixel_set = pixel_set_rgba; break; default: printk(KERN_WARNING "%s: Can not find pixel_set operation\n", __func__); return -EDOM; } fd = sys_open(filename, O_RDONLY, 0); if (fd < 0) { printk(KERN_WARNING "%s: Can not open %s\n", __func__, filename); return -ENOENT; } count = sys_lseek(fd, (off_t)0, 2); if (count <= 0) { err = -EIO; goto err_logo_close_file; } sys_lseek(fd, (off_t)0, 0); data = kmalloc(count, GFP_KERNEL); if (!data) { printk(KERN_WARNING "%s: Can not alloc data\n", __func__); err = -ENOMEM; goto err_logo_close_file; } if (sys_read(fd, (char *)data, count) != count) { err = -EIO; goto err_logo_free_data; } max = fb_width(info) * fb_height(info); ptr = data; bits = info->screen_base; while (count > 3) { unsigned n = ptr[0]; if (n > max) break; bits += pixel_set(bits, ptr[1], n); max -= n; ptr += 2; count -= 4; } err_logo_free_data: kfree(data); err_logo_close_file: sys_close(fd); return err; }
int ts_calibration_for_touch_key_region(char *filename, int *cal_data) { int fd, err = 0; int count, i,j,ii, count1 = 0; int cal_data_count = 0; char data1[50]= {0,}; char data2[10]= {0,}; int value = 0, value1 = 0; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); printk("[SWIFT]TS_CAL. sys_open-- for READ........\n"); fd = sys_open(filename, O_RDWR, 0); if (fd < 0) { printk(KERN_WARNING "%s: Can not open %s\n", __func__, filename); return -ENOENT; } printk("[SWIFT]TS_CAL. sys_lseek........\n"); count = sys_lseek(fd, (off_t)0, 2); if (count == 0) { printk("[SWIFT]TS_CAL. sys_lseek ERROR count == 0........\n"); err = -EIO; goto err_close_file; } sys_lseek(fd, (off_t)0, 0); printk("[SWIFT]TS_CAL. kmalloc......count[%d]..\n",count); printk("[SWIFT] sys_read........\n"); (unsigned)sys_read(fd, (char *)data1, count); count1 = 0; for(i =0 ; i < count ; i++) { //printk("data[%d]=0x%x\n",i,data1[i]); if((data1[i]== 0x2C)||(data1[i]== 0x0D)||data1[i]== 0x0A) { ii = 0; value = 0; while(count1 > 0) { count1-=1; for(j=0, value1=1; j < count1 ; j++) value1*= 10; value +=(data2[ii]-0x30)*value1; //printk("[SWIFT]ii[%d] FIND value[%d]..data2[%d]... count1[%d]\n",ii,value,data2[ii],count1); if (count1 == 0) { cal_data[cal_data_count] = value; cal_data_count++; } ii++; } memset(data2,0x00,sizeof(data2)); count1 = 0; } else { data2[count1]= data1[i]; //printk("[SWIFT] count1[%d]..data2[0x%x]....data1[0x%x]..i[%d]...\n",count1,data2[count1],data1[i],i); count1+=1; } } printk("[SWIFT]TS_CAL. sys_close........\n"); sys_close(fd); set_fs(old_fs); return 0; err_close_file: printk("[SWIFT]err_close_file!!........\n"); sys_close(fd); set_fs(old_fs); return err; }
static int syscall_dispatch(uint32_t sysnum, uint32_t args, regs_t *regs) { switch (sysnum) { case SYS_waitpid: return sys_waitpid((waitpid_args_t *)args); case SYS_exit: do_exit((int)args); panic("exit failed!\n"); return 0; case SYS_thr_exit: kthread_exit((void *)args); panic("thr_exit failed!\n"); return 0; case SYS_thr_yield: sched_make_runnable(curthr); sched_switch(); return 0; case SYS_fork: return sys_fork(regs); case SYS_getpid: return curproc->p_pid; case SYS_sync: sys_sync(); return 0; #ifdef __MOUNTING__ case SYS_mount: return sys_mount((mount_args_t *) args); case SYS_umount: return sys_umount((argstr_t *) args); #endif case SYS_mmap: return (int) sys_mmap((mmap_args_t *) args); case SYS_munmap: return sys_munmap((munmap_args_t *) args); case SYS_open: return sys_open((open_args_t *) args); case SYS_close: return sys_close((int)args); case SYS_read: return sys_read((read_args_t *)args); case SYS_write: return sys_write((write_args_t *)args); case SYS_dup: return sys_dup((int)args); case SYS_dup2: return sys_dup2((dup2_args_t *)args); case SYS_mkdir: return sys_mkdir((mkdir_args_t *)args); case SYS_rmdir: return sys_rmdir((argstr_t *)args); case SYS_unlink: return sys_unlink((argstr_t *)args); case SYS_link: return sys_link((link_args_t *)args); case SYS_rename: return sys_rename((rename_args_t *)args); case SYS_chdir: return sys_chdir((argstr_t *)args); case SYS_getdents: return sys_getdents((getdents_args_t *)args); case SYS_brk: return (int) sys_brk((void *)args); case SYS_lseek: return sys_lseek((lseek_args_t *)args); case SYS_halt: sys_halt(); return -1; case SYS_set_errno: curthr->kt_errno = (int)args; return 0; case SYS_errno: return curthr->kt_errno; case SYS_execve: return sys_execve((execve_args_t *)args, regs); case SYS_stat: return sys_stat((stat_args_t *)args); case SYS_uname: return sys_uname((struct utsname *)args); case SYS_debug: return sys_debug((argstr_t *)args); case SYS_kshell: return sys_kshell((int)args); default: dbg(DBG_ERROR, "ERROR: unknown system call: %d (args: %#08x)\n", sysnum, args); curthr->kt_errno = ENOSYS; return -1; } }
COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, compat_off_t, offset, unsigned int, whence) { return sys_lseek(fd, offset, whence); }
/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ int load_565rle_image(char *filename, bool bf_supported) { struct fb_info *info; int fd, count, err = 0; unsigned max; unsigned short *data, *bits, *ptr; #ifndef CONFIG_FRAMEBUFFER_CONSOLE struct module *owner; #endif int pad; info = registered_fb[0]; if (!info) { printk(KERN_WARNING "%s: Can not access framebuffer\n", __func__); return -ENODEV; } #ifndef CONFIG_FRAMEBUFFER_CONSOLE owner = info->fbops->owner; if (!try_module_get(owner)) return -ENODEV; if (info->fbops->fb_open && info->fbops->fb_open(info, 0)) { module_put(owner); return -ENODEV; } #endif fd = sys_open(filename, O_RDONLY, 0); if (fd < 0) { printk(KERN_WARNING "%s: Can not open %s\n", __func__, filename); return -ENOENT; } count = sys_lseek(fd, (off_t)0, 2); if (count <= 0) { err = -EIO; goto err_logo_close_file; } sys_lseek(fd, (off_t)0, 0); data = kmalloc(count, GFP_KERNEL); if (!data) { printk(KERN_WARNING "%s: Can not alloc data\n", __func__); err = -ENOMEM; goto err_logo_close_file; } if (sys_read(fd, (char *)data, count) != count) { err = -EIO; goto err_logo_free_data; } max = fb_width(info) * fb_height(info); ptr = data; if (bf_supported && (info->node == 1 || info->node == 2)) { err = -EPERM; pr_err("%s:%d no info->creen_base on fb%d!\n", __func__, __LINE__, info->node); goto err_logo_free_data; } if (info->screen_base) { bits = (unsigned short *)(info->screen_base); while (count > 3) { unsigned n = ptr[0]; if (n > max) break; if (info->var.bits_per_pixel >= 24) { pad = memset16_rgb8888(bits, ptr[1], n << 1, info); bits += n << 1; bits += pad; } else { memset16(bits, ptr[1], n << 1); bits += n; } max -= n; ptr += 2; count -= 4; } } err = 0; err_logo_free_data: kfree(data); err_logo_close_file: sys_close(fd); return err; }
/***************************************************************************** 函 数 名 : power_on_log_save 功能描述 : 保存开机log 输入参数 : 输出参数 : 无 返 回 值 : 调用函数 : 被调函数 : *****************************************************************************/ static int power_on_log_save( void ) { long pos; unsigned int pf; mm_segment_t old_fs; ssize_t rt = 0; char buf[128] = {0}; struct rtc_time tm; char *power_on_reason[4]; #if (MBB_CHARGE == FEATURE_ON) char *power_on_mode[5]; #else char *power_on_mode[3]; #endif BATT_LEVEL_ENUM battery_level; tm = power_item_info.time; battery_level = chg_get_batt_level(); power_on_reason[0] = "Charger"; power_on_reason[1] = "Power Key"; power_on_reason[2] = "Warm Reset"; power_on_reason[3] = "Unknown"; #if (MBB_CHG_PLATFORM_V7R2 == FEATURE_ON) power_on_mode[0] = "EXCEPTION"; power_on_mode[1] = "NORMAL"; power_on_mode[2] = "PWN CHARGING"; power_on_mode[3] = "UPDATE"; power_on_mode[4] = "INVALID"; #else power_on_mode[0] = "PWN CHARGING"; power_on_mode[1] = "NORMAL"; power_on_mode[2] = "UPDATE"; #endif /* 记录开机信息(时间、次数、关机原因) */ snprintf(buf, sizeof(buf) - 1, "power on reason(E5): %s, power on mode : %s, current battery voltage: %d, current time: %4d-%02d-%02d %02d:%02d:%02d\r\n", \ power_on_reason[power_item_info.reason], power_on_mode[power_item_info.mode], battery_level, tm.tm_year, tm.tm_mon, \ tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); #if ( FEATURE_ON == MBB_MLOG ) mlog_print(MLOG_POWER, mlog_lv_info, "POWERON mode %s\n" ,power_on_mode[power_item_info.mode]); mlog_print(MLOG_POWER, mlog_lv_info, "POWERON due to %s\n" ,power_on_reason[power_item_info.reason]); mlog_set_statis_info("on_times",1); #endif old_fs = get_fs(); //lint !e63 set_fs(KERNEL_DS); /*coverity[check_return] */ pf = (unsigned int)sys_open(EXCH_POWER_LOG_PATH, O_RDWR | O_CREAT, 0666); /*coverity[unchecked_value] */ if(IS_ERR((const void*)pf)) { pr_dbg( "error occured happened when open file %s, exiting.\n", EXCH_POWER_LOG_PATH); return (int)pf; } /*coverity[unchecked_value] */ pos = sys_lseek(pf, 0, SEEK_END); if(pos > EXCH_ONOFF_LOG_MAX){ /* 文件超过 16k,删除重新打开 */ sys_rmdir(EXCH_POWER_LOG_PATH); /*coverity[check_return] */ pf = (unsigned int)sys_open(EXCH_POWER_LOG_PATH, O_RDWR | O_CREAT, 0666); /*coverity[unchecked_value] */ if(IS_ERR((const void*)pf)) { pr_dbg( "error occured happened when open file %s, exiting.\n", EXCH_POWER_LOG_PATH); return (int)pf; } } else{ /*coverity[unchecked_value] */ sys_lseek(pf, pos, SEEK_SET); } /*coverity[unchecked_value] */ rt = sys_write(pf, (const char*)buf, strlen(buf)); if(rt<0) { pr_dbg("error occured happened when write file %s, exiting.\n", EXCH_POWER_LOG_PATH); /*coverity[unchecked_value] */ sys_close(pf); set_fs(old_fs); return (int)rt; } /*coverity[unchecked_value] */ sys_close(pf); set_fs(old_fs); pr_dbg(KERN_DEBUG "power on log save.\n "); return (int)rt; }
int load_565rle_image(char *filename, bool bf_supported) { int fd, err = 0; unsigned count, max; unsigned short *data, *bits, *ptr; struct fb_info *info; #if 0 struct module *owner; #endif info = registered_fb[0]; if (!info) { printk(KERN_WARNING "%s: Can not access framebuffer\n", __func__); return -ENODEV; } #if 0 owner = info->fbops->owner; if (!try_module_get(owner)) return NULL; if (info->fbops->fb_open && info->fbops->fb_open(info, 0)) { module_put(owner); return NULL; } #endif fd = sys_open(filename, O_RDONLY, 0); if (fd < 0) { printk(KERN_WARNING "%s: Can not open %s\n", __func__, filename); return -ENOENT; } printk("%s: open OK! %s\n",__func__, filename); count = (unsigned)sys_lseek(fd, (off_t)0, 2); if (count == 0) { sys_close(fd); err = -EIO; goto err_logo_close_file; } printk("%s: count %d\n",__func__, count); sys_lseek(fd, (off_t)0, 0); data = kmalloc(count, GFP_KERNEL); if (!data) { printk(KERN_WARNING "%s: Can not alloc data\n", __func__); err = -ENOMEM; goto err_logo_close_file; } if ((unsigned)sys_read(fd, (char *)data, count) != count) { err = -EIO; goto err_logo_free_data; } max = fb_width(info) * fb_height(info); ptr = data; bits = (unsigned short *)(info->screen_base); printk("%s: max %d, n %d 0x%x\n",__func__, max, ptr[0], (unsigned int)bits); while (count > 3) { unsigned n = ptr[0]; if (n > max) break; memset16_rgb8888(bits, ptr[1], n << 1); bits += n*2; // for rgb8888 max -= n; ptr += 2; count -= 4; } #if !defined (CONFIG_USA_OPERATOR_ATT) && !defined (CONFIG_JPN_MODEL_SC_03D) && !defined (CONFIG_CAN_OPERATOR_RWC) if (!is_lpcharging_state() && !sec_debug_is_recovery_mode()) s3cfb_start_progress(info); #endif err_logo_free_data: kfree(data); err_logo_close_file: sys_close(fd); return err; }
int smbrun(char *cmd, int *outfd) { pid_t pid; uid_t uid = current_user.uid; gid_t gid = current_user.gid; /* * Lose any kernel oplock capabilities we may have. */ oplock_set_capability(False, False); /* point our stdout at the file we want output to go into */ if (outfd && ((*outfd = setup_out_fd()) == -1)) { return -1; } /* in this method we will exec /bin/sh with the correct arguments, after first setting stdout to point at the file */ /* * We need to temporarily stop CatchChild from eating * SIGCLD signals as it also eats the exit status code. JRA. */ CatchChildLeaveStatus(); if ((pid=sys_fork()) < 0) { DEBUG(0,("smbrun: fork failed with error %s\n", strerror(errno) )); CatchChild(); if (outfd) { close(*outfd); *outfd = -1; } return errno; } if (pid) { /* * Parent. */ int status=0; pid_t wpid; /* the parent just waits for the child to exit */ while((wpid = sys_waitpid(pid,&status,0)) < 0) { if(errno == EINTR) { errno = 0; continue; } break; } CatchChild(); if (wpid != pid) { DEBUG(2,("waitpid(%d) : %s\n",(int)pid,strerror(errno))); if (outfd) { close(*outfd); *outfd = -1; } return -1; } /* Reset the seek pointer. */ if (outfd) { sys_lseek(*outfd, 0, SEEK_SET); } #if defined(WIFEXITED) && defined(WEXITSTATUS) if (WIFEXITED(status)) { return WEXITSTATUS(status); } #endif return status; } CatchChild(); /* we are in the child. we exec /bin/sh to do the work for us. we don't directly exec the command we want because it may be a pipeline or anything else the config file specifies */ /* point our stdout at the file we want output to go into */ if (outfd) { close(1); if (dup2(*outfd,1) != 1) { DEBUG(2,("Failed to create stdout file descriptor\n")); close(*outfd); exit(80); } } /* now completely lose our privileges. This is a fairly paranoid way of doing it, but it does work on all systems that I know of */ become_user_permanently(uid, gid); if (getuid() != uid || geteuid() != uid || getgid() != gid || getegid() != gid) { /* we failed to lose our privileges - do not execute the command */ exit(81); /* we can't print stuff at this stage, instead use exit codes for debugging */ } #ifndef __INSURE__ /* close all other file descriptors, leaving only 0, 1 and 2. 0 and 2 point to /dev/null from the startup code */ { int fd; for (fd=3;fd<256;fd++) close(fd); } #endif execl("/bin/sh","sh","-c",cmd,NULL); /* not reached */ exit(82); return 1; }
/* * Generic syscall handler. * * Returns 0 if syscall number is not handled by this * module, 1 otherwise. This allows applications to * extend the syscall handler by using exception chaining. */ int _bsp_do_syscall(int func, /* syscall function number */ long arg1, long arg2, /* up to four args. */ long arg3, long arg4, int *retval) /* syscall return value */ { int err = 0; switch (func) { case SYS_read: err = sys_read((int)arg1, (char *)arg2, (int)arg3); break; case SYS_write: err = sys_write((int)arg1, (char *)arg2, (int)arg3); break; case SYS_open: err = sys_open((const char *)arg1, (int)arg2, (int)arg3); break; case SYS_close: err = sys_close((int)arg1); break; case SYS_lseek: err = sys_lseek((int)arg1, (int)arg2, (int)arg3); break; case BSP_GET_SHARED: *(bsp_shared_t **)arg1 = bsp_shared_data; break; case SYS_meminfo: { // Return the top and size of memory. struct bsp_mem_info mem; int i; unsigned long u, totmem, topmem, numbanks; i = totmem = topmem = numbanks = 0; while (bsp_sysinfo(BSP_INFO_MEMORY, i++, &mem) == 0) { if (mem.kind == BSP_MEM_RAM) { numbanks++; totmem += mem.nbytes; u = (unsigned long)mem.virt_start + mem.nbytes; if (u > topmem) topmem = u; } } *(unsigned long *)arg1 = totmem; *(unsigned long *)arg2 = topmem; *retval = numbanks; } return 1; break; default: return 0; } *retval = err; return 1; }
/* * System call dispatcher. * * A pointer to the trapframe created during exception entry (in * exception.S) is passed in. * * The calling conventions for syscalls are as follows: Like ordinary * function calls, the first 4 32-bit arguments are passed in the 4 * argument registers a0-a3. 64-bit arguments are passed in *aligned* * pairs of registers, that is, either a0/a1 or a2/a3. This means that * if the first argument is 32-bit and the second is 64-bit, a1 is * unused. * * This much is the same as the calling conventions for ordinary * function calls. In addition, the system call number is passed in * the v0 register. * * On successful return, the return value is passed back in the v0 * register, or v0 and v1 if 64-bit. This is also like an ordinary * function call, and additionally the a3 register is also set to 0 to * indicate success. * * On an error return, the error code is passed back in the v0 * register, and the a3 register is set to 1 to indicate failure. * (Userlevel code takes care of storing the error code in errno and * returning the value -1 from the actual userlevel syscall function. * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.) * * Upon syscall return the program counter stored in the trapframe * must be incremented by one instruction; otherwise the exception * return code will restart the "syscall" instruction and the system * call will repeat forever. * * If you run out of registers (which happens quickly with 64-bit * values) further arguments must be fetched from the user-level * stack, starting at sp+16 to skip over the slots for the * registerized values, with copyin(). */ void syscall(struct trapframe *tf) { int callno; int32_t retval; int err; KASSERT(curthread != NULL); KASSERT(curthread->t_curspl == 0); KASSERT(curthread->t_iplhigh_count == 0); callno = tf->tf_v0; /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; /* note the casts to userptr_t */ switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; case SYS___time: err = sys___time((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); break; /* process calls */ case SYS_fork: err = sys_fork(tf, &retval); break; case SYS_execv: err = sys_execv( (userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); break; case SYS__exit: sys__exit(tf->tf_a0); panic("Returning from exit\n"); case SYS_waitpid: err = sys_waitpid( tf->tf_a0, (userptr_t)tf->tf_a1, tf->tf_a2, &retval); break; case SYS_getpid: err = sys_getpid(&retval); break; /* file calls */ case SYS_open: err = sys_open( (userptr_t)tf->tf_a0, tf->tf_a1, tf->tf_a2, &retval); break; case SYS_dup2: err = sys_dup2( tf->tf_a0, tf->tf_a1, &retval); break; case SYS_close: err = sys_close(tf->tf_a0); break; case SYS_read: err = sys_read( tf->tf_a0, (userptr_t)tf->tf_a1, tf->tf_a2, &retval); break; case SYS_write: err = sys_write( tf->tf_a0, (userptr_t)tf->tf_a1, tf->tf_a2, &retval); break; case SYS_lseek: { /* * Because the position argument is 64 bits wide, * it goes in the a2/a3 registers and we have to * get "whence" from the stack. Furthermore, the * return value is 64 bits wide, so the extra * part of it goes in the v1 register. * * This is a trifle messy. */ uint64_t offset; int whence; off_t retval64; join32to64(tf->tf_a2, tf->tf_a3, &offset); err = copyin((userptr_t)tf->tf_sp + 16, &whence, sizeof(int)); if (err) { break; } err = sys_lseek(tf->tf_a0, offset, whence, &retval64); if (err) { break; } split64to32(retval64, &tf->tf_v0, &tf->tf_v1); retval = tf->tf_v0; } break; case SYS_chdir: err = sys_chdir((userptr_t)tf->tf_a0); break; case SYS___getcwd: err = sys___getcwd( (userptr_t)tf->tf_a0, tf->tf_a1, &retval); break; /* Even more system calls will go here */ default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; } if (err) { /* * Return the error code. This gets converted at * userlevel to a return value of -1 and the error * code in errno. */ tf->tf_v0 = err; tf->tf_a3 = 1; /* signal an error */ } else { /* Success. */ tf->tf_v0 = retval; tf->tf_a3 = 0; /* signal no error */ } /* * Now, advance the program counter, to avoid restarting * the syscall over and over again. */ tf->tf_epc += 4; /* Make sure the syscall code didn't forget to lower spl */ KASSERT(curthread->t_curspl == 0); /* ...or leak any spinlocks */ KASSERT(curthread->t_iplhigh_count == 0); }
void syscall(struct trapframe *tf) { int callno; int32_t retval; int err; KASSERT(curthread != NULL); KASSERT(curthread->t_curspl == 0); KASSERT(curthread->t_iplhigh_count == 0); callno = tf->tf_v0; /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; uint32_t v0, v1; off_t pos; int whence; //userptr_t *status; struct stat statbuf; switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; case SYS___time: err = sys___time((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); /* the syscall ov*/ break; case SYS_open: err = sys_open((const_userptr_t)tf->tf_a0, tf->tf_a1, (mode_t)tf ->tf_a2, &retval); break; case SYS_close: err = sys_close((tf->tf_a0),&retval); break; case SYS_read: err = sys_read(tf->tf_a0, (userptr_t)tf->tf_a1, (size_t)tf -> tf_a2, &retval); //retval = (int32_t)bytes; break; case SYS_write: err = sys_write(tf->tf_a0, (userptr_t)tf->tf_a1, (size_t)tf -> tf_a2, &retval); //retval = (int32_t)bytes; break; case SYS_lseek: pos = tf->tf_a2; pos = pos << 32; pos += tf -> tf_a3; err = copyin((const_userptr_t)tf->tf_sp+16,&whence,sizeof(int)); if(err) { break; } err = sys_lseek(tf->tf_a0, pos, whence, &v0, &v1); if(err) { break; } retval = v0; tf->tf_v1 = v1; break; case SYS__exit: sys__exit(tf->tf_a0); // We are only here because of one of 2 reasons. We tried to kill the initial thread // while there was/were (an) immediate child(ren) of it running. // *NOTE* I'm actually NOT sure if that's a valid reason to be here // Second reason? Something went horribly, horribly wrong err = 0; break; case SYS_dup2: err = sys_dup2(tf->tf_a0,tf->tf_a1,&retval); break; case SYS_fstat: err = sys_fstat(tf->tf_a0, &statbuf); break; case SYS_fork: err = sys_fork(tf, &retval); break; case SYS_getpid: err = sys_getpid(&retval); break; case SYS_waitpid: err = sys_waitpid(tf->tf_a0, (int*)tf->tf_a1, (int)tf->tf_a2, &retval); break; case SYS___getcwd: err = sys___getcwd((char*)tf->tf_a0,(size_t)tf->tf_a1,&retval); break; case SYS_chdir: err = sys_chdir((char*)tf->tf_a0,&retval); break; case SYS_execv: err = sys_execv((const char*)tf->tf_a0, (char**)tf->tf_a1); break; case SYS_sbrk: err = sbrk((int)tf->tf_a0,&retval); break; default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; } if (err) { /* * Return the error code. This gets converted at * userlevel to a return value of -1 and the error * code in errno. */ tf->tf_v0 = err; tf->tf_a3 = 1; /* signal an error */ } else { /* Success. */ tf->tf_v0 = retval; tf->tf_a3 = 0; /* signal no error */ } /* * Now, advance the program counter, to avoid restarting * the syscall over and over again. */ tf->tf_epc += 4; /* Make sure the syscall code didn't forget to lower spl */ KASSERT(curthread->t_curspl == 0); /* ...or leak any spinlocks */ KASSERT(curthread->t_iplhigh_count == 0); }
/* * System call dispatcher. * * A pointer to the trapframe created during exception entry (in * exception-*.S) is passed in. * * The calling conventions for syscalls are as follows: Like ordinary * function calls, the first 4 32-bit arguments are passed in the 4 * argument registers a0-a3. 64-bit arguments are passed in *aligned* * pairs of registers, that is, either a0/a1 or a2/a3. This means that * if the first argument is 32-bit and the second is 64-bit, a1 is * unused. * * This much is the same as the calling conventions for ordinary * function calls. In addition, the system call number is passed in * the v0 register. * * On successful return, the return value is passed back in the v0 * register, or v0 and v1 if 64-bit. This is also like an ordinary * function call, and additionally the a3 register is also set to 0 to * indicate success. * * On an error return, the error code is passed back in the v0 * register, and the a3 register is set to 1 to indicate failure. * (Userlevel code takes care of storing the error code in errno and * returning the value -1 from the actual userlevel syscall function. * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.) * * Upon syscall return the program counter stored in the trapframe * must be incremented by one instruction; otherwise the exception * return code will restart the "syscall" instruction and the system * call will repeat forever. * * If you run out of registers (which happens quickly with 64-bit * values) further arguments must be fetched from the user-level * stack, starting at sp+16 to skip over the slots for the * registerized values, with copyin(). */ void syscall(struct trapframe *tf) { int callno; int32_t retval; int err; KASSERT(curthread != NULL); KASSERT(curthread->t_curspl == 0); KASSERT(curthread->t_iplhigh_count == 0); callno = tf->tf_v0; /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; int whence = 0; off_t position = 0; int32_t retval2 = 0; switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; case SYS___time: err = sys___time((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); break; /* Add stuff here */ case SYS_write: err = sys_write((int)tf->tf_a0,(const void *)tf->tf_a1,(size_t)tf->tf_a2, &retval); break; case SYS_read: err = sys_read(tf->tf_a0, (void *) tf->tf_a1, (size_t) tf->tf_a2, &retval); break; case SYS_open: err = sys_open((char *)tf->tf_a0, tf->tf_a1, (mode_t)tf->tf_a2, &retval); break; case SYS_close: err = sys_close(tf->tf_a0); break; case SYS_dup2: err = sys_dup2(tf->tf_a0, tf->tf_a1, &retval); break; case SYS_lseek: position |= (off_t)tf->tf_a2; position <<= 32; position |= (off_t)tf->tf_a3; err = copyin((const userptr_t)tf->tf_sp+16, &whence, sizeof(whence)); if (err) break; err = sys_lseek((int)tf->tf_a0, position, (int)whence, &retval, &retval2); if(!err) tf->tf_v1 = retval2; break; case SYS_fork: err = sys_fork(tf,&retval); break; case SYS_getpid: err = sys_getpid((pid_t *)&retval); break; case SYS_waitpid: err = sys_waitpid((pid_t)tf->tf_a0, (userptr_t)tf->tf_a1, (int)tf->tf_a2, (pid_t *)&retval); break; case SYS__exit: sys__exit((int)tf->tf_a0); err = -1; //will never come here as it doesnt return break; case SYS_execv: err=sys_execv((const char *)tf->tf_a0,(char **)tf->tf_a1); break; case SYS_sbrk: err=(int)sys_sbrk((intptr_t)tf->tf_a0, (vaddr_t *)&retval); break; default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; } if (err) { /* * Return the error code. This gets converted at * userlevel to a return value of -1 and the error * code in errno. */ tf->tf_v0 = err; tf->tf_a3 = 1; /* signal an error */ } else { /* Success. */ tf->tf_v0 = retval; tf->tf_a3 = 0; /* signal no error */ } /* * Now, advance the program counter, to avoid restarting * the syscall over and over again. */ tf->tf_epc += 4; /* Make sure the syscall code didn't forget to lower spl */ KASSERT(curthread->t_curspl == 0); /* ...or leak any spinlocks */ KASSERT(curthread->t_iplhigh_count == 0); }
/* * System call dispatcher. * * A pointer to the trapframe created during exception entry (in * exception.S) is passed in. * * The calling conventions for syscalls are as follows: Like ordinary * function calls, the first 4 32-bit arguments are passed in the 4 * argument registers a0-a3. 64-bit arguments are passed in *aligned* * pairs of registers, that is, either a0/a1 or a2/a3. This means that * if the first argument is 32-bit and the second is 64-bit, a1 is * unused. * * This much is the same as the calling conventions for ordinary * function calls. In addition, the system call number is passed in * the v0 register. * * On successful return, the return value is passed back in the v0 * register, or v0 and v1 if 64-bit. This is also like an ordinary * function call, and additionally the a3 register is also set to 0 to * indicate success. * * On an error return, the error code is passed back in the v0 * register, and the a3 register is set to 1 to indicate failure. * (Userlevel code takes care of storing the error code in errno and * returning the value -1 from the actual userlevel syscall function. * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.) * * Upon syscall return the program counter stored in the trapframe * must be incremented by one instruction; otherwise the exception * return code will restart the "syscall" instruction and the system * call will repeat forever. * * If you run out of registers (which happens quickly with 64-bit * values) further arguments must be fetched from the user-level * stack, starting at sp+16 to skip over the slots for the * registerized values, with copyin(). */ void syscall(struct trapframe *tf) { int callno; int32_t retval; int err = 0; KASSERT(curthread != NULL); KASSERT(curthread->t_curspl == 0); KASSERT(curthread->t_iplhigh_count == 0); callno = tf->tf_v0; /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; case SYS___time: err = sys___time((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); break; /* Add stuff here */ case SYS_read: err = sys_read((int)tf->tf_a0, // filehandle (void*)tf->tf_a1, // buffer (size_t)tf->tf_a2, // size &retval); // return value break; case SYS_write: err = sys_write((int)tf->tf_a0, // filehandle (const void*)tf->tf_a1, // buffer (size_t)tf->tf_a2, // size &retval); // return value break; case SYS_open: err = sys_open((const char*)tf->tf_a0, // filename (int)tf->tf_a1, // flags &retval); // return value break; case SYS_close: err = sys_close((int)tf->tf_a0); // filehandle break; case SYS_dup2: err = sys_dup2((int)tf->tf_a0, // old_filehandle (int)tf->tf_a1, // new_filehandle &retval); // return value break; case SYS__exit: sys_exit((int)tf->tf_a0); // exitcode break; case SYS_getpid: retval = sys_getpid(); // exitcode break; case SYS_waitpid: err = sys_waitpid((pid_t)tf->tf_a0, (int*)tf->tf_a1, tf->tf_a2, &retval); break; case SYS_fork: err = sys_fork(tf, &retval); break; case SYS_execv: err = sys_execv((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); break; case SYS_sbrk: err = sys_sbrk((intptr_t)tf->tf_a0, &retval); break; case SYS_lseek: { off_t offset = tf->tf_a2; offset = offset<<32; offset = offset|tf->tf_a3; int whence; int err_copyin = copyin((userptr_t)tf->tf_sp+16,&whence,sizeof(whence)); if (err_copyin) { break; } off_t retoffset; err = sys_lseek((int)tf->tf_a0, // filehandle offset, // desired offset whence, &retoffset); // return value if (!err) { retval = retoffset>>32; tf->tf_v1 = retoffset; } break; } break; case SYS___getcwd: err = sys___getcwd((char*)tf->tf_a0, // buffer (size_t)tf->tf_a1, // size &retval); // return value break; case SYS_chdir: err = sys_chdir((char*)tf->tf_a0); // path break; default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; }
int bsp_om_append_file(char *filename, void * address, u32 length, u32 max_size) { int ret = BSP_OK; int fd; int bytes; int len; mm_segment_t old_fs; old_fs = get_fs(); set_fs(KERNEL_DS); ret = om_create_dir(OM_ROOT_PATH); if(BSP_OK != ret) { om_error("<bsp_om_append_file>, create dir failed! ret = %d\n", ret); goto out; } /* open file */ ret = sys_access(filename, 0); if(BSP_OK != ret) { /*create file */ fd = sys_open(filename, O_CREAT|O_RDWR, 0755); if(fd < 0) { om_error("<bsp_om_append_file>, open failed while mode is create, ret = %d\n", fd); goto out; } } else { fd = sys_open(filename, O_APPEND|O_RDWR, 0755); if(fd < 0) { om_error("<bsp_om_append_file>, open failed while mode is append, ret = %d\n", fd); goto out; } } len = sys_lseek(fd, 0, SEEK_END); if(ERROR == len) { om_error("<bsp_om_append_file>, seek failed! ret = %d\n", len); (void)sys_close(fd); goto out; } if (len >= max_size) { sys_close(fd); ret = sys_unlink(filename); if (OK != ret) { om_error("<bsp_om_append_file>, remove failed! ret = %d\n", ret); goto out; } /*重新建立reset文件*/ fd = sys_open(filename, O_CREAT|O_RDWR, 0755); if(fd < 0) { om_error("<bsp_om_append_file>, create failed! ret = %d\n", fd); goto out; } } bytes = sys_write(fd, address, length); if(bytes != length) { om_error("<bsp_om_append_file>, write data failed! ret = %d\n", bytes); ret = BSP_ERROR; (void)sys_close(fd); goto out; } ret = sys_close(fd); if(0 != ret) { om_error("<bsp_om_append_file>, close failed! ret = %d\n", ret); ret = BSP_ERROR; goto out; } ret = BSP_OK; out: set_fs(old_fs); return ret; }
off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin) { /* sign extend n */ return sys_lseek(fd, (int)offset, origin); }
/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ int load_565rle_image(char *filename) { struct fb_info *info; int fd, count, err = 0; unsigned max; unsigned short *data, *ptr; #ifdef CONFIG_LGE_I_DISP_BOOTLOGO char *bits; #else unsigned int *bits; #endif info = registered_fb[0]; if (!info) { printk(KERN_WARNING "%s: Can not access framebuffer\n", __func__); return -ENODEV; } fd = sys_open(filename, O_RDONLY, 0); if (fd < 0) { printk(KERN_WARNING "%s: Can not open %s\n", __func__, filename); return -ENOENT; } count = sys_lseek(fd, (off_t)0, 2); if (count <= 0) { err = -EIO; goto err_logo_close_file; } sys_lseek(fd, (off_t)0, 0); data = kmalloc(count, GFP_KERNEL); if (!data) { printk(KERN_WARNING "%s: Can not alloc data\n", __func__); err = -ENOMEM; goto err_logo_close_file; } if (sys_read(fd, (char *)data, count) != count) { err = -EIO; goto err_logo_free_data; } max = fb_width(info) * fb_height(info); ptr = data; #ifdef CONFIG_LGE_I_DISP_BOOTLOGO bits = (char *)(info->screen_base); #else bits = (unsigned short *)(info->screen_base); #endif while (count > 3) { unsigned n = ptr[0]; if (n > max) break; #ifdef CONFIG_LGE_I_DISP_BOOTLOGO if(info->var.bits_per_pixel/8 == 4){ memset32(bits, ptr[1], n << 1); } else{ memset16(bits, ptr[1], n << 1); } bits += info->var.bits_per_pixel/8*n; #else memset16(bits, ptr[1], n << 1); bits += n; #endif max -= n; ptr += 2; count -= 4; } err_logo_free_data: kfree(data); err_logo_close_file: sys_close(fd); return err; }
/****************************************************************************** * Function: power_off_log_save * Description: save the power off log( reason and battery voltage ). * Input: * None * Output: * None * Return: * None * Note : ********************************************************************************/ LOCAL_1 int power_off_log_save( void ) { long pos; unsigned int pf; mm_segment_t old_fs; struct rtc_time tm; struct timespec ts; int rt; char buf[128]; char *reboot_reason[] = {"NORMAL", "BAD BATTERY", "LOWBATTERY", "OVERTEMP", \ "RM_CHARGER", "UPDATE", "REBOOT", "INVALID"}; BATT_LEVEL_ENUM battery_level = chg_get_batt_level(); DRV_SHUTDOWN_REASON_ENUM rb; getnstimeofday(&ts); rtc_time_to_tm((unsigned long)ts.tv_sec, &tm); power_off_ctrl.time = tm; rb = power_off_ctrl.reason; pr_dbg("%4d-%02d-%02d %02d:%02d:%02d\n",tm.tm_year, tm.tm_mon, \ tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); /* 记录关机信息(时间、次数、关机原因) */ snprintf(buf, sizeof(buf) - 1, "system close reason(E5): %s, current battery voltage: %d, current time: %4d-%02d-%02d %02d:%02d:%02d\n", \ reboot_reason[rb], battery_level, tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); old_fs = get_fs(); //lint !e63 set_fs(KERNEL_DS); /*coverity[check_return] */ pf = (unsigned int)sys_open(EXCH_RESET_LOG_PATH, O_RDWR | O_CREAT, 0666); /*coverity[unchecked_value] */ if(IS_ERR((const void*)pf)) { pr_dbg( "error occured happened when open file %s, exiting.\n", EXCH_RESET_LOG_PATH); return (int)pf; } /*coverity[unchecked_value] */ pos = sys_lseek(pf, 0, SEEK_END); if(pos > EXCH_ONOFF_LOG_MAX){ /* 文件超过 16k,删除重新打开 */ sys_rmdir(EXCH_RESET_LOG_PATH); /*coverity[check_return] */ pf = (unsigned int)sys_open(EXCH_RESET_LOG_PATH, O_RDWR | O_CREAT, 0666); /*coverity[unchecked_value] */ if(IS_ERR((const void*)pf)) { pr_dbg( "error occured happened when open file %s, exiting.\n", EXCH_RESET_LOG_PATH); return (int)pf; } } else{ /*coverity[unchecked_value] */ sys_lseek(pf, pos, SEEK_SET); } /*coverity[unchecked_value] */ rt = sys_write(pf, (const char*)buf, strlen(buf)); if(rt<0) { pr_dbg("error occured happened when write file %s, exiting.\n", EXCH_RESET_LOG_PATH); /*coverity[unchecked_value] */ sys_close( pf ); set_fs(old_fs); return rt; } pr_dbg(KERN_DEBUG "power off log save."); /*coverity[unchecked_value] */ sys_close( pf ); set_fs(old_fs); return rt; }
/* * The main routine to restore task via sigreturn. * This one is very special, we never return there * but use sigreturn facility to restore core registers * and jump execution to some predefined ip read from * core file. */ long __export_restore_task(struct task_restore_args *args) { long ret = -1; int i; VmaEntry *vma_entry; unsigned long va; struct rt_sigframe *rt_sigframe; unsigned long new_sp; k_rtsigset_t to_block; pid_t my_pid = sys_getpid(); rt_sigaction_t act; bootstrap_start = args->bootstrap_start; bootstrap_len = args->bootstrap_len; #ifdef CONFIG_VDSO vdso_rt_size = args->vdso_rt_size; #endif task_entries = args->task_entries; helpers = args->helpers; n_helpers = args->n_helpers; *args->breakpoint = rst_sigreturn; ksigfillset(&act.rt_sa_mask); act.rt_sa_handler = sigchld_handler; act.rt_sa_flags = SA_SIGINFO | SA_RESTORER | SA_RESTART; act.rt_sa_restorer = cr_restore_rt; sys_sigaction(SIGCHLD, &act, NULL, sizeof(k_rtsigset_t)); log_set_fd(args->logfd); log_set_loglevel(args->loglevel); cap_last_cap = args->cap_last_cap; pr_info("Switched to the restorer %d\n", my_pid); #ifdef CONFIG_VDSO if (vdso_do_park(&args->vdso_sym_rt, args->vdso_rt_parked_at, vdso_rt_size)) goto core_restore_end; #endif if (unmap_old_vmas((void *)args->premmapped_addr, args->premmapped_len, bootstrap_start, bootstrap_len)) goto core_restore_end; /* Shift private vma-s to the left */ for (i = 0; i < args->nr_vmas; i++) { vma_entry = args->tgt_vmas + i; if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR)) continue; if (!vma_priv(vma_entry)) continue; if (vma_entry->end >= TASK_SIZE) continue; if (vma_entry->start > vma_entry->shmid) break; if (vma_remap(vma_premmaped_start(vma_entry), vma_entry->start, vma_entry_len(vma_entry))) goto core_restore_end; } /* Shift private vma-s to the right */ for (i = args->nr_vmas - 1; i >= 0; i--) { vma_entry = args->tgt_vmas + i; if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR)) continue; if (!vma_priv(vma_entry)) continue; if (vma_entry->start > TASK_SIZE) continue; if (vma_entry->start < vma_entry->shmid) break; if (vma_remap(vma_premmaped_start(vma_entry), vma_entry->start, vma_entry_len(vma_entry))) goto core_restore_end; } /* * OK, lets try to map new one. */ for (i = 0; i < args->nr_vmas; i++) { vma_entry = args->tgt_vmas + i; if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR)) continue; if (vma_priv(vma_entry)) continue; va = restore_mapping(vma_entry); if (va != vma_entry->start) { pr_err("Can't restore %"PRIx64" mapping with %lx\n", vma_entry->start, va); goto core_restore_end; } } #ifdef CONFIG_VDSO /* * Proxify vDSO. */ for (i = 0; i < args->nr_vmas; i++) { if (vma_entry_is(&args->tgt_vmas[i], VMA_AREA_VDSO) || vma_entry_is(&args->tgt_vmas[i], VMA_AREA_VVAR)) { if (vdso_proxify("dumpee", &args->vdso_sym_rt, args->vdso_rt_parked_at, i, args->tgt_vmas, args->nr_vmas)) goto core_restore_end; break; } } #endif /* * Walk though all VMAs again to drop PROT_WRITE * if it was not there. */ for (i = 0; i < args->nr_vmas; i++) { vma_entry = args->tgt_vmas + i; if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR))) continue; if (vma_entry_is(vma_entry, VMA_ANON_SHARED)) { struct shmem_info *entry; entry = find_shmem(args->shmems, args->nr_shmems, vma_entry->shmid); if (entry && entry->pid == my_pid && entry->start == vma_entry->start) futex_set_and_wake(&entry->lock, 1); } if (vma_entry->prot & PROT_WRITE) continue; sys_mprotect(decode_pointer(vma_entry->start), vma_entry_len(vma_entry), vma_entry->prot); } /* * Finally restore madivse() bits */ for (i = 0; i < args->nr_vmas; i++) { unsigned long m; vma_entry = args->tgt_vmas + i; if (!vma_entry->has_madv || !vma_entry->madv) continue; for (m = 0; m < sizeof(vma_entry->madv) * 8; m++) { if (vma_entry->madv & (1ul << m)) { ret = sys_madvise(vma_entry->start, vma_entry_len(vma_entry), m); if (ret) { pr_err("madvise(%"PRIx64", %"PRIu64", %ld) " "failed with %ld\n", vma_entry->start, vma_entry_len(vma_entry), m, ret); goto core_restore_end; } } } } ret = 0; /* * Tune up the task fields. */ ret |= sys_prctl_safe(PR_SET_NAME, (long)args->comm, 0, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE, (long)args->mm.mm_start_code, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE, (long)args->mm.mm_end_code, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA, (long)args->mm.mm_start_data, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA, (long)args->mm.mm_end_data, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK, (long)args->mm.mm_start_stack, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK, (long)args->mm.mm_start_brk, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK, (long)args->mm.mm_brk, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START, (long)args->mm.mm_arg_start, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (long)args->mm.mm_arg_end, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START, (long)args->mm.mm_env_start, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END, (long)args->mm.mm_env_end, 0); ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV, (long)args->mm_saved_auxv, args->mm_saved_auxv_size); if (ret) goto core_restore_end; /* * Because of requirements applied from kernel side * we need to restore /proc/pid/exe symlink late, * after old existing VMAs are superseded with * new ones from image file. */ ret = restore_self_exe_late(args); if (ret) goto core_restore_end; /* * We need to prepare a valid sigframe here, so * after sigreturn the kernel will pick up the * registers from the frame, set them up and * finally pass execution to the new IP. */ rt_sigframe = (void *)args->t->mem_zone.rt_sigframe; if (restore_thread_common(rt_sigframe, args->t)) goto core_restore_end; /* * Threads restoration. This requires some more comments. This * restorer routine and thread restorer routine has the following * memory map, prepared by a caller code. * * | <-- low addresses high addresses --> | * +-------------------------------------------------------+-----------------------+ * | this proc body | own stack | rt_sigframe space | thread restore zone | * +-------------------------------------------------------+-----------------------+ * * where each thread restore zone is the following * * | <-- low addresses high addresses --> | * +--------------------------------------------------------------------------+ * | thread restore proc | thread1 stack | thread1 rt_sigframe | * +--------------------------------------------------------------------------+ */ if (args->nr_threads > 1) { struct thread_restore_args *thread_args = args->thread_args; long clone_flags = CLONE_VM | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM; long last_pid_len; long parent_tid; int i, fd; fd = args->fd_last_pid; ret = sys_flock(fd, LOCK_EX); if (ret) { pr_err("Can't lock last_pid %d\n", fd); goto core_restore_end; } for (i = 0; i < args->nr_threads; i++) { char last_pid_buf[16], *s; /* skip self */ if (thread_args[i].pid == args->t->pid) continue; new_sp = restorer_stack(thread_args + i); last_pid_len = vprint_num(last_pid_buf, sizeof(last_pid_buf), thread_args[i].pid - 1, &s); sys_lseek(fd, 0, SEEK_SET); ret = sys_write(fd, s, last_pid_len); if (ret < 0) { pr_err("Can't set last_pid %ld/%s\n", ret, last_pid_buf); goto core_restore_end; } /* * To achieve functionality like libc's clone() * we need a pure assembly here, because clone()'ed * thread will run with own stack and we must not * have any additional instructions... oh, dear... */ RUN_CLONE_RESTORE_FN(ret, clone_flags, new_sp, parent_tid, thread_args, args->clone_restore_fn); } ret = sys_flock(fd, LOCK_UN); if (ret) { pr_err("Can't unlock last_pid %ld\n", ret); goto core_restore_end; } } sys_close(args->fd_last_pid); restore_rlims(args); ret = create_posix_timers(args); if (ret < 0) { pr_err("Can't restore posix timers %ld\n", ret); goto core_restore_end; } ret = timerfd_arm(args); if (ret < 0) { pr_err("Can't restore timerfd %ld\n", ret); goto core_restore_end; } pr_info("%ld: Restored\n", sys_getpid()); futex_set(&zombies_inprogress, args->nr_zombies); restore_finish_stage(CR_STATE_RESTORE); futex_wait_while_gt(&zombies_inprogress, 0); if (wait_helpers(args) < 0) goto core_restore_end; ksigfillset(&to_block); ret = sys_sigprocmask(SIG_SETMASK, &to_block, NULL, sizeof(k_rtsigset_t)); if (ret) { pr_err("Unable to block signals %ld", ret); goto core_restore_end; } sys_sigaction(SIGCHLD, &args->sigchld_act, NULL, sizeof(k_rtsigset_t)); ret = restore_signals(args->siginfo, args->siginfo_nr, true); if (ret) goto core_restore_end; ret = restore_signals(args->t->siginfo, args->t->siginfo_nr, false); if (ret) goto core_restore_end; restore_finish_stage(CR_STATE_RESTORE_SIGCHLD); rst_tcp_socks_all(args); /* * Writing to last-pid is CAP_SYS_ADMIN protected, * turning off TCP repair is CAP_SYS_NED_ADMIN protected, * thus restore* creds _after_ all of the above. */ ret = restore_creds(&args->creds); ret = ret || restore_dumpable_flag(&args->mm); ret = ret || restore_pdeath_sig(args->t); futex_set_and_wake(&thread_inprogress, args->nr_threads); restore_finish_stage(CR_STATE_RESTORE_CREDS); if (ret) BUG(); /* Wait until children stop to use args->task_entries */ futex_wait_while_gt(&thread_inprogress, 1); log_set_fd(-1); /* * The code that prepared the itimers makes shure the * code below doesn't fail due to bad timing values. */ #define itimer_armed(args, i) \ (args->itimers[i].it_interval.tv_sec || \ args->itimers[i].it_interval.tv_usec) if (itimer_armed(args, 0)) sys_setitimer(ITIMER_REAL, &args->itimers[0], NULL); if (itimer_armed(args, 1)) sys_setitimer(ITIMER_VIRTUAL, &args->itimers[1], NULL); if (itimer_armed(args, 2)) sys_setitimer(ITIMER_PROF, &args->itimers[2], NULL); restore_posix_timers(args); sys_munmap(args->rst_mem, args->rst_mem_size); /* * Sigframe stack. */ new_sp = (long)rt_sigframe + SIGFRAME_OFFSET; /* * Prepare the stack and call for sigreturn, * pure assembly since we don't need any additional * code insns from gcc. */ rst_sigreturn(new_sp); core_restore_end: futex_abort_and_wake(&task_entries->nr_in_progress); pr_err("Restorer fail %ld\n", sys_getpid()); sys_exit_group(1); return -1; }
int cloudabi_sys_fd_seek(struct thread *td, struct cloudabi_sys_fd_seek_args *uap) { struct lseek_args lseek_args = { .fd = uap->fd, .offset = uap->offset }; switch (uap->whence) { case CLOUDABI_WHENCE_CUR: lseek_args.whence = SEEK_CUR; break; case CLOUDABI_WHENCE_END: lseek_args.whence = SEEK_END; break; case CLOUDABI_WHENCE_SET: lseek_args.whence = SEEK_SET; break; default: return (EINVAL); } return (sys_lseek(td, &lseek_args)); } /* Converts a file descriptor to a CloudABI file descriptor type. */ cloudabi_filetype_t cloudabi_convert_filetype(const struct file *fp) { struct socket *so; struct vnode *vp; switch (fp->f_type) { case DTYPE_FIFO: return (CLOUDABI_FILETYPE_FIFO); case DTYPE_KQUEUE: return (CLOUDABI_FILETYPE_POLL); case DTYPE_PIPE: return (CLOUDABI_FILETYPE_FIFO); case DTYPE_PROCDESC: return (CLOUDABI_FILETYPE_PROCESS); case DTYPE_SHM: return (CLOUDABI_FILETYPE_SHARED_MEMORY); case DTYPE_SOCKET: so = fp->f_data; switch (so->so_type) { case SOCK_DGRAM: return (CLOUDABI_FILETYPE_SOCKET_DGRAM); case SOCK_SEQPACKET: return (CLOUDABI_FILETYPE_SOCKET_SEQPACKET); case SOCK_STREAM: return (CLOUDABI_FILETYPE_SOCKET_STREAM); default: return (CLOUDABI_FILETYPE_UNKNOWN); } case DTYPE_VNODE: vp = fp->f_vnode; switch (vp->v_type) { case VBLK: return (CLOUDABI_FILETYPE_BLOCK_DEVICE); case VCHR: return (CLOUDABI_FILETYPE_CHARACTER_DEVICE); case VDIR: return (CLOUDABI_FILETYPE_DIRECTORY); case VFIFO: return (CLOUDABI_FILETYPE_FIFO); case VLNK: return (CLOUDABI_FILETYPE_SYMBOLIC_LINK); case VREG: return (CLOUDABI_FILETYPE_REGULAR_FILE); case VSOCK: return (CLOUDABI_FILETYPE_SOCKET_STREAM); default: return (CLOUDABI_FILETYPE_UNKNOWN); } default: return (CLOUDABI_FILETYPE_UNKNOWN); } } /* Removes rights that conflict with the file descriptor type. */ void cloudabi_remove_conflicting_rights(cloudabi_filetype_t filetype, cloudabi_rights_t *base, cloudabi_rights_t *inheriting) { /* * CloudABI has a small number of additional rights bits to * disambiguate between multiple purposes. Remove the bits that * don't apply to the type of the file descriptor. * * As file descriptor access modes (O_ACCMODE) has been fully * replaced by rights bits, CloudABI distinguishes between * rights that apply to the file descriptor itself (base) versus * rights of new file descriptors derived from them * (inheriting). The code below approximates the pair by * decomposing depending on the file descriptor type. * * We need to be somewhat accurate about which actions can * actually be performed on the file descriptor, as functions * like fcntl(fd, F_GETFL) are emulated on top of this. */ switch (filetype) { case CLOUDABI_FILETYPE_DIRECTORY: *base &= CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS | CLOUDABI_RIGHT_FD_SYNC | CLOUDABI_RIGHT_FILE_ADVISE | CLOUDABI_RIGHT_FILE_CREATE_DIRECTORY | CLOUDABI_RIGHT_FILE_CREATE_FILE | CLOUDABI_RIGHT_FILE_CREATE_FIFO | CLOUDABI_RIGHT_FILE_LINK_SOURCE | CLOUDABI_RIGHT_FILE_LINK_TARGET | CLOUDABI_RIGHT_FILE_OPEN | CLOUDABI_RIGHT_FILE_READDIR | CLOUDABI_RIGHT_FILE_READLINK | CLOUDABI_RIGHT_FILE_RENAME_SOURCE | CLOUDABI_RIGHT_FILE_RENAME_TARGET | CLOUDABI_RIGHT_FILE_STAT_FGET | CLOUDABI_RIGHT_FILE_STAT_FPUT_TIMES | CLOUDABI_RIGHT_FILE_STAT_GET | CLOUDABI_RIGHT_FILE_STAT_PUT_TIMES | CLOUDABI_RIGHT_FILE_SYMLINK | CLOUDABI_RIGHT_FILE_UNLINK | CLOUDABI_RIGHT_POLL_FD_READWRITE | CLOUDABI_RIGHT_SOCK_BIND_DIRECTORY | CLOUDABI_RIGHT_SOCK_CONNECT_DIRECTORY; *inheriting &= CLOUDABI_RIGHT_FD_DATASYNC | CLOUDABI_RIGHT_FD_READ | CLOUDABI_RIGHT_FD_SEEK | CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS | CLOUDABI_RIGHT_FD_SYNC | CLOUDABI_RIGHT_FD_TELL | CLOUDABI_RIGHT_FD_WRITE | CLOUDABI_RIGHT_FILE_ADVISE | CLOUDABI_RIGHT_FILE_ALLOCATE | CLOUDABI_RIGHT_FILE_CREATE_DIRECTORY | CLOUDABI_RIGHT_FILE_CREATE_FILE | CLOUDABI_RIGHT_FILE_CREATE_FIFO | CLOUDABI_RIGHT_FILE_LINK_SOURCE | CLOUDABI_RIGHT_FILE_LINK_TARGET | CLOUDABI_RIGHT_FILE_OPEN | CLOUDABI_RIGHT_FILE_READDIR | CLOUDABI_RIGHT_FILE_READLINK | CLOUDABI_RIGHT_FILE_RENAME_SOURCE | CLOUDABI_RIGHT_FILE_RENAME_TARGET | CLOUDABI_RIGHT_FILE_STAT_FGET | CLOUDABI_RIGHT_FILE_STAT_FPUT_SIZE | CLOUDABI_RIGHT_FILE_STAT_FPUT_TIMES | CLOUDABI_RIGHT_FILE_STAT_GET | CLOUDABI_RIGHT_FILE_STAT_PUT_TIMES | CLOUDABI_RIGHT_FILE_SYMLINK | CLOUDABI_RIGHT_FILE_UNLINK | CLOUDABI_RIGHT_MEM_MAP | CLOUDABI_RIGHT_MEM_MAP_EXEC | CLOUDABI_RIGHT_POLL_FD_READWRITE | CLOUDABI_RIGHT_PROC_EXEC | CLOUDABI_RIGHT_SOCK_BIND_DIRECTORY | CLOUDABI_RIGHT_SOCK_CONNECT_DIRECTORY; break; case CLOUDABI_FILETYPE_FIFO: *base &= CLOUDABI_RIGHT_FD_READ | CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS | CLOUDABI_RIGHT_FD_WRITE | CLOUDABI_RIGHT_FILE_STAT_FGET | CLOUDABI_RIGHT_POLL_FD_READWRITE; *inheriting = 0; break; case CLOUDABI_FILETYPE_POLL: *base &= ~CLOUDABI_RIGHT_FILE_ADVISE; *inheriting = 0; break; case CLOUDABI_FILETYPE_PROCESS: *base &= ~(CLOUDABI_RIGHT_FILE_ADVISE | CLOUDABI_RIGHT_POLL_FD_READWRITE); *inheriting = 0; break; case CLOUDABI_FILETYPE_REGULAR_FILE: *base &= CLOUDABI_RIGHT_FD_DATASYNC | CLOUDABI_RIGHT_FD_READ | CLOUDABI_RIGHT_FD_SEEK | CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS | CLOUDABI_RIGHT_FD_SYNC | CLOUDABI_RIGHT_FD_TELL | CLOUDABI_RIGHT_FD_WRITE | CLOUDABI_RIGHT_FILE_ADVISE | CLOUDABI_RIGHT_FILE_ALLOCATE | CLOUDABI_RIGHT_FILE_STAT_FGET | CLOUDABI_RIGHT_FILE_STAT_FPUT_SIZE | CLOUDABI_RIGHT_FILE_STAT_FPUT_TIMES | CLOUDABI_RIGHT_MEM_MAP | CLOUDABI_RIGHT_MEM_MAP_EXEC | CLOUDABI_RIGHT_POLL_FD_READWRITE | CLOUDABI_RIGHT_PROC_EXEC; *inheriting = 0; break; case CLOUDABI_FILETYPE_SHARED_MEMORY: *base &= ~(CLOUDABI_RIGHT_FD_SEEK | CLOUDABI_RIGHT_FD_TELL | CLOUDABI_RIGHT_FILE_ADVISE | CLOUDABI_RIGHT_FILE_ALLOCATE | CLOUDABI_RIGHT_FILE_READDIR); *inheriting = 0; break; case CLOUDABI_FILETYPE_SOCKET_DGRAM: case CLOUDABI_FILETYPE_SOCKET_SEQPACKET: case CLOUDABI_FILETYPE_SOCKET_STREAM: *base &= CLOUDABI_RIGHT_FD_READ | CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS | CLOUDABI_RIGHT_FD_WRITE | CLOUDABI_RIGHT_FILE_STAT_FGET | CLOUDABI_RIGHT_POLL_FD_READWRITE | CLOUDABI_RIGHT_SOCK_ACCEPT | CLOUDABI_RIGHT_SOCK_BIND_SOCKET | CLOUDABI_RIGHT_SOCK_CONNECT_SOCKET | CLOUDABI_RIGHT_SOCK_LISTEN | CLOUDABI_RIGHT_SOCK_SHUTDOWN | CLOUDABI_RIGHT_SOCK_STAT_GET; break; default: *inheriting = 0; break; } } /* Converts FreeBSD's Capsicum rights to CloudABI's set of rights. */ static void convert_capabilities(const cap_rights_t *capabilities, cloudabi_filetype_t filetype, cloudabi_rights_t *base, cloudabi_rights_t *inheriting) { cloudabi_rights_t rights; /* Convert FreeBSD bits to CloudABI bits. */ rights = 0; #define MAPPING(cloudabi, ...) do { \ if (cap_rights_is_set(capabilities, ##__VA_ARGS__)) \ rights |= (cloudabi); \ } while (0); RIGHTS_MAPPINGS #undef MAPPING *base = rights; *inheriting = rights; cloudabi_remove_conflicting_rights(filetype, base, inheriting); }
// // Generic syscall handler. // // Returns 0 if syscall number is not handled by this // module, 1 otherwise. This allows applications to // extend the syscall handler by using exception chaining. // CYG_ADDRWORD __do_syscall(CYG_ADDRWORD func, // syscall function number CYG_ADDRWORD arg1, CYG_ADDRWORD arg2, // up to four args. CYG_ADDRWORD arg3, CYG_ADDRWORD arg4, CYG_ADDRWORD *retval, CYG_ADDRWORD *sig) // syscall return value { int err = 0; *sig = 0; switch (func) { case SYS_open: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_open( const char *name, int flags, int mode, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_open((const char *)arg1, (int)arg2, (int)arg3, (int *)sig); else #endif err = sys_open((const char *)arg1, (int)arg2, (int)arg3); break; } case SYS_read: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_read( int fd, void *buf, size_t count, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_read((int)arg1, (void *)arg2, (size_t)arg3, (int *)sig); else #endif err = sys_read((int)arg1, (char *)arg2, (int)arg3); break; } case SYS_write: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_write( int fd, const void *buf, size_t count, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_write((int)arg1, (const void *)arg2, (size_t)arg3, (int *)sig); else #endif err = sys_write((int)arg1, (char *)arg2, (int)arg3); break; } case SYS_close: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_close( int fd, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_close((int)arg1, (int *)sig); else #endif err = sys_close((int)arg1); break; } case SYS_lseek: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_lseek( int fd, long offset, int whence, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_lseek((int)arg1, (long)arg2, (int)arg3, (int *)sig); else #endif err = sys_lseek((int)arg1, (int)arg2, (int)arg3); break; } case SYS_stat: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_stat( const char *pathname, void *statbuf, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_stat((const char *)arg1, (void *)arg2, (int *)sig); else #endif err = -NEWLIB_ENOSYS; break; } case SYS_fstat: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_fstat( int fd, void *statbuf, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_fstat((int)arg1, (void *)arg2, (int *)sig); else #endif { struct newlib_stat *st = (struct newlib_stat *)arg2; st->st_mode = NEWLIB_S_IFCHR; st->st_blksize = 4096; err = 0; } break; } case SYS_rename: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_rename( const char *oldpath, const char *newpath, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_rename((const char *)arg1, (const char *)arg2, (int *)sig); else #endif err = -NEWLIB_ENOSYS; break; } case SYS_unlink: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_unlink( const char *pathname, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_unlink((const char *)arg1, (int *)sig); else #endif err = -NEWLIB_ENOSYS; break; } case SYS_isatty: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_isatty( int fd, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_isatty((int)arg1, (int *)sig); else #endif err = 1; break; } case SYS_system: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_system( const char *command, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_system((const char *)arg1, (int *)sig); else #endif err = -1; break; } case SYS_gettimeofday: { #ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol __externC int cyg_hal_gdbfileio_gettimeofday( void *tv, void *tz, int *sig ); if (gdb_active) err = cyg_hal_gdbfileio_gettimeofday((void *)arg1, (void *)arg2, (int *)sig); else #endif err = 0; break; } case SYS_utime: // FIXME. Some libglosses depend on this behavior. err = sys_times((unsigned long *)arg1); break; case SYS_times: err = sys_times((unsigned long *)arg1); break; case SYS_meminfo: err = 1; *(unsigned long *)arg1 = (unsigned long)(ram_end-ram_start); *(unsigned long *)arg2 = (unsigned long)ram_end; break; #ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF case SYS_timer_call_back: sys_profile_call_back( (char *)arg1, (char **)arg2 ); break; case SYS_timer_frequency: sys_profile_frequency( (int)arg1, (unsigned int *)arg2 ); break; case SYS_timer_reset: sys_profile_reset(); break; #endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF case __GET_SHARED: *(__shared_t **)arg1 = &__shared_data; break; case SYS_exit: *sig = -1; // signal exit err = arg1; if (gdb_active) { #ifdef CYGOPT_REDBOOT_BSP_SYSCALLS_EXIT_WITHOUT_TRAP __send_exit_status((int)arg1); #else *sig = SIGTRAP; err = func; #endif // CYGOPT_REDBOOT_BSP_SYSCALLS_EXIT_WITHOUT_TRAP } break; default: return 0; } *retval = err; return 1; }
// unbounded_channels <= 0 means no, > 0 means yes // -1 means advance. void check_channel(char threadsafe, qio_chtype_t type, int64_t start, int64_t len, int64_t chunksz, qio_hint_t file_hints, qio_hint_t ch_hints, char unbounded_channels, char reopen) { qio_file_t* f; qio_channel_t* writing; qio_channel_t* reading; int64_t offset; int64_t usesz; int64_t end = start + len; int err; unsigned char* chunk; unsigned char* got_chunk; int64_t k; ssize_t amt_written; ssize_t amt_read; char* chhints; char* fhints; FILE* writefp = NULL; FILE* readfp = NULL; int memory; int64_t ch_end = end; char filename[128]; int fd = -1; strcpy(filename,"/tmp/qio_testXXXXXX"); if( unbounded_channels > 0 ) ch_end = INT64_MAX; ch_hints = (ch_hints & ~ QIO_CHTYPEMASK) | type; memory = 0; if( (file_hints & QIO_METHODMASK) == QIO_METHOD_MEMORY || (ch_hints & QIO_METHODMASK) == QIO_METHOD_MEMORY ) { memory = 1; } if( memory ) { file_hints = (file_hints & ~ QIO_METHODMASK ) | QIO_METHOD_MEMORY; ch_hints = (ch_hints & ~ QIO_METHODMASK ) | QIO_METHOD_MEMORY; } if( memory && type == QIO_CH_ALWAYS_UNBUFFERED ) return; if( memory && reopen ) return; if( (ch_hints & QIO_METHODMASK) == QIO_METHOD_FREADFWRITE ) { if( (file_hints & QIO_METHODMASK) != QIO_METHOD_FREADFWRITE ) return; } if( (ch_hints & QIO_METHODMASK) == QIO_METHOD_MMAP ) { if( (file_hints & QIO_METHODMASK) != QIO_METHOD_MMAP ) return; } fhints = qio_hints_to_string(file_hints); chhints = qio_hints_to_string(ch_hints); printf("check_channel(threadsafe=%i, type=%i, start=%lli, len=%lli, chunksz=%lli, file_hints=%s, ch_hints=%s, unbounded=%i, reopen=%i)\n", (int) threadsafe, (int) type, (long long int) start, (long long int) len, (long long int) chunksz, fhints, chhints, (int) unbounded_channels, (int) reopen ); free(fhints); free(chhints); chunk = malloc(chunksz); got_chunk = malloc(chunksz); assert(chunk); assert(got_chunk); if( memory ) { err = qio_file_open_mem_ext(&f, NULL, QIO_FDFLAG_READABLE|QIO_FDFLAG_WRITEABLE|QIO_FDFLAG_SEEKABLE, file_hints, NULL); assert(!err); } else { // Open a temporary file. if( reopen ) { fd = mkstemp(filename); close(fd); err = qio_file_open_access(&f, filename, "w", file_hints, NULL); assert(!err); } else { err = qio_file_open_tmp(&f, file_hints, NULL); assert(!err); } // Rewind the file if (f->fp ) { int got; got = fseek(f->fp, start, SEEK_SET); assert( got == 0 ); } else { off_t off; err = sys_lseek(f->fd, start, SEEK_SET, &off); assert(!err); } } // Create a "write to file" channel. err = qio_channel_create(&writing, f, ch_hints, 0, 1, start, ch_end, NULL); assert(!err); // Write stuff to the file. for( offset = start; offset < end; offset += usesz ) { usesz = chunksz; if( offset + usesz > end ) usesz = end - offset; // Fill chunk. fill_testdata(offset, usesz, chunk); // Write chunk. if( writefp ) { amt_written = fwrite(chunk, 1, usesz, writefp); } else { err = qio_channel_write(threadsafe, writing, chunk, usesz, &amt_written); assert(!err); } assert(amt_written == usesz); } // Attempt to write 1 more byte; we should get EEOF // if we've restricted the range of the channel. // Write chunk. if( unbounded_channels > 0) { // do nothing } else { if( writefp ) { int got; got = fflush(writefp); assert(got == 0); amt_written = fwrite(chunk, 1, 1, writefp); // fwrite might buffer on its own. if( amt_written != 0 ) { got = fflush(writefp); assert(got == EOF); } assert(errno == EEOF); } else { if( unbounded_channels < 0 ) { int times = -unbounded_channels; for( int z = 0; z < times; z++ ) { err = qio_channel_advance(threadsafe, writing, 1); assert( !err ); } } err = qio_channel_write(threadsafe, writing, chunk, 1, &amt_written); assert(amt_written == 0); assert( err == EEOF ); } } qio_channel_release(writing); // Reopen the file if we're doing reopen if( reopen ) { // Close the file. qio_file_release(f); err = qio_file_open_access(&f, filename, "r", file_hints, NULL); assert(!err); } // Check that the file is the right length. if( !memory ) { struct stat stats; err = sys_fstat(f->fd, &stats); assert(!err); assert(stats.st_size == end); } // That was fun. Now start at the beginning of the file // and read the data. // Rewind the file if( !memory ) { off_t off; sys_lseek(f->fd, start, SEEK_SET, &off); assert(!err); } // Read the data. //err = qio_channel_init_file(&reading, type, f, ch_hints, 1, 0, start, end); err = qio_channel_create(&reading, f, ch_hints, 1, 0, start, ch_end, NULL); assert(!err); // Read stuff from the file. for( offset = start; offset < end; offset += usesz ) { usesz = chunksz; if( offset + usesz > end ) usesz = end - offset; // Fill chunk. fill_testdata(offset, usesz, chunk); memset(got_chunk, 0xff, usesz); // Read chunk. if( readfp ) { amt_read = fread(got_chunk, 1, usesz, readfp); } else { err = qio_channel_read(threadsafe, reading, got_chunk, usesz, &amt_read); assert( err == EEOF || err == 0); } assert(amt_read == usesz); // Compare chunk. for( k = 0; k < usesz; k++ ) { assert(got_chunk[k] == chunk[k]); } } if( readfp ) { amt_read = fread(got_chunk, 1, 1, readfp); assert( amt_read == 0 ); assert( feof(readfp) ); } else { if( unbounded_channels < 0 ) { int times = -unbounded_channels; for( int z = 0; z < times; z++ ) { err = qio_channel_advance(threadsafe, reading, 1); assert( !err ); } err = qio_channel_advance(threadsafe, reading, -unbounded_channels); assert( !err ); } err = qio_channel_read(threadsafe, reading, got_chunk, 1, &amt_read); assert( err == EEOF ); } qio_channel_release(reading); //err = qio_channel_destroy(&reading); // Close the file. qio_file_release(f); if( reopen ) { unlink(filename); } free(chunk); free(got_chunk); }
/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ int load_565rle_image(char *filename) { struct fb_info *info; int fd, err = 0; unsigned count, max, width, stride, line_pos = 0; unsigned short *data, *ptr; unsigned char *bits; info = registered_fb[0]; if (!info) { printk(KERN_WARNING "%s: Can not access framebuffer\n", __func__); return -ENODEV; } if (!info->screen_base) { printk(KERN_WARNING "Framebuffer memory not allocated\n"); return -ENOMEM; } fd = sys_open(filename, O_RDONLY, 0); if (fd < 0) { printk(KERN_WARNING "%s: Can not open %s\n", __func__, filename); return -ENOENT; } count = sys_lseek(fd, (off_t)0, 2); if (count <= 0) { err = -EIO; goto err_logo_close_file; } sys_lseek(fd, (off_t)0, 0); data = kmalloc(count, GFP_KERNEL); if (!data) { printk(KERN_WARNING "%s: Can not alloc data\n", __func__); err = -ENOMEM; goto err_logo_close_file; } if (sys_read(fd, (char *)data, count) != count) { err = -EIO; goto err_logo_free_data; } width = fb_width(info); stride = fb_linewidth(info); max = width * fb_height(info); ptr = data; bits = (unsigned char *)(info->screen_base); while (count > 3) { int n = ptr[0]; if (n > max) break; max -= n; while (n > 0) { unsigned int j = (line_pos + n > width ? width-line_pos : n); if (fb_depth(info) == 2) memset16(bits, ptr[1], j << 1); else { unsigned int widepixel = ptr[1]; /* * Format is RGBA, but fb is big * endian so we should make widepixel * as ABGR. */ widepixel = /* red : f800 -> 000000f8 */ (widepixel & 0xf800) >> 8 | /* green : 07e0 -> 0000fc00 */ (widepixel & 0x07e0) << 5 | /* blue : 001f -> 00f80000 */ (widepixel & 0x001f) << 19; memset32(bits, widepixel, j << 2); } bits += j * fb_depth(info); line_pos += j; n -= j; if (line_pos == width) { bits += (stride-width) * fb_depth(info); line_pos = 0; } } ptr += 2; count -= 4; } err_logo_free_data: kfree(data); err_logo_close_file: sys_close(fd); return err; }
asmlinkage int sys32_lseek(unsigned int fd, int offset, unsigned int origin) { return sys_lseek(fd, offset, origin); }
static void ListerThread(struct ListerParams *args) { int found_parent = 0; pid_t clone_pid = sys_gettid(), ppid = sys_getppid(); char proc_self_task[80], marker_name[48], *marker_path; const char *proc_paths[3]; const char *const *proc_path = proc_paths; int proc = -1, marker = -1, num_threads = 0; int max_threads = 0, sig; struct kernel_stat marker_sb, proc_sb; stack_t altstack; /* Create "marker" that we can use to detect threads sharing the same * address space and the same file handles. By setting the FD_CLOEXEC flag * we minimize the risk of misidentifying child processes as threads; * and since there is still a race condition, we will filter those out * later, anyway. */ if ((marker = sys_socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0 || sys_fcntl(marker, F_SETFD, FD_CLOEXEC) < 0) { failure: args->result = -1; args->err = errno; if (marker >= 0) NO_INTR(sys_close(marker)); sig_marker = marker = -1; if (proc >= 0) NO_INTR(sys_close(proc)); sig_proc = proc = -1; sys__exit(1); } /* Compute search paths for finding thread directories in /proc */ local_itoa(strrchr(strcpy(proc_self_task, "/proc/"), '\000'), ppid); strcpy(marker_name, proc_self_task); marker_path = marker_name + strlen(marker_name); strcat(proc_self_task, "/task/"); proc_paths[0] = proc_self_task; /* /proc/$$/task/ */ proc_paths[1] = "/proc/"; /* /proc/ */ proc_paths[2] = NULL; /* Compute path for marker socket in /proc */ local_itoa(strcpy(marker_path, "/fd/") + 4, marker); if (sys_stat(marker_name, &marker_sb) < 0) { goto failure; } /* Catch signals on an alternate pre-allocated stack. This way, we can * safely execute the signal handler even if we ran out of memory. */ memset(&altstack, 0, sizeof(altstack)); altstack.ss_sp = args->altstack_mem; altstack.ss_flags = 0; altstack.ss_size = ALT_STACKSIZE; sys_sigaltstack(&altstack, (const stack_t *)NULL); /* Some kernels forget to wake up traced processes, when the * tracer dies. So, intercept synchronous signals and make sure * that we wake up our tracees before dying. It is the caller's * responsibility to ensure that asynchronous signals do not * interfere with this function. */ sig_marker = marker; sig_proc = -1; for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) { struct kernel_sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction_ = SignalHandler; sys_sigfillset(&sa.sa_mask); sa.sa_flags = SA_ONSTACK|SA_SIGINFO|SA_RESETHAND; sys_sigaction(sync_signals[sig], &sa, (struct kernel_sigaction *)NULL); } /* Read process directories in /proc/... */ for (;;) { /* Some kernels know about threads, and hide them in "/proc" * (although they are still there, if you know the process * id). Threads are moved into a separate "task" directory. We * check there first, and then fall back on the older naming * convention if necessary. */ if ((sig_proc = proc = c_open(*proc_path, O_RDONLY|O_DIRECTORY, 0)) < 0) { if (*++proc_path != NULL) continue; goto failure; } if (sys_fstat(proc, &proc_sb) < 0) goto failure; /* Since we are suspending threads, we cannot call any libc * functions that might acquire locks. Most notably, we cannot * call malloc(). So, we have to allocate memory on the stack, * instead. Since we do not know how much memory we need, we * make a best guess. And if we guessed incorrectly we retry on * a second iteration (by jumping to "detach_threads"). * * Unless the number of threads is increasing very rapidly, we * should never need to do so, though, as our guestimate is very * conservative. */ if (max_threads < proc_sb.st_nlink + 100) max_threads = proc_sb.st_nlink + 100; /* scope */ { pid_t pids[max_threads]; int added_entries = 0; sig_num_threads = num_threads; sig_pids = pids; for (;;) { struct kernel_dirent *entry; char buf[4096]; ssize_t nbytes = sys_getdents(proc, (struct kernel_dirent *)buf, sizeof(buf)); if (nbytes < 0) goto failure; else if (nbytes == 0) { if (added_entries) { /* Need to keep iterating over "/proc" in multiple * passes until we no longer find any more threads. This * algorithm eventually completes, when all threads have * been suspended. */ added_entries = 0; sys_lseek(proc, 0, SEEK_SET); continue; } break; } for (entry = (struct kernel_dirent *)buf; entry < (struct kernel_dirent *)&buf[nbytes]; entry = (struct kernel_dirent *)((char *)entry+entry->d_reclen)) { if (entry->d_ino != 0) { const char *ptr = entry->d_name; pid_t pid; /* Some kernels hide threads by preceding the pid with a '.' */ if (*ptr == '.') ptr++; /* If the directory is not numeric, it cannot be a * process/thread */ if (*ptr < '0' || *ptr > '9') continue; pid = local_atoi(ptr); /* Attach (and suspend) all threads */ if (pid && pid != clone_pid) { struct kernel_stat tmp_sb; char fname[entry->d_reclen + 48]; strcat(strcat(strcpy(fname, "/proc/"), entry->d_name), marker_path); /* Check if the marker is identical to the one we created */ if (sys_stat(fname, &tmp_sb) >= 0 && marker_sb.st_ino == tmp_sb.st_ino) { long i, j; /* Found one of our threads, make sure it is no duplicate */ for (i = 0; i < num_threads; i++) { /* Linear search is slow, but should not matter much for * the typically small number of threads. */ if (pids[i] == pid) { /* Found a duplicate; most likely on second pass */ goto next_entry; } } /* Check whether data structure needs growing */ if (num_threads >= max_threads) { /* Back to square one, this time with more memory */ NO_INTR(sys_close(proc)); goto detach_threads; } /* Attaching to thread suspends it */ pids[num_threads++] = pid; sig_num_threads = num_threads; if (sys_ptrace(PTRACE_ATTACH, pid, (void *)0, (void *)0) < 0) { /* If operation failed, ignore thread. Maybe it * just died? There might also be a race * condition with a concurrent core dumper or * with a debugger. In that case, we will just * make a best effort, rather than failing * entirely. */ num_threads--; sig_num_threads = num_threads; goto next_entry; } while (sys_waitpid(pid, (int *)0, __WALL) < 0) { if (errno != EINTR) { sys_ptrace_detach(pid); num_threads--; sig_num_threads = num_threads; goto next_entry; } } if (sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i++ != j || sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i != j) { /* Address spaces are distinct, even though both * processes show the "marker". This is probably * a forked child process rather than a thread. */ sys_ptrace_detach(pid); num_threads--; sig_num_threads = num_threads; } else { found_parent |= pid == ppid; added_entries++; } } } } next_entry:; } } NO_INTR(sys_close(proc)); sig_proc = proc = -1; /* If we failed to find any threads, try looking somewhere else in * /proc. Maybe, threads are reported differently on this system. */ if (num_threads > 1 || !*++proc_path) { NO_INTR(sys_close(marker)); sig_marker = marker = -1; /* If we never found the parent process, something is very wrong. * Most likely, we are running in debugger. Any attempt to operate * on the threads would be very incomplete. Let's just report an * error to the caller. */ if (!found_parent) { ResumeAllProcessThreads(num_threads, pids); sys__exit(3); } /* Now we are ready to call the callback, * which takes care of resuming the threads for us. */ args->result = args->callback(args->parameter, num_threads, pids, args->ap); args->err = errno; /* Callback should have resumed threads, but better safe than sorry */ if (ResumeAllProcessThreads(num_threads, pids)) { /* Callback forgot to resume at least one thread, report error */ args->err = EINVAL; args->result = -1; } sys__exit(0); } detach_threads: /* Resume all threads prior to retrying the operation */ ResumeAllProcessThreads(num_threads, pids); sig_pids = NULL; num_threads = 0; sig_num_threads = num_threads; max_threads += 100; } } }
/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ int load_565rle_image(char *filename) { struct fb_info *info; int fd, err = 0; unsigned count, max; unsigned short *data, *bits, *ptr; printk(KERN_WARNING "~~ %s: %s\n",__func__, filename); info = registered_fb[0]; if (!info) { printk(KERN_WARNING "%s: Can not access framebuffer\n", __func__); return -ENODEV; } fd = sys_open(filename, O_RDONLY, 0); if (fd < 0) { printk(KERN_WARNING "%s: Can not open %s\n", __func__, filename); return -ENOENT; } count = (unsigned)sys_lseek(fd, (off_t)0, 2); if (count == 0) { sys_close(fd); err = -EIO; goto err_logo_close_file; } sys_lseek(fd, (off_t)0, 0); data = kmalloc(count, GFP_KERNEL); if (!data) { printk(KERN_WARNING "%s: Can not alloc data\n", __func__); err = -ENOMEM; goto err_logo_close_file; } if ((unsigned)sys_read(fd, (char *)data, count) != count) { err = -EIO; goto err_logo_free_data; } max = fb_width(info) * fb_height(info); ptr = data; bits = (unsigned short *)(info->screen_base); while (count > 3) { unsigned n = ptr[0]; if (n > max) break; memset16(bits, ptr[1], n << 1); bits += n; max -= n; ptr += 2; count -= 4; } err_logo_free_data: kfree(data); err_logo_close_file: sys_close(fd); printk(KERN_WARNING "~~ %s: %s err:%d end \n",__func__, filename, err); return err; }
int external_memory_test(void) { int return_value = 0; char *src = NULL, *dest = NULL; off_t fd_offset; int fd = -1; mm_segment_t old_fs; int ret; old_fs = get_fs(); set_fs(KERNEL_DS); fd = sys_open((const char __user *) "/sdcard/SDTest.txt", O_CREAT | O_RDWR, 0); set_fs(old_fs); if ( fd < 0 ) { printk(KERN_ERR "[ATCMD_EMT] Can not access SD card\n"); return return_value; } src = kmalloc(10, GFP_KERNEL); if (NULL == src) { printk(KERN_ERR "[ATCMD_EMT] memory allocation is failed\n"); goto file_fail; } sprintf(src,"TEST"); old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_write(fd, (const char __user *) src, 5); set_fs(old_fs); if(ret < 0) { printk(KERN_ERR "[ATCMD_EMT] Can not write SD card \n"); goto file_fail; } fd_offset = sys_lseek(fd, 0, 0); dest = kmalloc(10, GFP_KERNEL); if (NULL == dest) { printk(KERN_ERR "[ATCMD_EMT] memory allocation is failed\n"); goto file_fail; } old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_read(fd, (char __user *) dest, 5); set_fs(old_fs); if(ret < 0) { printk(KERN_ERR "[ATCMD_EMT]Can not read SD card \n"); goto file_fail; } if ((memcmp(src, dest, 4)) == 0) return_value = 1; else return_value = 0; file_fail: if (fd > 0) { sys_close(fd); sys_unlink((const char __user *)"/sdcard/SDTest.txt"); } if (src) kfree(src); if (dest) kfree(dest); return return_value; }
/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ static int load_565rle_image(char *filename) { struct fb_info *info; int fd, err = 0; unsigned max, width, stride, line_pos = 0; unsigned short *data, *ptr; unsigned char *bits; signed count; info = registered_fb[0]; if (!info) { printk(KERN_ERR "%s: Can not access framebuffer\n", __func__); return -ENODEV; } fd = sys_open(filename, O_RDONLY, 0); if (fd < 0) { printk(KERN_ERR "%s: Can not open %s\n", __func__, filename); return -ENOENT; } count = sys_lseek(fd, (off_t)0, 2); if (count <= 0) { err = -EIO; printk(KERN_ERR "%s: sys_lseek failed %s\n", __func__, filename); goto err_logo_close_file; } sys_lseek(fd, (off_t)0, 0); data = kmalloc(count, GFP_KERNEL); if (!data) { printk(KERN_ERR "%s: Can not alloc data\n", __func__); err = -ENOMEM; goto err_logo_close_file; } if (sys_read(fd, (char *)data, count) != count) { err = -EIO; printk(KERN_ERR "%s: sys_read failed %s\n", __func__, filename); goto err_logo_free_data; } width = fb_width(info); stride = fb_linewidth(info); max = width * fb_height(info); ptr = data; bits = (unsigned char *)(info->screen_base); while (count > 3) { int n = ptr[0]; if (n > max) break; max -= n; while (n > 0) { unsigned int j = (line_pos+n > width ? width-line_pos : n); if (fb_depth(info) == 2) { memset16(bits, ptr[1], j << 1); } else { /* Should probably add check for framebuffer * format here*/ unsigned int widepixel = ptr[1]; widepixel = (widepixel & 0xf800) << (19-11) | (widepixel & 0x07e0) << (10-5) | (widepixel & 0x001f) << (3-0) | 0xff000000; /* Set alpha channel*/ memset32(bits, widepixel, j << 2); } bits += j * fb_depth(info); line_pos += j; n -= j; if (line_pos == width) { bits += (stride-width) * fb_depth(info); line_pos = 0; } } ptr += 2; count -= 4; } err_logo_free_data: kfree(data); err_logo_close_file: sys_close(fd); return err; }
/** * SPB & FAR * System call dispatcher. * * A pointer to the trapframe created during exception entry (in * exception.S) is passed in. * * The calling conventions for syscalls are as follows: Like ordinary * function calls, the first 4 32-bit arguments are passed in the 4 * argument registers a0-a3. 64-bit arguments are passed in *aligned* * pairs of registers, that is, either a0/a1 or a2/a3. This means that * if the first argument is 32-bit and the second is 64-bit, a1 is * unused. * * This much is the same as the calling conventions for ordinary * function calls. In addition, the system call number is passed in * the v0 register. * * On successful return, the return value is passed back in the v0 * register, or v0 and v1 if 64-bit. This is also like an ordinary * function call, and additionally the a3 register is also set to 0 to * indicate success. * * On an error return, the error code is passed back in the v0 * register, and the a3 register is set to 1 to indicate failure. * (Userlevel code takes care of storing the error code in errno and * returning the value -1 from the actual userlevel syscall function. * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.) * * Upon syscall return the program counter stored in the trapframe * must be incremented by one instruction; otherwise the exception * return code will restart the "syscall" instruction and the system * call will repeat forever. * * If you run out of registers (which happens quickly with 64-bit * values) further arguments must be fetched from the user-level * stack, starting at sp+16 to skip over the slots for the * registerized values, with copyin(). */ void syscall(struct trapframe *tf) { int callno, err; int32_t retval; off_t pos = 0; off_t lsret; int whence; KASSERT(curthread != NULL); KASSERT(curthread->t_curspl == 0); KASSERT(curthread->t_iplhigh_count == 0); callno = tf->tf_v0; /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; case SYS___time: err = sys___time((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); break; case SYS_open: err = sys_open((const char*)tf->tf_a0, tf->tf_a1, &retval); break; case SYS_read: err = sys_read((int)tf->tf_a0,(void*)tf->tf_a1,(size_t)tf->tf_a2,&retval); break; case SYS_write: err = sys_write((int)tf->tf_a0,(const void*)tf->tf_a1,(size_t)tf->tf_a2,&retval); break; case SYS_close: err = sys_close((int)tf->tf_a0, &retval); break; case SYS_lseek: pos |= (off_t)tf->tf_a2; pos <<= 32; //puts a2 and a3 into one var. pos |= (off_t)tf->tf_a3; err = copyin((const userptr_t)tf->tf_sp+16, &whence, sizeof(whence)); if (err) break; err = sys_lseek((int)tf->tf_a0, pos, (int)whence, &lsret); if(!err){ retval = lsret>>32; tf->tf_v1 = lsret; } break; case SYS_dup2: err = sys_dup2((int)tf->tf_a0 , (int)tf->tf_a1, &retval); break; case SYS_chdir: err = sys_chdir((const char*)tf->tf_a0); break; case SYS___getcwd: err = sys___getcwd((char*)tf->tf_a0, (size_t)tf->tf_a1, &retval); break; case SYS_fork: err = sys_fork(tf, &retval); break; case SYS_getpid: err = sys_getpid(&retval); break; case SYS__exit: err = sys__exit((int)tf->tf_a0, &retval); break; case SYS_waitpid: err = sys_waitpid((int) tf->tf_a0, (int*) tf->tf_a1, tf->tf_a2, &retval); break; case SYS_execv: err = sys_execv((const char*) tf->tf_a0, (char**) tf->tf_a1, &retval); break; default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; }
/* 888RLE image format: [count(2 bytes), rle(3 bytes)] */ int load_565rle_image(char *filename) { struct fb_info *info; int fd, count, err = 0; unsigned max; unsigned char *data, *ptr; unsigned int *bits; unsigned int pixel; info = registered_fb[0]; if (!info) { printk(KERN_WARNING "%s: Can not access framebuffer\n", __func__); return -ENODEV; } fd = sys_open(filename, O_RDONLY, 0); if (fd < 0) { printk(KERN_WARNING "%s: Can not open %s\n", __func__, filename); return -ENOENT; } count = sys_lseek(fd, (off_t)0, 2); if (count <= 0) { err = -EIO; goto err_logo_close_file; } sys_lseek(fd, (off_t)0, 0); data = kmalloc(count, GFP_KERNEL); if (!data) { printk(KERN_WARNING "%s: Can not alloc data\n", __func__); err = -ENOMEM; goto err_logo_close_file; } if (sys_read(fd, (char *)data, count) != count) { err = -EIO; goto err_logo_free_data; } max = fb_width(info) * fb_height(info); ptr = data; bits = (unsigned int *)(info->screen_base); while (count > 4) { unsigned n = ptr[0] | ptr[1] << 8; if (n > max) break; pixel = (0xff<<24)|(ptr[4]<<16)|(ptr[3]<<8)|ptr[2]; memset32(bits, pixel, n << 1); bits += n; max -= n; ptr += 5; count -= 5; } err_logo_free_data: kfree(data); err_logo_close_file: sys_close(fd); return err; }
} void creat_lseek_read_write_open_close_file_test(void) { int count = 0; char buff_in[100] = "Hello world!\nI'm writing a small OS.\nThanks."; char buff_out[100] = {0}; char filename[50] = {0}; unsigned short oldfs; /* 已创建了内核默认的最多磁盘存储文件数,则停止 */ while((++count) < NR_D_INODE) { _k_printf("This is the content will be written: \n%s\n\n", buff_in); sprintf(filename, "/hello--%d.txt", count); _k_printf("%s\n", filename); /* 创建文件并写入 */ oldfs = set_fs_kernel(); FILEDESC desc = sys_creat(filename, FILE_FILE | FILE_RW); set_fs(oldfs); if(-1 == desc) { k_printf("creat_lseek_...: Create file failed!"); return; } d_printf("Create file return.\n"); if(-1 == sys_lseek(desc, 995920, SEEK_SET)) { k_printf("creat_lseek_...: Lseek file failed!"); return; } d_printf("Lseek file return.\n"); oldfs = set_fs_kernel(); if(-1 == sys_write(desc, buff_in, 1 + strlen(buff_in))) { set_fs(oldfs); k_printf("creat_lseek_...: Write file failed!"); return; } set_fs(oldfs); d_printf("Write file return.\n"); if(-1 == sys_close(desc)) { k_printf("creat_lseek_...: Close file failed!"); return; } d_printf("Close file return.\n"); /* 打印根目录含有的文件 */ print_dir("/"); /* 打开之前创建的文件,读取 */ oldfs = set_fs_kernel(); if(-1 == (desc = sys_open(filename, O_RW))) { set_fs(oldfs); k_printf("creat_lseek_...: Open file failed!"); return; } set_fs(oldfs); d_printf("Open file return.\n"); if(-1 == sys_lseek(desc, 995920, SEEK_SET)) { k_printf("creat_lseek_...: Lseek file failed!"); return; } d_printf("Lseek file return.\n"); oldfs = set_fs_kernel(); if(-1 == sys_read(desc, buff_out, 1 + strlen(buff_in))) { set_fs(oldfs); k_printf("creat_lseek_...: Read file failed!"); return; } set_fs(oldfs); d_printf("Read file return.\n"); if(-1 == sys_close(desc)) { k_printf("creat_lseek_...: Close file failed!"); return; } d_printf("Close file return.\n"); _k_printf("This is the content of READ file: \n%s\n\n", buff_out);