void do_no_page(void *addr) { pde_t *page_dir = (pde_t *)current->cr3; pte_t *page_tbl = 0; unsigned long page = alloc_one_page(0); assert(page != 0); int npde = get_npd(addr); int npte = get_npt(addr); if(page_dir[npde] == 0) { page_tbl = (pte_t *) alloc_one_page(0); assert(page_tbl != 0); memset((void *) page_tbl, 0, PAGE_SIZE); page_dir[npde] = va2pa(page_tbl) | PAGE_P | PAGE_WR | PAGE_US; } page_tbl = (pte_t *)pa2va(PAGE_ALIGN(page_dir[npde])); page_tbl[npte] = va2pa(page) | PAGE_P | PAGE_WR | PAGE_US; load_cr3(current); }
long sys_lstat(const char* name, void* st) { struct frontend_stat buf; size_t name_size = strlen(name)+1; long ret = frontend_syscall(SYS_lstat, va2pa(name), name_size, va2pa(&buf), 0, 0, 0, 0); copy_stat(st, &buf); return ret; }
int ofmem_posix_memalign( void **memptr, size_t alignment, size_t size ) { ofmem_t *ofmem = ofmem_arch_get_private(); alloc_desc_t *d, **pp; void *ret; ucell top; phys_addr_t pa; if( !size ) return ENOMEM; if( !ofmem->next_malloc ) ofmem->next_malloc = (char*)ofmem_arch_get_malloc_base(); size = align_size(size + sizeof(alloc_desc_t), alignment); /* look in the freelist */ for( pp=&ofmem->mfree; *pp && (**pp).size < size; pp = &(**pp).next ) { } /* waste at most 4K by taking an entry from the freelist */ if( *pp && (**pp).size > size + 0x1000 ) { /* Alignment should be on physical not virtual address */ pa = va2pa((uintptr_t)*pp + sizeof(alloc_desc_t)); pa = align_ptr(pa, alignment); ret = (void *)pa2va(pa); memset( ret, 0, (**pp).size - sizeof(alloc_desc_t) ); *pp = (**pp).next; *memptr = ret; return 0; } top = ofmem_arch_get_heap_top(); /* Alignment should be on physical not virtual address */ pa = va2pa((uintptr_t)ofmem->next_malloc + sizeof(alloc_desc_t)); pa = align_ptr(pa, alignment); ret = (void *)pa2va(pa); if( pointer2cell(ret) + size > top ) { printk("out of malloc memory (%x)!\n", size ); return ENOMEM; } d = (alloc_desc_t*)((uintptr_t)ret - sizeof(alloc_desc_t)); ofmem->next_malloc += size; d->next = NULL; d->size = size; memset( ret, 0, size - sizeof(alloc_desc_t) ); *memptr = ret; return 0; }
int sys_renameat(int old_fd, const char *old_path, int new_fd, const char *new_path) { int old_kfd = at_kfd(old_fd); int new_kfd = at_kfd(new_fd); if(old_kfd != -1 && new_kfd != -1) { size_t old_size = strlen(old_path)+1; size_t new_size = strlen(new_path)+1; return frontend_syscall(SYS_renameat, old_kfd, va2pa(old_path), old_size, new_kfd, va2pa(new_path), new_size, 0); } return -EBADF; }
long sys_fstatat(int dirfd, const char* name, void* st, int flags) { int kfd = at_kfd(dirfd); if (kfd != -1) { struct frontend_stat buf; size_t name_size = strlen(name)+1; long ret = frontend_syscall(SYS_fstatat, kfd, va2pa(name), name_size, va2pa(&buf), flags, 0, 0); copy_stat(st, &buf); return ret; } return -EBADF; }
long sys_linkat(int old_dirfd, const char* old_name, int new_dirfd, const char* new_name, int flags) { int old_kfd = at_kfd(old_dirfd); int new_kfd = at_kfd(new_dirfd); if (old_kfd != -1 && new_kfd != -1) { size_t old_size = strlen(old_name)+1; size_t new_size = strlen(new_name)+1; return frontend_syscall(SYS_linkat, old_kfd, va2pa(old_name), old_size, new_kfd, va2pa(new_name), new_size, flags); } return -EBADF; }
long sys_unlinkat(int dirfd, const char* name, int flags) { int kfd = at_kfd(dirfd); if (kfd != -1) { size_t name_size = strlen(name)+1; return frontend_syscall(SYS_unlinkat, kfd, va2pa(name), name_size, flags, 0, 0, 0); } return -EBADF; }
/* * Initialize IOMMU * This looks like initialization of CPU MMU but * the routine is higher in food chain. */ static struct iommu_regs * iommu_init(struct iommu *t, uint64_t base) { unsigned int *ptab; int ptsize; #ifdef CONFIG_DEBUG_IOMMU unsigned int impl, vers; #endif unsigned int tmp; struct iommu_regs *regs; int ret; unsigned long vasize; regs = (struct iommu_regs *)ofmem_map_io(base, IOMMU_REGS); if (regs == NULL) { DPRINTF("Cannot map IOMMU\n"); for (;;) { } } t->regs = regs; #ifdef CONFIG_DEBUG_IOMMU impl = (regs->control & IOMMU_CTRL_IMPL) >> 28; vers = (regs->control & IOMMU_CTRL_VERS) >> 24; #endif tmp = regs->control; tmp &= ~(IOMMU_CTRL_RNGE); tmp |= (IOMMU_RNGE_32MB | IOMMU_CTRL_ENAB); t->plow = 0xfe000000; /* End - 32 MB */ /* Size of VA region that we manage */ vasize = 0x2000000; /* 32 MB */ regs->control = tmp; iommu_invalidate(regs); /* Allocate IOMMU page table */ /* Tremendous alignment causes great waste... */ ptsize = (vasize / PAGE_SIZE) * sizeof(int); ret = ofmem_posix_memalign((void *)&ptab, ptsize, ptsize); if (ret != 0) { DPRINTF("Cannot allocate IOMMU table [0x%x]\n", ptsize); for (;;) { } } t->page_table = ptab; /* flush_cache_all(); */ /** flush_tlb_all(); **/ tmp = (unsigned int)va2pa((unsigned long)ptab); regs->base = tmp >> 4; iommu_invalidate(regs); DPRINTF("IOMMU: impl %d vers %d page table at 0x%p (pa 0x%x) of size %d bytes\n", impl, vers, t->page_table, tmp, ptsize); mem_init(&cdvmem, (char*)t->plow, (char *)0xfffff000); return regs; }
long sys_mkdirat(int dirfd, const char* name, int mode) { int kfd = at_kfd(dirfd); if (kfd != -1) { size_t name_size = strlen(name)+1; return frontend_syscall(SYS_mkdirat, kfd, va2pa(name), name_size, mode, 0, 0, 0); } return -EBADF; }
//--------------------------------------------------------------------------------------------------*/ // 文件系统主循环任务 void task_fs(void * pdata) { MSG msg; FS_MSG* p_fs_msg; pdata = pdata; int src; init_fs(); while(1) { //--------------------------------------------------------------------------------------------------*/ // assert(recv(ANY,&msg) == 0); assert( msg.type == FS_MSG_UNION ); src = msg.sender; p_fs_msg = &msg.msg_union.fs_msg; switch(p_fs_msg->para) { case FS_OPEN: p_fs_msg->fd = fs_open(p_fs_msg->pathname,p_fs_msg->flags,task_table + msg.sender); break; case FS_WRITE: p_fs_msg->count = fs_write(p_fs_msg->fd,p_fs_msg->buf,p_fs_msg->offset,p_fs_msg->count,task_table + msg.sender); break; case FS_READ: p_fs_msg->count = fs_read(p_fs_msg->fd,p_fs_msg->buf,p_fs_msg->offset,p_fs_msg->count,task_table + msg.sender); break; case FS_CLOSE: p_fs_msg->para = fs_close(p_fs_msg->fd,task_table + msg.sender); break; case FS_DEL: p_fs_msg->para = fs_delete(va2pa((task_table + msg.sender)->pdb,p_fs_msg->pathname),p_fs_msg->flags); break; case FS_RESUME: src = p_fs_msg->flags; // 待解除阻塞的进程ID(利用了flags这个成员返回PID) assert(0 <= src && src < NR_TOTAL); break; // p_fs_msg->count:-1 请求失败(有其他进程正在请求输入),其他值表示输入字节数 case FS_FORK: p_fs_msg->para = fs_do_fork(p_fs_msg->flags); break; case FS_EXIT: fs_do_exit(p_fs_msg->flags); break; case FS_LSEEK: p_fs_msg->para = fs_do_lseek(p_fs_msg->fd,p_fs_msg->offset,p_fs_msg->flags,task_table + msg.sender); break; default: break; } if(no_answer == 1) no_answer = 0; // 解除下一个tty请求的阻塞 else send(src,&msg); //--------------------------------------------------------------------------------------------------*/ } }
static void kni_allocate_mbufs(struct rte_kni *kni) { int i, ret; struct rte_mbuf *pkts[MAX_MBUF_BURST_NUM]; void *phys[MAX_MBUF_BURST_NUM]; RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, pool) != offsetof(struct rte_kni_mbuf, pool)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, buf_addr) != offsetof(struct rte_kni_mbuf, buf_addr)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, next) != offsetof(struct rte_kni_mbuf, next)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, data_off) != offsetof(struct rte_kni_mbuf, data_off)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, data_len) != offsetof(struct rte_kni_mbuf, data_len)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, pkt_len) != offsetof(struct rte_kni_mbuf, pkt_len)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, ol_flags) != offsetof(struct rte_kni_mbuf, ol_flags)); /* Check if pktmbuf pool has been configured */ if (kni->pktmbuf_pool == NULL) { RTE_LOG(ERR, KNI, "No valid mempool for allocating mbufs\n"); return; } for (i = 0; i < MAX_MBUF_BURST_NUM; i++) { pkts[i] = rte_pktmbuf_alloc(kni->pktmbuf_pool); if (unlikely(pkts[i] == NULL)) { /* Out of memory */ RTE_LOG(ERR, KNI, "Out of memory\n"); break; } phys[i] = va2pa(pkts[i]); } /* No pkt mbuf alocated */ if (i <= 0) return; ret = kni_fifo_put(kni->alloc_q, phys, i); /* Check if any mbufs not put into alloc_q, and then free them */ if (ret >= 0 && ret < i && ret < MAX_MBUF_BURST_NUM) { int j; for (j = ret; j < i; j++) rte_pktmbuf_free(pkts[j]); } }
static size_t parse_args(arg_buf* args) { long r = frontend_syscall(SYS_getmainvars, va2pa(args), sizeof(*args), 0, 0, 0, 0, 0); kassert(r == 0); uint64_t* pk_argv = &args->buf[1]; // pk_argv[0] is the proxy kernel itself. skip it and any flags. size_t pk_argc = args->buf[0], arg = 1; for ( ; arg < pk_argc && *(char*)(uintptr_t)pk_argv[arg] == '-'; arg++) handle_option((const char*)(uintptr_t)pk_argv[arg]); for (size_t i = 0; arg + i < pk_argc; i++) args->argv[i] = (char*)(uintptr_t)pk_argv[arg + i]; return pk_argc - arg; }
unsigned rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num) { void *phy_mbufs[num]; unsigned int ret; unsigned int i; for (i = 0; i < num; i++) phy_mbufs[i] = va2pa(mbufs[i]); ret = kni_fifo_put(kni->rx_q, phy_mbufs, num); /* Get mbufs from free_q and then free them */ kni_free_mbufs(kni); return ret; }
/* * XXX This is a problematic interface. We alloc _memory_ which is uncached. * So if we ever reuse allocations somebody is going to get uncached pages. * Returned address is always aligned by page. * BTW, we were not going to give away anonymous storage, were we not? */ void * dvma_alloc(int size, unsigned int *pphys) { void *va; unsigned int pa, ba; unsigned int npages; unsigned int mva, mpa; unsigned int i; unsigned int *iopte; struct iommu *t = &ciommu; int ret; npages = (size + (PAGE_SIZE-1)) / PAGE_SIZE; ret = ofmem_posix_memalign(&va, npages * PAGE_SIZE, PAGE_SIZE); if (ret != 0) return NULL; ba = (unsigned int)mem_alloc(&cdvmem, npages * PAGE_SIZE, PAGE_SIZE); if (ba == 0) return NULL; pa = (unsigned int)va2pa((unsigned long)va); /* * Change page attributes in MMU to uncached. */ mva = (unsigned int) va; mpa = (unsigned int) pa; ofmem_arch_map_pages(mpa, mva, npages * PAGE_SIZE, ofmem_arch_io_translation_mode(mpa)); /* * Map into IOMMU page table. */ mpa = (unsigned int) pa; iopte = &t->page_table[(ba - t->plow) / PAGE_SIZE]; for (i = 0; i < npages; i++) { *iopte++ = MKIOPTE(mpa); mpa += PAGE_SIZE; } *pphys = ba; return va; }
void * mem_alloc(struct mem *t, int size, int align) { char *p; unsigned long pa; // The alignment restrictions refer to physical, not virtual // addresses pa = va2pa((unsigned long)t->curp) + (align - 1); pa &= ~(align - 1); p = (char *)pa2va(pa); if ((unsigned long)p >= (unsigned long)t->uplim || (unsigned long)p + size > (unsigned long)t->uplim) return NULL; t->curp = p + size; return p; }
/* 函数功能:读文件 输入参数:进程指针 p_tcb 文件fd fd 读缓冲 buf 读大小 count 字节 输出参数:对于普通文件,输出实际读取字节数。 对于字符设备:0 请求成功,-1 请求失败(有其他进程正在请求输入) */ int fs_read(int fd,void * buf,int offset,int count,TCB* p_tcb) { File_Desc* p_fd; Inode* p_inode; buf = va2pa(p_tcb->pdb,buf); p_fd = p_tcb->filp[fd]; p_inode = p_fd->fd_inode; //---------------------------------------------------------- // 字符设备文件 if(p_inode->i_mode == I_MODE_CHAR) { MSG msg; msg.type = TTY_MSG_UNION; msg.msg_union.tty_msg.para = DEV_READ; msg.msg_union.tty_msg.sub_device = MINOR(p_inode->i_start_sect); msg.msg_union.tty_msg.req_caller = TASK_FS_PID; msg.msg_union.tty_msg.req_PID = p_tcb - task_table; msg.msg_union.tty_msg.req_buf = buf; msg.msg_union.tty_msg.req_count = count; disable_int(); if(tty_has_msg_tmp == 0) { if(sendrecv(SEND,dd_map[MAJAR(p_inode->i_start_sect)],&msg) == 0) { no_answer = 1; // 通知主循环将用户进程挂起 enable_int(); return 0; // 0 消息发送成功 } // 请求是否成功在这里还不能判断,需要在主循环中收到tty发来的消息才知道 } enable_int(); return -1; // -1 发送消息失败(可能构成死锁) } //---------------------------------------------------------- // 以下是普通文件 int cnt = file_buff_read( buf, p_fd->fd_inode, offset + p_fd->fd_pos, count); assert(cnt != -1); p_fd->fd_pos += offset + cnt; return cnt; }
ssize_t ia64_copyout(vm_offset_t va, void *dst, size_t len) { void *pa; ssize_t res; size_t sz; res = 0; while (len > 0) { sz = len; pa = va2pa(va, &sz); if (sz == 0) break; bcopy(pa, dst, sz); len -= sz; res += sz; va += sz; } return (res); }
ssize_t ia64_copyin(const void *src, vm_offset_t va, size_t len) { void *pa; ssize_t res; size_t sz; res = 0; while (len > 0) { sz = len; pa = va2pa(va, &sz); if (sz == 0) break; bcopy(src, pa, sz); len -= sz; res += sz; va += sz; } return (res); }
void do_wp_page(void *addr) { //printk("%s addr %08x current %08x\n", __func__, (unsigned long)addr, current); if((unsigned long) addr >= PAGE_OFFSET) { panic("%s invalid addr", __func__); } int npde = get_npd(addr); int npte = get_npt(addr); pde_t *page_dir = (pde_t *)current->cr3; pte_t *page_tbl = pa2va(PAGE_ALIGN(page_dir[npde])); unsigned long wp_pa_addr = PAGE_ALIGN(page_tbl[npte]); page_t *page = pa2page(wp_pa_addr); if(page->count > 0) { page->count --; unsigned long flags = PAGE_FLAGS(page_tbl[npte]); unsigned long wp_va_addr = (unsigned long) pa2va(wp_pa_addr); unsigned long newtbl = alloc_one_page(0); assert(newtbl != 0); memcpy((void *)newtbl, (void *)wp_va_addr, PAGE_SIZE); page_tbl[npte] = va2pa(newtbl) | flags; } page_tbl[npte] |= PAGE_WR; #if 0 page_tbl[npte] |= PAGE_US; page_dir[npde] |= PAGE_WR; page_dir[npde] |= PAGE_US; #endif load_cr3(current); }
ssize_t ia64_readin(int fd, vm_offset_t va, size_t len) { void *pa; ssize_t res, s; size_t sz; res = 0; while (len > 0) { sz = len; pa = va2pa(va, &sz); if (sz == 0) break; s = read(fd, pa, sz); if (s <= 0) break; len -= s; res += s; va += s; } return (res); }
/* 函数功能:写文件 输入参数:进程指针 p_tcb 文件fd fd 写缓冲 buf 写大小 count 字节 输出参数:成功返回实际写入字节数,失败返回-1 */ int fs_write(int fd,void * buf,int offset,int count,TCB* p_tcb) { File_Desc* p_fd; Inode* p_inode; buf = va2pa(p_tcb->pdb,buf); p_fd = p_tcb->filp[fd]; p_inode = p_fd->fd_inode; //---------------------------------------------------------- // 字符设备文件 if(p_inode->i_mode == I_MODE_CHAR) { MSG msg; msg.type = TTY_MSG_UNION; msg.msg_union.tty_msg.para = DEV_WRITE; msg.msg_union.tty_msg.sub_device = MINOR(p_inode->i_start_sect); msg.msg_union.tty_msg.req_buf = buf; msg.msg_union.tty_msg.req_count = count; disable_int(); if(tty_has_msg_tmp == 0) { if(sendrecv(BOTH,dd_map[MAJAR(p_inode->i_start_sect)],&msg) == -1) msg.msg_union.tty_msg.req_count = -1; enable_int(); return msg.msg_union.tty_msg.req_count; } enable_int(); return -1; } //---------------------------------------------------------- // 以下是普通文件 int cnt = file_buff_write( buf, p_fd->fd_inode, offset + p_fd->fd_pos, count); assert(cnt != -1); p_fd->fd_pos += offset + cnt; return cnt; }
/* * sys_disk_request * * Disk I/O without going through the buffer cache. * * xn_user is the name of a pxn that grants access to the disk * reqbp is a list of scatter/gather requests * k is which capability in the env should be checked * * permission is granted to perform the operation if: * 1) the blocks in reqbp are covered by the pxn * 2) the capability gives access to the pxn * */ int sys_disk_request (u_int sn, struct Xn_name *xn_user, struct buf *reqbp, u_int k) { struct Xn_name xn; struct Xn_xtnt xtnt; struct Pxn *pxn; cap c; int ret; int access; struct disk *di; int *resptr = NULL; u_int bcount = 0; struct buf *bp, *segbp, *nsegbp; int noncontigs = 0, nctemp; #ifdef MEASURE_DISK_TIMES disk_pctr_start = rdtsc(); #endif /* XXX - use PFM or copyin instead of isreadable_* */ /* bypass for direct scsi commands */ if (reqbp->b_flags & B_SCSICMD) { return sys_disk_scsicmd (sn, k, reqbp); } /* get the capability */ if ((ret = env_getcap (curenv, k, &c)) < 0) return ret; /* and the pxn */ copyin (xn_user, &xn, sizeof (xn)); if (! (pxn = lookup_pxn (&xn))) { warn ("sys_disk_request: no pxn found"); return (-E_NOT_FOUND); } /* XXX - do we need to check that this is a physical disk? */ /* get a refernce to the disk unit for this command */ di = &(si->si_disks[xn.xa_dev]); /* Iterate over the request list checking: -- if the request is transfering data to/from memory that this user can read/write. -- if the pxn and capability specified give access to these blocks */ for (segbp = reqbp; ; segbp = (struct buf *) segbp->b_sgnext) { if (! (isreadable_varange ((u_int)segbp, sizeof(struct buf)))) { warn ("sys_disk_request: bad reqbp (%p)", segbp); return (-E_FAULT); } if (segbp->b_flags & B_READ) { access = ACL_R; } else { access = ACL_W; } xtnt.xtnt_block = segbp->b_blkno; xtnt.xtnt_size = segbp->b_bcount / di->d_bsize; bcount += segbp->b_bcount; if (! pxn_authorizes_xtnt (pxn, &c, &xtnt, access, &ret)) { warn ("sys_disk_request: pxn/cap does not grant access to block(s)"); return ret; } if (! ((reqbp->b_flags & B_READ) ? iswriteable_varange : isreadable_varange) ((u_int) segbp->b_memaddr, segbp->b_bcount)) { warn ("sys_disk_request: bad b_memaddr: %p (b_bcount %d)", segbp->b_memaddr, segbp->b_bcount); return (-E_FAULT); } if (! (segbp->b_flags & B_SCATGATH)) { if (segbp->b_resptr) { resptr = segbp->b_resptr; if ((((u_int) resptr) % sizeof(u_int)) || !(isvawriteable (resptr))) { warn ("sys_disk_request: bad resptr (%p)", resptr); return (-E_FAULT); } resptr = (int *) pa2kva (va2pa (resptr)); } break; } } if ((reqbp->b_flags & B_SCATGATH) && bcount != reqbp->b_sgtot) { warn ("sys_disk_request: invalid scatter/gather, with total (%u) unequal " "to sum of parts (%u)", reqbp->b_sgtot, bcount); return (-E_INVAL); } /* are we done before we've started? */ if (bcount == 0) { if (resptr) (*resptr)--; return (0); } if (bcount & di->d_bmod) { warn ("sys_disk_request: bad bcount %u", bcount); return (-E_INVAL); } /* copy request into kernel buffer */ segbp = reqbp; nsegbp = NULL; reqbp = NULL; do { segbp->b_dev = di->d_id; bp = copy_and_pin(segbp, segbp->b_bcount, &nctemp); if (!bp) { warn ("sys_disk_request: could not copy_and_pin"); /* XXX - cleanup before returning */ return (-E_NO_MEM); } noncontigs += nctemp; if (nsegbp) nsegbp->b_sgnext = bp; if (!reqbp) reqbp = bp; if (noncontigs >= DISK_MAX_SCATTER) { warn ("sys_disk_request: would require too many scatter/gather entries " "(%d)", noncontigs); /* XXX - cleanup before returning */ return (-E_INVAL); } nsegbp = bp; segbp = segbp->b_sgnext; } while (nsegbp->b_flags & B_SCATGATH); nsegbp->b_resptr = resptr; if (resptr) ppage_pin (kva2pp((u_int) resptr)); /* call appropriate strategy routine */ di->d_strategy (reqbp); #ifdef MEASURE_DISK_TIMES disk_pctr_return = rdtsc(); #endif return (0); }
/* * sys_disk_mbr * * Read/Write the master boot record of a disk. * * The mbr contains the bootstrap code that the BIOS * loads on startup. This is always in sector 0 * of the disk being booted. The mbr also contains the * partition table for the disk. * */ int sys_disk_mbr (u_int sn, int write, u_int dev, int k, char *buffer, int *resptr) { cap c; int ret; struct buf *diskbuf; /* get the capability */ if ((ret = env_getcap (curenv, k, &c)) < 0) return ret; /* make sure the root cap was passed in */ if (!cap_isroot (&c)) return -E_CAP_INSUFF; /* verify the dev */ if (dev >= si->si_ndisks) return -E_NOT_FOUND; /* check and translate the buffers we were given */ if ((((u_int) resptr) % sizeof(u_int)) || !(isvawriteable (resptr))) { warn ("sys_disk_mrb: bad resptr (%p)", resptr); return (-E_FAULT); } ppage_pin (pa2pp ((va2pa (resptr)))); resptr = (int *) pa2kva (va2pa (resptr)); if (write) { if (! (iswriteable_varange ((u_int)buffer, 512))) { warn ("sys_disk_mbr: bad buffer (%p)", buffer); return (-E_FAULT); } } else { if (! (isreadable_varange ((u_int)buffer, 512))) { warn ("sys_disk_mbr: bad buffer (%p)", buffer); return (-E_FAULT); } } /* get a disk req buffer and fill it in */ diskbuf = disk_buf_alloc (); if (!diskbuf) return -E_NO_MEM; diskbuf->b_next = NULL; diskbuf->b_sgnext = NULL; diskbuf->b_dev = dev; diskbuf->b_blkno = 0; diskbuf->b_bcount = 512; /* only want to read the first sector */ diskbuf->b_sgtot = 512; diskbuf->b_memaddr = buffer; diskbuf->b_envid = curenv->env_id; diskbuf->b_resid = 0; diskbuf->b_resptr = resptr; diskbuf->b_flags = B_ABSOLUTE; /* bypass partitions table */ if (write) { diskbuf->b_flags |= B_WRITE; } else { diskbuf->b_flags |= B_READ; } /* pin it in case the user frees it before the request completes. This will be unpinned when sched_reqcomplete is called which in turn calls disk_buf_free which calls ppage_unpin. */ ppage_pin (pa2pp ((va2pa (buffer)))); /* start the request */ si->si_disks[dev].d_strategy (diskbuf); return 0; }
/* XXX - we should use copyin, etc, instead of isreadable_* so that user will get pagefaults he can handle transparently */ static int sys_disk_scsicmd (u_int sn, u_int k, struct buf *reqbp) { struct buf *bp; struct scsicmd *scsicmd = (struct scsicmd *) reqbp->b_memaddr; struct scsicmd *scsicmd2; int noncontigs; struct disk *di; /* must have root capability for system to do a raw SCSI command!! */ /* XXX -- later, if desired, deeper checking of validity can reduce */ /* this restriction... */ if (k >= curenv->env_clen || ! curenv->env_clist[k].c_valid) { warn ("sys_disk_scsicmd: bad capability number %u\n", k); return (-E_CAP_INVALID); } if (! cap_isroot(&curenv->env_clist[k])) { warn ("sys_disk_scsicmd: cap %u is not root capability for system\n", k); return (-E_CAP_INSUFF); } /* must be able to read the reqbp ... */ if (! (isreadable_varange ((u_int) reqbp, sizeof (struct buf)))) { warn ("sys_disk_scsicmd: bad reqbp (%p)", reqbp); return (-E_FAULT); } /* Should be a SCSICMD */ if (! (reqbp->b_flags & B_SCSICMD)) { warn ("sys_disk_scsicmd: not a B_SCSICMD\n"); return (-E_INVAL); } /* Must be proper environment */ if (reqbp->b_envid != curenv->env_id) { warn ("sys_disk_scsicmd: bad envid\n"); return (-E_INVAL); } /* no scatter/gather support for raw SCSI commands */ if (reqbp->b_flags & B_SCATGATH) { warn ("sys_disk_scsicmd: B_SCATGATH not allowed with B_SCSICMD\n"); return (-E_INVAL); } /* can't send request to non-existent disk... */ if (reqbp->b_dev >= si->si_ndevs) { warn ("sys_disk_scsicmd: there is no disk %u in system\n", reqbp->b_dev); return (-E_NOT_FOUND); } /* check that everything is readable */ if (! isreadable_varange ((u_int) reqbp->b_memaddr, sizeof (struct scsicmd))) { warn ("sys_disk_scsicmd: SCSI command description is not readable\n"); return (-E_FAULT); } if (! isreadable_varange ((u_int) scsicmd->scsi_cmd, scsicmd->cmdlen) ) { warn ("sys_disk_scsicmd: SCSI command itself is not readable\n"); return (-E_FAULT); } if (! isreadable_varange ((u_int)scsicmd->data_addr, scsicmd->datalen) ) { warn ("sys_disk_scsicmd: data area for SCSI command is not readable\n"); return (-E_FAULT); } /* length of SCSI command must not be greater than B_SCSICMD_MAXLEN */ if (scsicmd->cmdlen > B_SCSICMD_MAXLEN) { /* XXX - why do we compare scsicmd->cmdlen, but we print out reqbp->b_bcount? */ warn ("sys_disk_scsicmd: specified SCSI command too large (%d > %d)\n", reqbp->b_bcount, B_SCSICMD_MAXLEN); return (-E_INVAL); } /* copy the SCSI command to avoid sharing it with app */ bp = bp_copy (reqbp); if (bp == NULL) { warn ("sys_disk_scsicmd: kernel malloc for bp failed\n"); return (-E_NO_MEM); } bp->b_memaddr = malloc (sizeof (struct scsicmd)); if (bp->b_memaddr == NULL) { warn ("sys_disk_scsicmd: kernel malloc for scsicmd failed\n"); free (bp); return (-E_NO_MEM); } scsicmd2 = (struct scsicmd *) bp->b_memaddr; bcopy (scsicmd, scsicmd2, sizeof (struct scsicmd)); scsicmd2->scsi_cmd = (struct scsi_generic *) malloc (scsicmd->cmdlen); if (scsicmd2->scsi_cmd == NULL) { warn ("sys_disk_scsicmd: second kernel malloc failed\n"); free (bp->b_memaddr); free (bp); return (-E_NO_MEM); } bcopy (scsicmd->scsi_cmd, scsicmd2->scsi_cmd, scsicmd->cmdlen); scsicmd2->bp = bp; bp->b_resid = scsicmd->datalen; bp->b_resptr = (int *) pa2kva (va2pa (reqbp->b_resptr)); /* pin down the app pages that will later be used by the driver */ ppage_pin (kva2pp ((u_int) bp->b_resptr)); noncontigs = pin_and_count_noncontigs (scsicmd2->data_addr, scsicmd2->datalen); if (noncontigs >= DISK_MAX_SCATTER) { warn ("sys_disk_scsicmd: will require too many scatter/gather entries " "(%d)", noncontigs); disk_buf_free (bp); return (-E_TOO_BIG); } /* XXX */ /* call down to the low-level driver. GROK -- since the partition stuff */ /* creates and abstract disk that is separate from the real one, a hack */ /* is needed to get the actual disk strategy routine for raw SCSI commands */ /* This is fine as long as all disks actually go to the same strategy */ /* routine. */ di = &(si->si_disks[0]); di->d_strategy (bp); return (0); }
static msgringent * msgringent_setup (msgringent * u_msgringent) { msgringent *ktmp; Pte *pte = NULL; int scatptr = 0; int total_len = 0; ktmp = (msgringent *) malloc (sizeof (msgringent)); if (ktmp == NULL) { warn ("msgringent_setup: failed malloc"); return (NULL); } ktmp->appaddr = u_msgringent; ktmp->owner = NULL; ktmp->body.n = 0; /* Verify and translate owner field */ if ((((u_int) u_msgringent->owner % sizeof (int)) || ! (pte = va2ptep ((u_int) u_msgringent->owner)) || ((*pte & WRITE_MASK) != WRITE_MASK))) { warn ("msgringent_setup: owner field failed\n"); msgringent_free (ktmp); return (NULL); } ktmp->owner = (u_int *) pa2kva (va2pa (u_msgringent->owner)); ppage_pin (kva2pp ((u_long) ktmp->owner)); /* Verify and translate data field */ if (u_msgringent->body.n > 1) { warn ("msgringent_setup: not allowed to setup disjoint message body\n"); msgringent_free (ktmp); return (NULL); } scatptr = 0; total_len = 0; { int len = u_msgringent->body.r[0].sz; caddr_t addr = u_msgringent->body.r[0].data; u_int pagebound = NBPG-(((u_long)addr)&(NBPG - 1)); while (len > 0) { u_int slen = min (len, pagebound); if (!(pte = va2ptep ((u_int) addr)) || ((*pte & READ_MASK) != READ_MASK)) { /* physical page is not accessible */ warn ("msgringent_setup: can't read scatter ptr\n"); msgringent_free (ktmp); return (NULL); } ktmp->body.r[scatptr].data = (char *) pa2kva (va2pa (addr)); ktmp->body.r[scatptr].sz = slen; ktmp->body.n++; /* pin the page to prevent re-allocation */ ppage_pin (kva2pp ((u_long) ktmp->body.r[scatptr].data)); len -= slen; addr += slen; total_len += slen; pagebound = NBPG; scatptr++; if (scatptr > IPC_MAX_SCATTER_PTR || total_len > IPC_MAX_MSG_SIZE) { msgringent_free (ktmp); warn ("msgringent_setup: message body too big\n"); return (NULL); } } } return (ktmp); }
int sys_chdir(const char *path) { return frontend_syscall(SYS_chdir, va2pa(path), 0, 0, 0, 0, 0, 0); }
/* 函数功能:打开文件 输入参数:文件名 pathname 打开方式 flags 进程指针 p_tcb 输出参数:成功返回进程filp中的fd下标,失败返回-1 */ int fs_open(char * pathname,int flags,TCB* p_tcb) { pathname = va2pa(p_tcb->pdb,pathname); DEV_Inode* p_devinode; int inode_nr; File_Desc* p_fd; Inode* p_inode; Dir_Entry* p_de; int i,j; // 读目录文件,寻找pathname,获得其inode_nr int file_offset = 0; for(i = 0,inode_nr = 0;i < ROOT_SECTS;i++,file_offset += SECTOR_SIZE) { file_buff_read(fsbuf,p_inode_de,file_offset,SECTOR_SIZE); for(j = 0,p_de = (Dir_Entry*)fsbuf;j < DIR_ENT_PER_SECT;j++,p_de++) { if(strcmp(p_de->name,pathname) == 0) { inode_nr = p_de->inode_nr; break; } } if(inode_nr != 0) break; } // 目录中寻找结束 if(inode_nr == 0) // 没找到dev_inode { if(flags == O_CREATE) { // 这里应该判断待创建打开的是否是普通文件 inode_nr = create_file(pathname); if(inode_nr == 0) { printk("create_file error! %s\n",pathname); return -1; // 创建文件失败 } } else { printk("no file : %s\n",pathname); return -1; // 没有找到,也没有创建文件 } } //printk("file : %s inode_nr : %d\n",pathname,inode_nr); // 找到了dev_inode编号inode_nr // 查看内存里的inode_table中是否存在该inode int i_dev = ROOT_DEV; Inode* p_inode_empty = 0; Inode* p_inode_empty1 = 0; for(p_inode = inode_table;p_inode < inode_table + MAX_ALL_INODE;p_inode++) { if(p_inode->i_cnt == 0) { if(p_inode_empty == 0) p_inode_empty = p_inode; // 第一个空位 if(p_inode_empty1 == 0 && p_inode->i_dev == 0 && p_inode->i_num == 0) p_inode_empty1 = p_inode; // 第一个从未被使用过的空位 } if(p_inode->i_dev != i_dev) continue; if(p_inode->i_num != inode_nr) continue; break; } int new_inode = 0; if(p_inode >= inode_table + MAX_ALL_INODE) // 不在inode_table里,需要手动添加 { // 在inode_table中寻找一个空位 if(p_inode_empty1 != 0) { p_inode = p_inode_empty1; } else { if(p_inode_empty == 0) { printk("inode_table full : %s----",pathname); return -1; // inode_table无空位 } p_inode = p_inode_empty; } new_inode = 1; // 用于判断该inode是否是新添加的 } // 此时p_inode的i_dev i_num正确,但是i_cnt可能是0。即:现在找到的inode可能是正在被其他进程共享的,也可能是被其他进程废弃的 // 在file_table中寻找一个空位 for(p_fd = file_table;p_fd < file_table + MAX_ALL_FILE;p_fd++) { if(p_fd->fd_inode == 0) break; } //printk(" p_fd : %d \n",p_fd - file_table); if(p_fd >= file_table + MAX_ALL_FILE) { printk("file_table full : %s----",pathname); return -1; // file_table无空位 } // 在进程filp数组中寻找一个空位 for(i = 0;i < MAX_TASK_FILE;i++) { if(p_tcb->filp[i] == 0) break; } if(i >= MAX_TASK_FILE) { printk("filp full : %s----",pathname); return -1; // filp无空位 } // 填充空位信息 p_tcb->filp[i] = p_fd; p_fd->fd_mode = RD_WR; p_fd->fd_pos = 0; p_fd->fd_inode = p_inode; p_inode->i_cnt++; if(new_inode == 1) // 新添加的inode,需要赋值 { //printk("new inode : %d\n",inode_nr); // 获取dev_inode指针 hd_read(ROOT_DEV,fsbuf,SECTOR_SIZE * (INODE_1ST_SECTS + inode_nr / INODE_PER_SECT),1); p_devinode = (DEV_Inode*)fsbuf; p_devinode += inode_nr % INODE_PER_SECT; // 赋值 p_inode->i_mode = p_devinode->i_mode; p_inode->i_size = p_devinode->i_size; p_inode->i_start_sect = p_devinode->i_start_sect; p_inode->i_nr_sects = p_devinode->i_nr_sects; p_inode->i_dev = ROOT_DEV; p_inode->i_num = inode_nr; } // 返回filp中的下标 //printk("file open : %s ----",pathname); if(p_inode->i_mode == I_MODE_CHAR) // 字符设备文件 { MSG msg; msg.type = TTY_MSG_UNION; msg.msg_union.tty_msg.para = DEV_OPEN; msg.msg_union.tty_msg.sub_device = MINOR(p_inode->i_start_sect); // 字符设备的i_start_sect即设备号 //printk("sub_device : %d ",msg.msg_union.tty_msg.sub_device); disable_int(); if(tty_has_msg_tmp == 0) { assert(sendrecv(BOTH,dd_map[MAJAR(p_inode->i_start_sect)],&msg) == 0); } enable_int(); } //printk(" i : %d----",i); return i; }
static int sbromsw_toc1_traverse(void) { sbrom_toc1_item_group item_group; int ret; uint len, i; u8 buffer[SUNXI_X509_CERTIFF_MAX_LEN]; sunxi_certif_info_t root_certif; sunxi_certif_info_t sub_certif; u8 hash_of_file[256]; //u8 hash_in_certif[256]; //u8 key_certif_extension[260]; //u8 content_certif_key[520]; int out_to_ns; int ready_out_to_ns = 0; toc1_item_traverse(); printf("probe root certif\n"); sunxi_ss_open(); memset(buffer, 0, SUNXI_X509_CERTIFF_MAX_LEN); len = toc1_item_read_rootcertif(buffer, SUNXI_X509_CERTIFF_MAX_LEN); if(!len) { printf("%s error: cant read rootkey certif\n", __func__); return -1; } if(sunxi_certif_verify_itself(&root_certif, buffer, len)) { printf("certif invalid: root certif verify itself failed\n"); return -1; } do { memset(&item_group, 0, sizeof(sbrom_toc1_item_group)); ret = toc1_item_probe_next(&item_group); if(ret < 0) { printf("sbromsw_toc1_traverse err in toc1_item_probe_next\n"); return -1; } else if(ret == 0) { printf("sbromsw_toc1_traverse find out all items\n"); return 0; } if(item_group.bin_certif) { memset(buffer, 0, SUNXI_X509_CERTIFF_MAX_LEN); len = toc1_item_read(item_group.bin_certif, buffer, SUNXI_X509_CERTIFF_MAX_LEN); if(!len) { printf("%s error: cant read content key certif\n", __func__); return -1; } //证书内容进行自校验,确保没有被替换 if(sunxi_certif_verify_itself(&sub_certif, buffer, len)) { printf("%s error: cant verify the content certif\n", __func__); return -1; } // printf("key n:\n"); // ndump(sub_certif.pubkey.n, sub_certif.pubkey.n_len); // printf("key e:\n"); // ndump(sub_certif.pubkey.e, sub_certif.pubkey.e_len); //每当发现一个公钥证书,即在根证书中寻找匹配项目,找不到则认为有错误 for(i=0;i<root_certif.extension.extension_num;i++) { if(!strcmp((const char *)root_certif.extension.name[i], item_group.bin_certif->name)) { printf("find %s key stored in root certif\n", item_group.bin_certif->name); if(memcmp(root_certif.extension.value[i], sub_certif.pubkey.n+1, sub_certif.pubkey.n_len-1)) { printf("%s key n is incompatible\n", item_group.bin_certif->name); printf(">>>>>>>key in rootcertif<<<<<<<<<<\n"); ndump(root_certif.extension.value[i], sub_certif.pubkey.n_len-1); printf(">>>>>>>key in certif<<<<<<<<<<\n"); ndump(sub_certif.pubkey.n+1, sub_certif.pubkey.n_len-1); return -1; } if(memcmp(root_certif.extension.value[i] + sub_certif.pubkey.n_len-1, sub_certif.pubkey.e, sub_certif.pubkey.e_len)) { printf("%s key e is incompatible\n", item_group.bin_certif->name); printf(">>>>>>>key in rootcertif<<<<<<<<<<\n"); ndump(root_certif.extension.value[i] + sub_certif.pubkey.n_len-1, sub_certif.pubkey.e_len); printf(">>>>>>>key in certif<<<<<<<<<<\n"); ndump(sub_certif.pubkey.e, sub_certif.pubkey.e_len); return -1; } break; } } if(i==root_certif.extension.extension_num) { printf("cant find %s key stored in root certif", item_group.bin_certif->name); return -1; } } if(item_group.binfile) { //读出bin文件内容到内存 len = sunxi_flash_read(item_group.binfile->data_offset/512, (item_group.binfile->data_len+511)/512, (void *)item_group.binfile->run_addr); //len = sunxi_flash_read(item_group.binfile->data_offset/512, (item_group.binfile->data_len+511)/512, (void *)0x2a000000); if(!len) { printf("%s error: cant read bin file\n", __func__); return -1; } //计算文件hash memset(hash_of_file, 0, sizeof(hash_of_file)); ret = sunxi_sha_calc(hash_of_file, sizeof(hash_of_file), (u8 *)item_group.binfile->run_addr, item_group.binfile->data_len); //ret = sunxi_sha_calc(hash_of_file, sizeof(hash_of_file), (u8 *)0x2a000000, item_group.binfile->data_len); if(ret) { printf("sunxi_sha_calc: calc sha256 with hardware err\n"); return -1; } //使用内容证书的扩展项,和文件hash进行比较 //开始比较文件hash(小机端阶段计算得到)和证书hash(PC端计算得到) if(memcmp(hash_of_file, sub_certif.extension.value[0], 32)) { printf("hash compare is not correct\n"); printf(">>>>>>>hash of file<<<<<<<<<<\n"); ndump(hash_of_file, 32); printf(">>>>>>>hash in certif<<<<<<<<<<\n"); ndump(sub_certif.extension.value[0], 32); return -1; } printf("ready to run %s\n", item_group.binfile->name); if(!toc0_config->secure_without_OS) { ready_out_to_ns = 1; } else { printf("secure_without_OS mode \n"); ready_out_to_ns = 0; } if(strcmp(item_group.binfile->name, "u-boot")) { out_to_ns = SECURE_SWITCH_OTHER; } else { if(!ready_out_to_ns) out_to_ns = SECURE_NON_SECUREOS; else out_to_ns = SECURE_SWITCH_NORMAL; } toc0_config->next_exe_pa = va2pa(item_group.binfile->run_addr); go_exec(item_group.binfile->run_addr, CONFIG_TOC0_CONFIG_ADDR, out_to_ns); } } while(1); return 0; }
void page_check(void) { struct Page *pp, *pp0, *pp1, *pp2; struct Page_list fl; // should be able to allocate three pages pp0 = pp1 = pp2 = 0; assert(page_alloc(&pp0) == 0); assert(page_alloc(&pp1) == 0); assert(page_alloc(&pp2) == 0); assert(pp0); assert(pp1 && pp1 != pp0); assert(pp2 && pp2 != pp1 && pp2 != pp0); // temporarily steal the rest of the free pages fl = page_free_list; LIST_INIT(&page_free_list); // should be no free memory assert(page_alloc(&pp) == -E_NO_MEM); // there is no free memory, so we can't allocate a page table assert(page_insert(boot_pgdir, pp1, 0x0, 0) < 0); // free pp0 and try again: pp0 should be used for page table page_free(pp0); assert(page_insert(boot_pgdir, pp1, 0x0, 0) == 0); assert(PTE_ADDR(boot_pgdir[0]) == page2pa(pp0)); assert(va2pa(boot_pgdir, 0x0) == page2pa(pp1)); assert(pp1->pp_ref == 1); // should be able to map pp2 at BY2PG because pp0 is already allocated for page table assert(page_insert(boot_pgdir, pp2, BY2PG, 0) == 0); assert(va2pa(boot_pgdir, BY2PG) == page2pa(pp2)); assert(pp2->pp_ref == 1); // should be no free memory assert(page_alloc(&pp) == -E_NO_MEM); //printf("why\n"); // should be able to map pp2 at BY2PG because it's already there assert(page_insert(boot_pgdir, pp2, BY2PG, 0) == 0); assert(va2pa(boot_pgdir, BY2PG) == page2pa(pp2)); assert(pp2->pp_ref == 1); //printf("It is so unbelivable\n"); // pp2 should NOT be on the free list // could happen in ref counts are handled sloppily in page_insert assert(page_alloc(&pp) == -E_NO_MEM); // should not be able to map at PDMAP because need free page for page table assert(page_insert(boot_pgdir, pp0, PDMAP, 0) < 0); // insert pp1 at BY2PG (replacing pp2) assert(page_insert(boot_pgdir, pp1, BY2PG, 0) == 0); // should have pp1 at both 0 and BY2PG, pp2 nowhere, ... assert(va2pa(boot_pgdir, 0x0) == page2pa(pp1)); assert(va2pa(boot_pgdir, BY2PG) == page2pa(pp1)); // ... and ref counts should reflect this assert(pp1->pp_ref == 2); assert(pp2->pp_ref == 0); // pp2 should be returned by page_alloc assert(page_alloc(&pp) == 0 && pp == pp2); // unmapping pp1 at 0 should keep pp1 at BY2PG page_remove(boot_pgdir, 0x0); assert(va2pa(boot_pgdir, 0x0) == ~0); assert(va2pa(boot_pgdir, BY2PG) == page2pa(pp1)); assert(pp1->pp_ref == 1); assert(pp2->pp_ref == 0); // unmapping pp1 at BY2PG should free it page_remove(boot_pgdir, BY2PG); assert(va2pa(boot_pgdir, 0x0) == ~0); assert(va2pa(boot_pgdir, BY2PG) == ~0); assert(pp1->pp_ref == 0); assert(pp2->pp_ref == 0); // so it should be returned by page_alloc assert(page_alloc(&pp) == 0 && pp == pp1); // should be no free memory assert(page_alloc(&pp) == -E_NO_MEM); // forcibly take pp0 back assert(PTE_ADDR(boot_pgdir[0]) == page2pa(pp0)); boot_pgdir[0] = 0; assert(pp0->pp_ref == 1); pp0->pp_ref = 0; // give free list back page_free_list = fl; // free the pages we took page_free(pp0); page_free(pp1); page_free(pp2); printf("page_check() succeeded!\n"); }
long sys_getcwd(const char* buf, size_t size) { populate_mapping(buf, size, PROT_WRITE); return frontend_syscall(SYS_getcwd, va2pa(buf), size, 0, 0, 0, 0, 0); }