int sys_read(int *retval, int fdn, void *buf, size_t nbytes) { //Check for Bad memory reference. if (!buf || (u_int32_t) buf >= MIPS_KSEG0 || !as_valid_write_addr(curthread->t_vmspace,buf)) { return EFAULT; } //Get the file descriptor from the opened list of file descriptors that the current thread has, based on the fdn given. struct filedescriptor* fd = ft_get(curthread->ft, fdn); if (fd == NULL) { return EBADF; } //Make sure that the file is opened for writing. switch (O_ACCMODE & fd->mode) { case O_RDONLY: case O_RDWR: break; default: return EBADF; } //Make the uio struct uio u; mk_kuio(&u, (void *) buf, nbytes, fd->offset, UIO_READ); //Disable interrupt //int spl; //spl = splhigh(); //Read int sizeread = VOP_READ(fd->fdvnode, &u); //splx(spl); if (sizeread) { return sizeread; } //Find the number of bytes read sizeread = nbytes - u.uio_resid; *retval = sizeread; //Update the offset fd->offset += sizeread; return 0; }
int swap_pagein( u_int32_t paddr, int rw, u_int32_t mem, u_int32_t file, u_int32_t offset, int swap, int swap_index) { int result; int fillamt; struct uio u; struct addrspace *as; // struct vnode *swap_vnode; as = curthread->t_vmspace; if(swap == 1) { result = vfs_open(SWAP_DEVICE, O_RDWR, &swap_vnode); mk_kuio(&u, paddr, PAGE_SIZE, swap_index * PAGE_SIZE, UIO_READ); result = VOP_READ(swap_vnode, &u); if (result) { return result; } vfs_close(swap_vnode); } else { /* Open the file. */ struct vnode *v; result = vfs_open(as->as_progname, O_RDONLY, &v); if (result) { return result; } mk_kuio_pd(&u, paddr, mem, file, offset, rw); if(rw == UIO_READ) { result = VOP_READ(v, &u) ; } else { result = VOP_WRITE(v, &u); } if (u.uio_resid != 0) { /* short read; problem with executable? */ kprintf("ELF: short read on segment - file truncated?\n"); return ENOEXEC; } /* Fill the rest of the memory space (if any) with zeros */ fillamt = mem - file; if (fillamt > 0) { u.uio_resid += fillamt; u.uio_rw = UIO_READ; result = uiomovezeros(fillamt, &u); } if (result==EIO) { panic("swap: EIO on swapfile (offset %ld)\n", (long)as->as_offset1); } else if (result==EINVAL) { panic("swap: EINVAL from swapfile (offset %ld)\n", (long)as->as_offset1); } else if (result) { panic("swap: Error %d from swapfile (offset %ld)\n", result, (long)as->as_offset1); } /* Done with the file now. */ vfs_close(v); return 0; } }
/* * Load an ELF executable user program into the current address space. * * Returns the entry point (initial PC) for the program in ENTRYPOINT. */ int load_elf(struct vnode *v, vaddr_t *entrypoint) { Elf_Ehdr eh; /* Executable header */ Elf_Phdr ph; /* "Program header" = segment header */ int result, i; struct uio ku; /* * Read the executable header from offset 0 in the file. */ mk_kuio(&ku, &eh, sizeof(eh), 0, UIO_READ); result = VOP_READ(v, &ku); if (result) { return result; } if (ku.uio_resid != 0) { /* short read; problem with executable? */ kprintf("ELF: short read on header - file truncated?\n"); return ENOEXEC; } /* * Check to make sure it's a 32-bit ELF-version-1 executable * for our processor type. If it's not, we can't run it. * * Ignore EI_OSABI and EI_ABIVERSION - properly, we should * define our own, but that would require tinkering with the * linker to have it emit our magic numbers instead of the * default ones. (If the linker even supports these fields, * which were not in the original elf spec.) */ if (eh.e_ident[EI_MAG0] != ELFMAG0 || eh.e_ident[EI_MAG1] != ELFMAG1 || eh.e_ident[EI_MAG2] != ELFMAG2 || eh.e_ident[EI_MAG3] != ELFMAG3 || eh.e_ident[EI_CLASS] != ELFCLASS32 || eh.e_ident[EI_DATA] != ELFDATA2MSB || eh.e_ident[EI_VERSION] != EV_CURRENT || eh.e_version != EV_CURRENT || eh.e_type!=ET_EXEC || eh.e_machine!=EM_MACHINE) { return ENOEXEC; } /* * Go through the list of segments and set up the address space. * * Ordinarily there will be one code segment, one read-only * data segment, and one data/bss segment, but there might * conceivably be more. You don't need to support such files * if it's unduly awkward to do so. * * Note that the expression eh.e_phoff + i*eh.e_phentsize is * mandated by the ELF standard - we use sizeof(ph) to load, * because that's the structure we know, but the file on disk * might have a larger structure, so we must use e_phentsize * to find where the phdr starts. */ for (i=0; i<eh.e_phnum; i++) { off_t offset = eh.e_phoff + i*eh.e_phentsize; mk_kuio(&ku, &ph, sizeof(ph), offset, UIO_READ); result = VOP_READ(v, &ku); if (result) { return result; } if (ku.uio_resid != 0) { /* short read; problem with executable? */ kprintf("ELF: short read on phdr - file truncated?\n"); return ENOEXEC; } switch (ph.p_type) { case PT_NULL: /* skip */ continue; case PT_PHDR: /* skip */ continue; case PT_MIPS_REGINFO: /* skip */ continue; case PT_LOAD: break; default: kprintf("loadelf: unknown segment type %d\n", ph.p_type); return ENOEXEC; } //ph coming from compiler from the elf file loaded result = as_define_region(curthread->t_vmspace, ph.p_vaddr, ph.p_filesz, ph.p_flags & PF_R, ph.p_flags & PF_W, ph.p_flags & PF_X, v, ph.p_offset, ph.p_memsz); if (result) { return result; } } result = as_prepare_load(curthread->t_vmspace);//Does getpages if (result) { return result; } /* * Now actually load each segment. */ /*for (i=0; i<eh.e_phnum; i++) { off_t offset = eh.e_phoff + i*eh.e_phentsize; mk_kuio(&ku, &ph, sizeof(ph), offset, UIO_READ); result = VOP_READ(v, &ku); if (result) { return result; } if (ku.uio_resid != 0) { //short read; problem with executable? kprintf("ELF: short read on phdr - file truncated?\n"); return ENOEXEC; } switch (ph.p_type) { case PT_NULL: continue; case PT_PHDR: continue; case PT_MIPS_REGINFO: continue; case PT_LOAD: break; default: kprintf("loadelf: unknown segment type %d\n", ph.p_type); return ENOEXEC; } result = load_segment(v, ph.p_offset, ph.p_vaddr, ph.p_memsz, ph.p_filesz, ph.p_flags & PF_X); if (result) { return result; } }*/ result = as_complete_load(curthread->t_vmspace); if (result) { return result; } *entrypoint = eh.e_entry; return 0; }
int sys_write(int fd, const void *buf, size_t nbytes, int32_t *retval) { if (fd < 0) { *retval = EBADF; return -1; } if (fd >= MAX_OPENED_FILES) { *retval = EBADF; //kprintf("invalid fd!\n"); return -1; } if (buf <= 0x0 || buf + nbytes <= 0x0 || buf >= 0x80000000|| buf + nbytes >= 0x80000000 || buf == 0x40000000 || buf + nbytes == 0x40000000) { *retval = EFAULT; return -1; } int result =0; if (fd < 3 && ((curthread->files[fd] == NULL))) { struct vnode *vn =NULL; pid_t notUsed = 0; char *consolein = NULL; consolein = kstrdup("con:"); vn = kmalloc (sizeof(struct vnode)); result = vfs_open(consolein,O_RDONLY,&vn); if (result){ *retval = (int32_t)notUsed; return -1; } curthread->files[0] = files_create(kstrdup("con:"),vn, O_RDONLY); curthread->files[1] = files_create(kstrdup("con:"),vn, O_WRONLY); curthread->files[2] = files_create(kstrdup("con:"),vn, O_WRONLY); kfree(consolein); } struct uio copyUIO; switch (fd) { case 0: *retval = EBADF; return -1; case 1: case 2: { int i; for (i = 0; i < nbytes; i++) { putch(((char*)buf)[i]); } } break; default: { struct files *file = curthread->files[fd]; if (file == NULL) { *retval = EBADF; return -1; } // void* klebuf = kmalloc (sizeof(nbytes)); // copyin (buf, klebuf, nbytes); mk_kuio(©UIO, (void*)buf, nbytes, file->offset, UIO_WRITE); result = VOP_WRITE (file->vn, ©UIO); if (result) { return result; } //kfree(klebuf); /* mk_kuio(©UIO, buf, nbytes, file->offset, UIO_WRITE); result = VOP_WRITE (file->vn, ©UIO); if (result == 0) { // check if VOP_WRITE done }else{ } */ *retval = nbytes - copyUIO.uio_resid; file->offset += *retval; } } return 0; }