Exemplo n.º 1
0
/**
 * @param name is prined before the tag value.
 * @param tag is the tag id.
 * @param wc is the size of the property in words.
 */
static void print_prop(char * name, uint32_t tag, size_t wc)
{
    uint32_t mbuf[6 + wc] __attribute__((aligned (16)));
    int err;
    char buf[80];
    char * s;

    mbuf[0] = sizeof(mbuf);         /* Size */
    mbuf[1] = BCM2835_PROP_REQUEST; /* Request */
    /* Tags */
    mbuf[2] = tag;
    mbuf[3] = wc * 4;
    mbuf[4] = 0; /* Request len always zero */
    mbuf[5 + wc] = BCM2835_PROP_TAG_END;

    err = bcm2835_prop_request(mbuf);
    if (err) {
        KERROR(KERROR_INFO, "bcm2835_info %s: ERR %d\n", name, err);
        return;
    }

    s = buf;
    for (size_t i = 0; i < wc; i++) {
        s += ksprintf(s, buf + sizeof(buf) - s, "%x ", mbuf[5 + i]) - 1;
    }
    KERROR(KERROR_INFO, "bcm2835_info %s: %s\n", name, buf);
}
Exemplo n.º 2
0
/**
 * Get kmalloc'd array for full path name.
 */
static char * format_fpath(struct fatfs_inode * indir, const char * name)
{
    char * fpath;
    size_t fpath_size;

#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG,
             "format_fpath(indir \"%s\", name \"%s\")\n",
             indir->in_fpath, name);
#endif

    fpath_size = strlenn(name, NAME_MAX + 1) +
                 strlenn(indir->in_fpath, NAME_MAX + 1) + 6;
    fpath = kmalloc(fpath_size);
    if (!fpath)
        return NULL;

    ksprintf(fpath, fpath_size, "%s/%s", indir->in_fpath, name);

#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG, "Formatted \"%s\" as \"%s\"\n",
           name, fpath);
#endif

    return fpath;
}
Exemplo n.º 3
0
Arquivo: fb.c Projeto: Zeke-OS/zeke
/*
 * TODO If fb is a default kerror output device then a fb should be registered
 * before kerror is initialized but there is no obvious way to do that, since
 * we definitely want to keep fb constructors in driver files to support
 * dynamic loading, in the future, just for example.
 */
int fb_register(struct fb_conf * fb)
{
    const int minor = atomic_inc(&fb_minor);
    dev_t devid_tty;
    dev_t devid_mm;
    int err;

    devid_tty = DEV_MMTODEV(VDEV_MJNR_FB, minor);
    devid_mm = DEV_MMTODEV(VDEV_MJNR_FBMM, minor);

    fb_console_init(fb);
    err = fb_console_maketty(fb, devid_tty);
    if (err) {
        KERROR(KERROR_ERR, "FB: maketty failed\n");
        return err;
    }

    err = fb_makemmdev(fb, devid_mm);
    if (err) {
        KERROR(KERROR_ERR, "FB: makemmdev failed\n");
        return err;
    }

    draw_splash(fb);
    fb_console_write(fb, "FB ready\r\n");

    return 0;
}
Exemplo n.º 4
0
Arquivo: module.c Projeto: UIKit0/TSOS
/*
 * Reads the file from the path into a temporary buffer, and then attempt to
 * load it as a kernel module.
 *
 * @param path Path to the kernel module
 * @param err Pointer to an integer in which to store a more detailed error
 * @return true if success, false if error.
 */
bool module_load_from_file(char *path, int *err) {
	// Attempt to open file
	fs_file_handle_t *module = hal_vfs_fopen(path, kFSFileModeReadOnly);
	if(module) {
		// Reject modules > 1MB in size
		fs_file_t *file = hal_vfs_handle_to_file(module);
		if(file->size > MODULE_MAX_SIZE) {
			KERROR("%s is %u bytes, max %u bytes", path, (unsigned int) file->size, MODULE_MAX_SIZE);
			return false;
		}

		// Get buffer and zero it
		void *buf = (void *) paging_module_buffer();
		memclr(buf, MODULE_MAX_SIZE);

		// Read entire file
		hal_vfs_fread(buf, file->size, module);

		// Clean up
		hal_vfs_fclose(module);

		// Perform module loading
		module_load(buf, file->i.name);
	} else {
		KERROR("Can't open '%s' for module read", path);
	}

	return false;
}
Exemplo n.º 5
0
Arquivo: atag.c Projeto: htchiang/zeke
/**
 * ATAG scanner.
 * @note This function is called before intializers.
 */
void atag_scan(uint32_t fw, uint32_t mtype, uint32_t * atag_addr)
{
    uint32_t * atags;

    sysinfo.mtype = mtype;

    if (atag_addr[0] == 0 || atag_addr[1] != ATAG_CORE) {
        KERROR(KERROR_WARN, "No ATAGs!\n");
        return;
    }

    for (atags = atag_addr; atags < (uint32_t *)0x8000; atags += 1) {
        switch (atags[1]) {
        case ATAG_CORE:
            KERROR(KERROR_INFO,
                    "[ATAG_CORE] flags: %x, page size: %u, rootdev: %u\n",
                    atags[2], atags[3], atags[4]);

            atags += atags[0]-1;
            break;
        case ATAG_MEM:
            KERROR(KERROR_INFO, "[ATAG_MEM] size: %x, start: %x\n",
                   atags[2], atags[3]);

            sysinfo_setmem((size_t)atags[3], (size_t)atags[2]);
            atags += atags[0]-1;
            break;
        case ATAG_VIDEOTEXT:
            atags += atags[0]-1;
            break;
        case ATAG_RAMDISK:
            atags += atags[0]-1;
            break;
        case ATAG_INITRD2:
            atags += atags[0]-1;
            break;
        case ATAG_SERIAL:
            atags += atags[0]-1;
            break;
        case ATAG_REVISION:
            atags += atags[0]-1;
            break;
        case ATAG_VIDEOLFB:
            atags += atags[0]-1;
            break;
        case ATAG_CMDLINE:
            atags += 2;

            KERROR(KERROR_INFO, "[ATAG_CMDLINE] : %s\n", (char *)atags);
            sysinfo_cmdline((const char *)atags);

            atags += atags[0]-1;
            break;
        default:
            break;
        }
    }
}
Exemplo n.º 6
0
int ptmapper_alloc(mmu_pagetable_t * pt)
{
    size_t block;
    size_t addr;
    size_t size = 0; /* Size in bitmap */
    size_t bsize = 0; /* Size in bytes */
    size_t balign;
    int retval = 0;

    switch (pt->type) {
    case MMU_PTT_MASTER:
        size = PTM_MASTER;
        bsize = MMU_PTSZ_MASTER;
        balign = 0x10; /* TODO Depends on HW */
        break;
    case MMU_PTT_COARSE:
        size = PTM_COARSE;
        bsize = MMU_PTSZ_COARSE;
        balign = 0x1;
        break;
    default:
        panic("pt size can't be zero");
    }

    /* Try to allocate a new page table */
    if (!PTM_ALLOC(&block, size, balign)) {
#if configDEBUG != 0
        char buf[80];
#endif

        addr = PTM_BLOCK2ADDR(block);
#if configDEBUG >= KERROR_DEBUG
        ksprintf(buf, sizeof(buf),
                "Alloc pt %u bytes @ %x", bsize, addr);
        KERROR(KERROR_DEBUG, buf);
#endif
        pt->pt_addr = addr;
        if (pt->type == MMU_PTT_MASTER) {
            pt->master_pt_addr = addr;
        }

        /* Accounting for sysctl */
        ptm_nr_pt++;
        ptm_mem_free -= bsize;
    } else {
#if configDEBUG >= KERROR_ERR
        KERROR(KERROR_ERR, "Out of pt memory");
#endif
        retval = -1;
    }

    return retval;
}
Exemplo n.º 7
0
void ptmapper_free(mmu_pagetable_t * pt)
{
    size_t block;
    size_t size = 0; /* Size in bitmap */
    size_t bsize = 0; /* Size in bytes */

    switch (pt->type) {
    case MMU_PTT_MASTER:
        size = PTM_MASTER;
        bsize = MMU_PTSZ_MASTER;
        break;
    case MMU_PTT_COARSE:
        size = PTM_COARSE;
        bsize = MMU_PTSZ_COARSE;
        break;
    default:
        KERROR(KERROR_ERR, "Attemp to free an invalid page table.");
        return;
    }

    block = PTM_ADDR2BLOCK(pt->pt_addr);
    PTM_FREE(block, size);

    /* Accounting for sysctl */
    ptm_nr_pt--;
    ptm_mem_free += bsize;
}
Exemplo n.º 8
0
DRESULT fatfs_disk_ioctl(uint8_t pdrv, unsigned cmd, void * buff, size_t bsize)
{
    file_t * file;
    ssize_t err;
#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG,
           "fatfs_disk_ioctl(pdrv %u, cmd %u, buff %p, bsize %u)\n",
           (uint32_t)pdrv, (uint32_t)cmd, buff, (uint32_t)bsize);
#endif

    if (pdrv >= configFATFS_MAX_MOUNTS || !fatfs_sb_arr[pdrv])
        return RES_PARERR;

    file = &fatfs_sb_arr[pdrv]->ff_devfile;
    if (!file->vnode->vnode_ops->ioctl)
        return RES_ERROR;

    switch (cmd) {
    case CTRL_SYNC:
    case CTRL_ERASE_SECTOR:
        /* TODO Not implemented yet. */
        return 0;
        break;
    default:
        break;
    }

    err = file->vnode->vnode_ops->ioctl(file, cmd, buff, bsize);
    if (err)
        return RES_ERROR;

    return 0;
}
Exemplo n.º 9
0
int fatfs_mknod(vnode_t * dir, const char * name, int mode, void * specinfo,
                vnode_t ** result)
{
    struct fatfs_inode * indir = get_inode_of_vnode(dir);
    struct fatfs_inode * res = NULL;
    char * in_fpath;
    int err;

#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG,
           "fatfs_mknod(dir %p, name \"%s\", mode %u, specinfo %p, result %p)\n",
           dir, name, mode, specinfo, result);
#endif

    if (!S_ISDIR(dir->vn_mode))
        return -ENOTDIR;

    if ((mode & S_IFMT) != S_IFREG)
        return -ENOTSUP; /* FAT only suports regular files. */

    if (specinfo)
        return -EINVAL; /* specinfo not supported. */

    in_fpath = format_fpath(indir, name);
    if (!in_fpath)
        return -ENOMEM;

    err = create_inode(&res, get_ffsb_of_sb(dir->sb), in_fpath,
                       hash32_str(in_fpath, 0), O_CREAT);
    if (err) {
        kfree(in_fpath);
        return fresult2errno(err);
    }

    if (result)
        *result = &res->in_vnode;
    fatfs_chmod(&res->in_vnode, mode);

#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG, "mkdod() ok\n");
#endif

    return 0;
}
Exemplo n.º 10
0
struct buf * vr_rclone(struct buf * old_region)
{
    struct buf * new_region;
    const size_t rsize = old_region->b_bufsize;

    /* "Lock", ensure that the region is not freed during the operation. */
    vrref(old_region);

    new_region = geteblk(rsize);
    if (!new_region) {
        KERROR(KERROR_ERR, "Out of memory");
        return 0;
    }

#if configDEBUG >= KERROR_DEBUG
    {
    char buf[80];
    ksprintf(buf, sizeof(buf), "clone %x -> %x, %u bytes",
            old_region->b_data, new_region->b_data, rsize);
    KERROR(KERROR_DEBUG, buf);
    }
#endif

    /* Copy data */
    memcpy((void *)(new_region->b_data), (void *)(old_region->b_data),
            rsize);

    /* Copy attributes */
    new_region->b_uflags = ~VM_PROT_COW & old_region->b_uflags;
    new_region->b_mmu.vaddr = old_region->b_mmu.vaddr;
    /* num_pages already set */
    new_region->b_mmu.ap = old_region->b_mmu.ap;
    new_region->b_mmu.control = old_region->b_mmu.control;
    /* paddr already set */
    new_region->b_mmu.pt = old_region->b_mmu.pt;
    vm_updateusr_ap(new_region);

    /* Release "lock". */
    brelse(old_region);

    return new_region;
}
Exemplo n.º 11
0
/**
 * Read sector(s).
 * @param pdrv      is a (physical) drive nmuber to identify the drive.
 * @param buff      is a data buffer to store read data.
 * @param sector    is a sector address in LBA.
 * @param count     is the number of bytes to read.
 *
 */
DRESULT fatfs_disk_read(uint8_t pdrv, uint8_t * buff, DWORD sector,
                        unsigned int count)
{
    file_t * file;
    vnode_t * vnode;
    struct uio uio;
    ssize_t retval;

    if (pdrv >= configFATFS_MAX_MOUNTS || !fatfs_sb_arr[pdrv])
        return RES_PARERR;

    file = &fatfs_sb_arr[pdrv]->ff_devfile;
    vnode = file->vnode;

    retval = vnode->vnode_ops->lseek(file, sector, SEEK_SET);
    if (retval < 0) {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_ERR, "%s(): err %i\n", __func__, retval);
#endif
        return RES_ERROR;
    }

    uio_init_kbuf(&uio, buff, count);
    retval = file->vnode->vnode_ops->read(file, &uio, count);
    if (retval < 0) {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_ERR, "fatfs_disk_read(): err %i\n", retval);
#endif
        return RES_ERROR;
    }

    if (retval != (ssize_t)count) {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_WARN, "retval(%i) != count(%i)\n",
               (uint32_t)retval, (uint32_t)count);
#endif
        return RES_PARERR;
    }

    return 0;
}
Exemplo n.º 12
0
Arquivo: mbr.c Projeto: htchiang/zeke
/**
 * Check an MBR signature.
 */
static int check_signature(uint8_t * block_0)
{
    if ((block_0[0x1fe] != 0x55) || (block_0[0x1ff] != 0xaa)) {
        KERROR(KERROR_ERR,
               "MBR: Invalid signature (%x %x)\n",
               block_0[0x1fe], block_0[0x1ff]);

        return -ENOENT;
    }

    return 0;
}
Exemplo n.º 13
0
static int load_sections(struct proc_info * proc, file_t * file,
                         struct elf32_header * elfhdr, struct elf32_phdr * phdr,
                         uintptr_t rbase, uintptr_t * vaddr_base)
{
    int e_type = elfhdr->e_type;
    size_t phnum = elfhdr->e_phnum;

    for (size_t i = 0; i < phnum; i++) {
        struct buf * sect;
        int err;

        if (!(phdr[i].p_type == PT_LOAD && phdr[i].p_memsz != 0))
            continue;

        if ((err = load_section(&sect, file, rbase, &phdr[i])))
            return err;

        if (e_type == ET_EXEC && i < 2) {
            const int reg_nr = (i == 0) ? MM_CODE_REGION : MM_HEAP_REGION;

            if (i == 0)
                *vaddr_base = phdr[i].p_vaddr + rbase;
            err = vm_replace_region(proc, sect, reg_nr, VM_INSOP_MAP_REG);
            if (err) {
                KERROR(KERROR_ERR, "Failed to replace a region\n");
                return err;
            }
        } else {
            err = vm_insert_region(proc, sect, VM_INSOP_MAP_REG);
            if (err < 0) {
                KERROR(KERROR_ERR, "Failed to insert a region\n");
                return -1;
            }
        }
    }

    return 0;
}
Exemplo n.º 14
0
Arquivo: mbr.c Projeto: htchiang/zeke
static int read_block_0(uint8_t * block_0, file_t * file)
{
    struct uio uio;
    int ret;

    uio_init_kbuf(&uio, block_0, MBR_SIZE);

    /* Read the first 512 bytes. */
    ret = dev_read(file, &uio, MBR_SIZE);
    if (ret < 0) {
        KERROR(KERROR_ERR, "MBR: block_read failed (%i)\n", ret);

        return ret;
    } else if (ret != MBR_SIZE) {
        KERROR(KERROR_ERR,
               "MBR: Failed to read %d bytes, only %d bytes read\n",
               MBR_SIZE, ret);

        return -ENOENT;
    }

    return 0;
}
Exemplo n.º 15
0
Arquivo: ata.c Projeto: UIKit0/TSOS
/*
 * Polls a certain channel until the command either completes successfully, or
 * an abnormal condition happens.
 */
int ata_poll_ready(ata_driver_t *drv, uint8_t channel, bool advanced_check) {
	// Wait for drive to assert BSY
	for(int i = 0; i < 4; i++) {
		ata_reg_read(drv, channel, ATA_REG_ALTSTATUS);
	}

	unsigned int startCycles = kern_get_ticks();

	// Wait for the device to no longer be busy
	while(ata_reg_read(drv, channel, ATA_REG_STATUS) & ATA_SR_BSY) {
		// Allow requests to time out
		if(kern_get_ticks() - startCycles > ATA_WAIT_TIMEOUT) {
			KERROR("IDE: device took too long (%u ticks)", (unsigned int) (kern_get_ticks() - startCycles));			
			return ATA_ERR_TIMEOUT;
		}
	}

	//advanced_check = false;

 	// If set, we perform more in-depth checking
	if(advanced_check) {
		// Read status register
		uint8_t state = ata_reg_read(drv, channel, ATA_REG_STATUS);

		if(state & ATA_SR_ERR) { // Error executing command
			return 2;
		} else if(state & ATA_SR_DF) { // Device fault
			return 1;
		} else if(!(state & ATA_SR_DRQ)) { // BSY = 0; DF = 0; ERR = 0; DRQ = 0
			KERROR("IDE: No data after %u timer ticks", (unsigned int) (kern_get_ticks() - startCycles));
			return 3;
		}
	}

	// Hooray everything is happy
	return 0;
}
Exemplo n.º 16
0
vnode_t * fs_create_pseudofs_root(fs_t * newfs, int majornum)
{
    int err;
    vnode_t * rootnode;

    /*
     * We use a little trick here and create a temporary vnode that will be
     * destroyed after succesful mount.
     */

    rootnode = kzalloc(sizeof(vnode_t));
    if (!rootnode)
        return NULL;

    /* Temp root dir */
    rootnode->vn_next_mountpoint = rootnode;
    vrefset(rootnode, 1);
    mtx_init(&rootnode->vn_lock, VN_LOCK_TYPE, VN_LOCK_OPT);

    err = fs_mount(rootnode, "", "ramfs", 0, "", 1);
    if (err) {
        KERROR(KERROR_ERR,
               "Unable to create a pseudo fs root vnode for %s (%i)\n",
               newfs->fsname, err);

        return NULL;
    }
    rootnode = rootnode->vn_next_mountpoint;
    kfree(rootnode->vn_prev_mountpoint);
    rootnode->vn_prev_mountpoint = rootnode;
    rootnode->vn_next_mountpoint = rootnode;

    newfs->fs_majornum = majornum;
    newfs->sblist_head = rootnode->sb->fs->sblist_head;
    rootnode->sb->fs = newfs;

    rootnode->sb->vdev_id = DEV_MMTODEV(majornum, 0);

    return rootnode;
}
Exemplo n.º 17
0
// Opens a file, optionally creating it.
static fs_file_handle_t *fat32_file_open(void *superblock, char *path, fs_file_open_mode_t mode) {
	// Validate input
	if(path) {
		// Paths that don't start with a slash are invalid
		if(path[0] != '/') {
			#if PRINT_ERROR
			KERROR("Rejecting invalid path '%s'", path);
			#endif

			return NULL;
		}

		fs_fat32 *fs = (fs_fat32 *) superblock;
		fs_file_handle_t *handle = fs->get_file_handle(path, mode);

		// Set the file mode
		handle->mode = mode;

		return handle;
	}

	return NULL;
}
Exemplo n.º 18
0
static int clone_code_region(struct proc_info * new_proc,
                             struct proc_info * old_proc)
{
    struct buf * vm_reg_tmp;

    /* Copy code region pointer. */
    vm_reg_tmp = (*old_proc->mm.regions)[MM_CODE_REGION];
    if (!vm_reg_tmp) {
        KERROR(KERROR_ERR, "Old proc code region can't be null\n");
        return -EINVAL; /* Not allowed but this shouldn't happen. */
    }

    /*
     * In Zeke we always have at least one read-only code region by design so
     * we don't have to COW it or do anything fancy with it, instead we just
     * take a reference to the code region of the old process.
     */
    if (vm_reg_tmp->vm_ops->rref)
        vm_reg_tmp->vm_ops->rref(vm_reg_tmp);

    (*new_proc->mm.regions)[MM_CODE_REGION] = vm_reg_tmp;

    return 0;
}
Exemplo n.º 19
0
Arquivo: kinit.c Projeto: Zeke-OS/zeke
static void mount_tmp_rootfs(void)
{
    const char failed[] = "Failed to mount rootfs";
    vnode_t * tmp = NULL;
    struct proc_info * kernel_proc;
    int ret;

    kernel_proc = proc_ref(0);
    if (!kernel_proc) {
        panic(failed);
    }
    /* No need to keep the ref because it won't go away. */
    proc_unref(kernel_proc);

    /* Root dir */
    tmp = kzalloc_crit(sizeof(vnode_t));
    kernel_proc->croot = tmp;
    kernel_proc->croot->vn_next_mountpoint = kernel_proc->croot;
    kernel_proc->croot->vn_prev_mountpoint = kernel_proc->croot;
    mtx_init(&tmp->vn_lock, MTX_TYPE_SPIN, 0);
    vrefset(kernel_proc->croot, 2);

    ret = fs_mount(kernel_proc->croot, "", "ramfs", 0, "", 1);
    if (ret) {
        KERROR(KERROR_ERR, "%s : %i\n", failed, ret);
        goto out;
    }

    kernel_proc->croot->vn_next_mountpoint->vn_prev_mountpoint =
        kernel_proc->croot->vn_next_mountpoint;
    kernel_proc->croot = kernel_proc->croot->vn_next_mountpoint;
    kernel_proc->cwd = kernel_proc->croot;

out:
    kfree(tmp);
}
Exemplo n.º 20
0
static vnode_t * create_root(struct fatfs_sb * fatfs_sb)
{
    char * rootpath;
    long vn_hash;
    struct fatfs_inode * in;
    int err;

    rootpath = kzalloc(2);
    if (!rootpath)
        return NULL;

    vn_hash = hash32_str(rootpath, 0);
    err = create_inode(&in, fatfs_sb, rootpath, vn_hash,
                       O_DIRECTORY | O_RDWR);
    if (err) {
        KERROR(KERROR_ERR, "Failed to init a root vnode for fatfs (%d)\n", err);
        return NULL;
    }

    in->in_fpath = rootpath;

    vrefset(&in->in_vnode, 1);
    return &in->in_vnode;
}
Exemplo n.º 21
0
Arquivo: tty.c Projeto: Zeke-OS/zeke
struct tty * tty_alloc(const char * drv_name, dev_t dev_id,
                       const char * dev_name, size_t data_size)
{
    struct dev_info * dev;
    struct tty * tty;

    dev = kzalloc(sizeof(struct dev_info) + sizeof(struct tty) + data_size);
    if (!dev)
        return NULL;
    tty = (struct tty *)((uintptr_t)dev + sizeof(struct dev_info));

    dev->dev_id = dev_id;
    dev->drv_name = drv_name;
    strlcpy(dev->dev_name, dev_name, sizeof(dev->dev_name));
    dev->flags = DEV_FLAGS_MB_READ | DEV_FLAGS_WR_BT_MASK;
    dev->block_size = 1;
    dev->read = tty_read;
    dev->write = tty_write;
    dev->lseek = tty_lseek;
    dev->open_callback = tty_open_callback;
    dev->close_callback = tty_close_callback;
    dev->ioctl = tty_ioctl;
    dev->opt_data = tty;
    /*
     * Linux defaults:
     * tty->conf.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL |
     *                     ECHOKE | IEXTEN;
     */
    /*
     * TODO termios support
     * *supported now*
     * iflags: -
     * oflags: -
     * cflags: -
     * lfags: -
     */

    /* TODO Better winsize support. */
    tty->winsize = (struct winsize){
        .ws_row = 24,
        .ws_col = 80,
        .ws_xpixel = 0,
        .ws_ypixel = 0,
    };

    return tty;
}

void tty_free(struct tty * tty)
{
    struct dev_info * dev;

    dev = (struct dev_info *)((uintptr_t)tty - sizeof(struct dev_info));
    KASSERT(dev->opt_data == tty, "opt_data changed or invalid tty");

    kfree(dev);
}

struct dev_info * tty_get_dev(struct tty * tty)
{
    return (struct dev_info *)((uintptr_t)tty - sizeof(struct dev_info));
}

int make_ttydev(struct tty * tty)
{
    struct dev_info * dev;
    vnode_t * vn;

    dev = (struct dev_info *)((uintptr_t)tty - sizeof(struct dev_info));
    KASSERT(dev->opt_data == tty, "opt_data changed or invalid tty");

    if (tty->tty_vn != NULL) {
        KERROR(KERROR_ERR, "A device file is already created for this tty\n");
        return -EMLINK;
    }

    if (make_dev(dev, 0, 0, 0666, &vn)) {
        KERROR(KERROR_ERR, "Failed to make a tty dev.\n");
        return -ENODEV;
    }
    tty->tty_vn = vn;

    return 0;
}

void destroy_ttydev(struct tty * tty)
{
    struct dev_info * dev;

    dev = (struct dev_info *)((uintptr_t)tty - sizeof(struct dev_info));
    KASSERT(dev->opt_data == tty, "opt_data changed or invalid tty");

    destroy_dev(tty->tty_vn);
}

static ssize_t tty_read(struct dev_info * devnfo, off_t blkno, uint8_t * buf,
                        size_t bcount, int oflags)
{
    struct tty * tty = (struct tty *)devnfo->opt_data;

    KASSERT(tty, "opt_data should have a tty");

    return tty->read(tty, blkno, buf, bcount, oflags);
}

static ssize_t tty_write(struct dev_info * devnfo, off_t blkno, uint8_t * buf,
                         size_t bcount, int oflags)
{
    struct tty * tty = (struct tty *)devnfo->opt_data;
    ssize_t retval;

    KASSERT(tty, "opt_data should have a tty");

    retval = tty->write(tty, blkno, buf, bcount, oflags);
    if (retval > 0) {
        off_t n = tty->write_count + retval;
        tty->write_count = (n < 0) ? -n : n;
    }

    return retval;
}

static off_t tty_lseek(file_t * file, struct dev_info * devnfo, off_t offset,
                       int whence)
{
    struct tty * tty = (struct tty *)devnfo->opt_data;

    /*
     * Many unices will return the number of written characters if whence is
     * SEEK_SET and the file is a tty, and some will return -ESPIPE. We support
     * the write count.
     */
    if (whence == SEEK_SET)
        return tty->write_count;

    /*
     * Some drivers may use seek_pos as an index variable and on this kernel
     * we promise to return it if lseek is called with offset zero and SEEK_CUR
     * set as a whence.
     */
    if (offset == 0 && whence == SEEK_CUR)
        return file->seek_pos;

    return -ESPIPE;
}

static void tty_open_callback(struct proc_info * p, file_t * file,
                              struct dev_info * devnfo)
{
    struct tty * tty = (struct tty *)devnfo->opt_data;

    KASSERT(tty, "opt_data should have a tty");

    if (tty->open_callback)
        tty->open_callback(file, tty);
}

static void tty_close_callback(struct proc_info * p, file_t * file,
                               struct dev_info * devnfo)
{
    struct tty * tty = (struct tty *)devnfo->opt_data;

    KASSERT(tty, "opt_data should have a tty");

    if (tty->close_callback)
        tty->close_callback(file, tty);
}

static int tty_ioctl(struct dev_info * devnfo, uint32_t request,
                     void * arg, size_t arg_len)
{
    int err;
    struct tty * tty = (struct tty *)(devnfo->opt_data);

    if (!tty)
        return -EINVAL;

    /*
     * First call ioctl of the device driver since it may override some ioctls
     * defined here.
     */
    if (tty->ioctl) {
        err = tty->ioctl(devnfo, request, arg, arg_len);
        if (err == 0 || err != -EINVAL)
            return err;
    } /* otherwise check if we can handle it here */

    switch (request) {
    case IOCTL_GTERMIOS:
        if (arg_len < sizeof(struct termios))
            return -EINVAL;

        memcpy(arg, &(tty->conf), sizeof(struct termios));
        break;

    case IOCTL_STERMIOS:
        if (arg_len < sizeof(struct termios))
            return -EINVAL;

        err = priv_check(&curproc->cred, PRIV_TTY_SETA);
        if (err)
            return err;

        memcpy(&(tty->conf), arg, sizeof(struct termios));
        tty->setconf(&tty->conf);
        break;

    case IOCTL_TIOCGWINSZ:
        if (arg_len < sizeof(struct winsize))
            return -EINVAL;

        memcpy(arg, &(tty->winsize), sizeof(struct winsize));
        break;

    case IOCTL_TIOCSWINSZ:
        if (arg_len < sizeof(struct winsize))
            return -EINVAL;

        memcpy(&(tty->winsize), arg, sizeof(struct winsize));
        break;

    /*
     * This should be probably overriden and "optimized" in
     * the low level driver. Also if there is any muxing on
     * any lower level flush may do stupid things if done
     * by this function.
     */
    case IOCTL_TTYFLUSH:
        if (arg_len < sizeof(int)) {
            return -EINVAL;
        } else {
            int control = (int)arg;
            uint8_t buf[5];

            switch (control) {
            case TCIFLUSH:
                while (tty->read(tty, 0, buf, sizeof(buf), O_NONBLOCK) >= 0);
                break;
            default:
                return -EINVAL;
            }
        }
        break;

    case IOCTL_TCSBRK:
        /* NOP */
        break;

    default:
        return -EINVAL;
    }

    return 0;
}
Exemplo n.º 22
0
int _mtx_lock(mtx_t * mtx, char * whr)
#endif
{
    int ticket;
    const int sleep_mode = MTX_OPT(mtx, MTX_OPT_SLEEP);
#ifdef configLOCK_DEBUG
    unsigned deadlock_cnt = 0;
#endif

    if (mtx->mtx_type == MTX_TYPE_TICKET) {
        ticket = atomic_inc(&mtx->ticket.queue);
    }

    if (MTX_OPT(mtx, MTX_OPT_DINT)) {
        cpu_istate = get_interrupt_state();
        disable_interrupt();
    }

    while (1) {
#ifdef configLOCK_DEBUG
        /*
         * TODO Deadlock detection threshold should depend on lock type and
         *      current priorities.
         */
        if (++deadlock_cnt >= configSCHED_HZ * (configKLOCK_DLTHRES + 1)) {
            char * lwhr = (mtx->mtx_ldebug) ? mtx->mtx_ldebug : "?";

            KERROR(KERROR_DEBUG,
                   "Deadlock detected:\n%s WAITING\n%s LOCKED\n",
                   whr, lwhr);

            deadlock_cnt = 0;
        }
#endif

        if (sleep_mode && (current_thread->wait_tim == -2))
            return -EWOULDBLOCK;

        switch (mtx->mtx_type) {
        case MTX_TYPE_SPIN:
            if (!test_and_set((int *)(&mtx->mtx_lock)))
                goto out;
            break;

        case MTX_TYPE_TICKET:
            if (atomic_read(&mtx->ticket.dequeue) == ticket) {
                mtx->mtx_lock = 1;
                goto out;
            }

            thread_yield(THREAD_YIELD_LAZY);
            break;

        default:
            MTX_TYPE_NOTSUP();
            if (MTX_OPT(mtx, MTX_OPT_DINT))
                set_interrupt_state(cpu_istate);

            return -ENOTSUP;
        }

#ifdef configMP
        cpu_wfe(); /* Sleep until event. */
#endif
    }
out:

    /* Handle priority ceiling. */
    priceil_set(mtx);

#ifdef configLOCK_DEBUG
    mtx->mtx_ldebug = whr;
#endif

    return 0;
}
Exemplo n.º 23
0
Arquivo: mbr.c Projeto: htchiang/zeke
int mbr_register(int fd, int * part_count)
{
    file_t * file;
    vnode_t * parent_vnode;
    struct dev_info * parent;
    uint8_t * block_0 = NULL;
    int parts = 0;
    int retval = 0;

#ifdef configMBR_DEBUG
    KERROR(KERROR_DEBUG, "%s(fd: %d, part_count: %p)\n", __func__,
           fd, part_count);
#endif

    file = fs_fildes_ref(curproc->files, fd, 1);

    parent_vnode = file->vnode;
    parent = (struct dev_info *)parent_vnode->vn_specinfo;
    if (!(S_ISBLK(parent_vnode->vn_mode) || S_ISCHR(parent_vnode->vn_mode))) {
        KERROR(KERROR_ERR, "MBR: not a device\n");

        retval = -ENODEV;
        goto fail;
    }

    /* Check the validity of the parent device. */
    if (!parent) {
        KERROR(KERROR_ERR, "MBR: invalid parent device\n");

        retval = -ENODEV;
        goto fail;
    }

    block_0 = kmalloc(MBR_SIZE);
    if (!block_0) {
        retval = -ENOMEM;
        goto fail;
    }

#ifdef configMBR_DEBUG
    KERROR(KERROR_DEBUG,
           "MBR: reading block 0 from device %s\n",
           parent->dev_name);
#endif

    retval = read_block_0(block_0, file);
    if (retval)
        goto fail;
    retval = check_signature(block_0);
    if (retval)
        goto fail;

#ifdef configMBR_DEBUG
    KERROR(KERROR_DEBUG,
             "MBR: found valid MBR on device %s\n", parent->dev_name);
#endif

    /*
     * If parent block size is not MBR_SIZE, we have to coerce start_block
     * and blocks to fit.
     */
    if (parent->block_size < MBR_SIZE) {
        /* We do not support parent device block sizes < 512 */
        KERROR(KERROR_ERR,
                 "MBR: block size of %s is too small (%i)\n",
                 parent->dev_name, parent->block_size);

        retval = -ENOTSUP;
        goto fail;
    }

    uint32_t block_size_adjust = parent->block_size / MBR_SIZE;
    if (parent->block_size % MBR_SIZE) {
        /*
         * We do not support parent device block sizes that are not
         * multiples of 512.
         */
        KERROR(KERROR_ERR,
               "MBR: block size of %s is not a multiple of 512 (%i)\n",
               parent->dev_name, parent->block_size);

        retval = -ENOTSUP;
        goto fail;
    }

#ifdef configMBR_DEBUG
    if (block_size_adjust > 1) {
        KERROR(KERROR_DEBUG, "MBR: block_size_adjust: %i\n",
                 block_size_adjust);
    }
#endif

    int major_num = DEV_MAJOR(parent->dev_id) + 1;
    for (size_t i = 0; i < 4; i++) {
        size_t p_offset = 0x1be + (i * 0x10);
        struct mbr_dev * d;

        if (block_0[p_offset + 4] == 0x00) {
            /* Invalid partition */
            continue;
        }

        d = kzalloc(sizeof(struct mbr_dev));
        if (!d) {
            KERROR(KERROR_ERR, "MBR: Out of memory");

            retval = -ENOMEM;
            break;
        }

        d->dev.dev_id = DEV_MMTODEV(major_num, mbr_dev_count);
        d->dev.drv_name = driver_name;
        ksprintf(d->dev.dev_name, sizeof(d->dev.dev_name), "%sp%u",
                 parent->dev_name, i);
        d->dev.read = mbr_read;
        d->dev.write = (parent->write) ? mbr_write : NULL;
        d->dev.block_size = parent->block_size;
        d->dev.flags = parent->flags;
        d->part_no = i;
        d->part_id = block_0[p_offset + 4];
        d->start_block = read_word(block_0, p_offset + 8);
        d->blocks = read_word(block_0, p_offset + 12);
        d->parent = parent;

        /* Adjust start_block and blocks to the parent block size */
        if (d->start_block % block_size_adjust) {
            KERROR(KERROR_ERR,
                   "MBR: partition number %i on %s does not start on a block "
                   "boundary (%i).\n",
                   d->part_no, parent->dev_name, d->start_block);

            retval = -EFAULT;
            goto fail;
        }
        d->start_block /= block_size_adjust;

        if (d->blocks % block_size_adjust) {
            KERROR(KERROR_ERR,
                   "MBR: partition number %i on %s does not have a length "
                   "that is an exact multiple of the block length (%i).\n",
                   d->part_no, parent->dev_name, d->start_block);

            retval = -EFAULT;
            goto fail;
        }
        d->blocks /= block_size_adjust;
        d->dev.num_blocks = d->blocks;

#ifdef configMBR_DEBUG
        KERROR(KERROR_DEBUG,
               "MBR: partition number %i (%s) of type %x, "
               "start sector %u, sector count %u, p_offset %03x\n",
               d->part_no, d->dev.dev_name, d->part_id,
               d->start_block, d->blocks, p_offset);
#endif

        make_dev(&d->dev, 0, 0, 0666, NULL);
        mbr_dev_count++;
        parts++;

        /* Register the fs */
        //register_fs__((struct dev_info *)d, d->part_id);
        /* TODO Register the fs dev with devfs */
    }

    KERROR(KERROR_INFO, "MBR: found total of %i partition(s)\n",
           parts);

fail:
    kfree(block_0);
    fs_fildes_ref(curproc->files, fd, -1);

    if (retval != 0) {
        KERROR(KERROR_ERR, "MBR registration failed on device: \"%s\"\n",
               parent->dev_name);
    }

    return retval;
}
Exemplo n.º 24
0
int fatfs_stat(vnode_t * vnode, struct stat * buf)
{
    struct fatfs_sb * ffsb = get_ffsb_of_sb(vnode->sb);
    struct fatfs_inode * in = get_inode_of_vnode(vnode);
    FILINFO fno;
    struct stat mp_stat = { .st_uid = 0, .st_gid = 0 };
    size_t blksize = ffsb->ff_fs.ssize;
    int err;

    memset(&fno, 0, sizeof(fno));

    err = get_mp_stat(vnode, &mp_stat);
    if (err) {
        if (err == -EINPROGRESS) {
#ifdef configFATFS_DEBUG
            KERROR(KERROR_WARN, "vnode->sb->mountpoint should be set\n");
#endif
        } else {
#ifdef configFATFS_DEBUG
            KERROR(KERROR_WARN,
                   "get_mp_stat() returned error (%d)\n",
                   err);
#endif

            return err;
        }
    }

    /* Can't stat FAT root */
    if (vnode == vnode->sb->root) {
        memcpy(buf, &mp_stat, sizeof(struct stat));

        return 0;
    }

    err = f_stat(&ffsb->ff_fs, in->in_fpath, &fno);
    if (err) {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG,
                 "f_stat(fs %p, fpath \"%s\", fno %p) failed\n",
                 &ffsb->ff_fs, in->in_fpath, &fno);
#endif
        return fresult2errno(err);
    }

    buf->st_dev = vnode->sb->vdev_id;
    buf->st_ino = vnode->vn_num;
    buf->st_mode = vnode->vn_mode;
    buf->st_nlink = 1; /* Always one link on FAT. */
    buf->st_uid = mp_stat.st_uid;
    buf->st_gid = mp_stat.st_gid;
    buf->st_size = fno.fsize;
    /* TODO Times */
#if 0
    buf->st_atim;
    buf->st_mtim;
    buf->st_ctim;
    buf->st_birthtime;
#endif
    buf->st_flags = fattrib2uflags(fno.fattrib);
    buf->st_blksize = blksize;
    buf->st_blocks = fno.fsize / blksize + 1; /* Best guess. */

    return 0;
}

int fatfs_chmod(vnode_t * vnode, mode_t mode)
{
    struct fatfs_sb * ffsb = get_ffsb_of_sb(vnode->sb);
    struct fatfs_inode * in = get_inode_of_vnode(vnode);
    uint8_t attr = 0;
    const uint8_t mask = AM_RDO;
    int err;

    if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
        attr |= AM_RDO;

    err = fresult2errno(f_chmod(&ffsb->ff_fs, in->in_fpath, attr, mask));
    if (!err)
        vnode->vn_mode = mode;

    return err;
}

/*
 * Note: Thre is practically two ways to set AM_RDO, either
 * by using chmod() or by this chflags().
 */
int fatfs_chflags(vnode_t * vnode, fflags_t flags)
{
    struct fatfs_sb * ffsb = get_ffsb_of_sb(vnode->sb);
    struct fatfs_inode * in = get_inode_of_vnode(vnode);
    uint8_t attr = 0;
    const uint8_t mask = AM_RDO | AM_ARC | AM_SYS | AM_HID;
    FRESULT fresult;

    if (flags & UF_SYSTEM)
        attr |= AM_SYS;
    if (flags & UF_ARCHIVE)
        attr |= AM_ARC;
    if (flags & UF_READONLY)
        attr |= AM_RDO;
    if (flags & UF_HIDDEN)
        attr |= AM_HID;

    fresult = f_chmod(&ffsb->ff_fs, in->in_fpath, attr, mask);

    return fresult2errno(fresult);
}

/**
 * Initialize fatfs vnode data.
 * @param vnode is the target vnode to be initialized.
 */
static void init_fatfs_vnode(vnode_t * vnode, ino_t inum, mode_t mode,
                             long vn_hash, struct fs_superblock * sb)
{
    struct stat stat;

#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG,
           "init_fatfs_vnode(vnode %p, inum %l, mode %o, vn_hash %u, sb %p)\n",
           vnode, (uint64_t)inum, mode, (uint32_t)vn_hash, sb);
#endif

    fs_vnode_init(vnode, inum, sb, &fatfs_vnode_ops);

    vnode->vn_hash = vn_hash;

    if (S_ISDIR(mode))
        mode |= S_IRWXU | S_IXGRP | S_IXOTH;
    vnode->vn_mode = mode | S_IRUSR | S_IRGRP | S_IROTH;
    fatfs_stat(vnode, &stat);
    vnode->vn_len = stat.st_size;
    if ((stat.st_flags & UF_READONLY) == 0)
        vnode->vn_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
}

/**
 * Get mountpoint stat.
 */
static int get_mp_stat(vnode_t * vnode, struct stat * st)
{
     struct fs_superblock * sb;
     vnode_t * mp;

#ifdef configFATFS_DEBUG
    KASSERT(vnode, "Vnode was given");
    KASSERT(vnode->sb, "Superblock is set");
#endif

    sb = vnode->sb;
    mp = sb->mountpoint;

    if (!mp) {
        /* We are probably mounting and mountpoint is not yet set. */
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "mp not set\n");
#endif
        return -EINPROGRESS;
    }

#ifdef configFATFS_DEBUG
    KASSERT(mp->vnode_ops->stat, "stat() is defined");
#endif

    return mp->vnode_ops->stat(mp, st);
}

static int fresult2errno(int fresult)
{
    switch (fresult) {
    case FR_DISK_ERR:
    case FR_INVALID_OBJECT:
    case FR_INT_ERR:
        return -EIO;
    case FR_NOT_ENABLED:
        return -ENODEV;
    case FR_NO_FILESYSTEM:
        return -ENXIO;
    case FR_NO_FILE:
    case FR_NO_PATH:
        return -ENOENT;
    case FR_DENIED:
        return -EACCES;
    case FR_EXIST:
        return -EEXIST;
    case FR_WRITE_PROTECTED:
        return -EPERM;
    case FR_NOT_READY:
        return -EBUSY;
    case FR_INVALID_NAME:
    case FR_INVALID_DRIVE:
    case FR_MKFS_ABORTED:
    case FR_INVALID_PARAMETER:
        return -EINVAL;
    case FR_TIMEOUT:
        return -EWOULDBLOCK;
    case FR_NOT_ENOUGH_CORE:
        return -ENOMEM;
    case FR_TOO_MANY_OPEN_FILES:
        return -ENFILE;
    default:
        if (fresult != 0) /* Unknown error */
            return -EIO;
    }

    return 0;
}
Exemplo n.º 25
0
/**
 * ATAG scanner.
 * @note This function is called before intializers.
 */
void atag_scan(uint32_t fw, uint32_t mtype, uint32_t * atag_addr)
{
    uint32_t * atags;
    char msg[120];

    sysinfo.mtype = mtype;

    if (*atag_addr != ATAG_CORE) {
        KERROR(KERROR_WARN, "No ATAGs!");
        return;
    }

    for (atags = atag_addr; atags < (uint32_t *)0x8000; atags += 1) {
        switch (atags[1]) {
        case ATAG_CORE:
            ksprintf(msg, sizeof(msg),
                    "[ATAG_CORE] flags: %x, page size: %u, rootdev: %u\n",
                    atags[2], atags[3], atags[4]);
            KERROR(KERROR_INFO, msg);

            atags += atags[0]-1;
            break;
        case ATAG_MEM:
            ksprintf(msg, sizeof(msg),
                    "[ATAG_MEM] size: %x, start: %x\n",
                    atags[2], atags[3]);
            KERROR(KERROR_INFO, msg);

            atags += atags[0]-1;

            sysinfo.mem.size = (size_t)atags[2];
            sysinfo.mem.start = (size_t)atags[3];
            break;
        case ATAG_VIDEOTEXT:
            atags += atags[0]-1;
            break;
        case ATAG_RAMDISK:
            atags += atags[0]-1;
            break;
        case ATAG_INITRD2:
            atags += atags[0]-1;
            break;
        case ATAG_SERIAL:
            atags += atags[0]-1;
            break;
        case ATAG_REVISION:
            atags += atags[0]-1;
            break;
        case ATAG_VIDEOLFB:
            atags += atags[0]-1;
            break;
        case ATAG_CMDLINE:
            atags += 2;

            ksprintf(msg, sizeof(msg),
                    "[ATAG_CMDLINE] : %s\n", (char *)atags);
            KERROR(KERROR_INFO, msg);

            atags += atags[0]-1;
            break;
        default:
            break;
        }
    }
}
Exemplo n.º 26
0
/**
 * Lookup for a vnode (file/dir) in FatFs.
 * First lookup form vfs_hash and if not found then read it from ff which will
 * probably read it via devfs interface. After the vnode has been created it
 * will be added to the vfs hashmap. In ff terminology all files and directories
 * that are in hashmap are also open on a file/dir handle, thus we'll have to
 * make sure we don't have too many vnodes in cache that have no references, to
 * avoid hitting any ff hard limits.
 */
static int fatfs_lookup(vnode_t * dir, const char * name, vnode_t ** result)
{
    struct fatfs_inode * indir = get_inode_of_vnode(dir);
    struct fatfs_sb * sb = get_ffsb_of_sb(dir->sb);
    char * in_fpath;
    long vn_hash;
    struct vnode * vn = NULL;
    int err, retval = 0;

    KASSERT(dir != NULL, "dir must be set");

    /* Format full path */
    in_fpath = format_fpath(indir, name);
    if (!in_fpath)
        return -ENOMEM;

    /*
     * Emulate . and ..
     */
    if (name[0] == '.' && name[1] != '.') {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "Lookup emulating \".\"\n");
#endif
        (void)vref(dir);
        *result = dir;

        kfree(in_fpath);
        return 0;
    } else if (name[0] == '.' && name[1] == '.' && name[2] != '.') {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "Lookup emulating \"..\"\n");
#endif
        if (VN_IS_FSROOT(dir)) {
            *result = dir->sb->mountpoint;

            kfree(in_fpath);
            return -EDOM;
        } else {
            size_t i = strlenn(in_fpath, NAME_MAX) - 4;

            while (in_fpath[i] != '/') {
                i--;
            }
            in_fpath[i] = '\0';
        }
    }

    /*
     * Lookup from vfs_hash
     */
    vn_hash = hash32_str(in_fpath, 0);
    err = vfs_hash_get(
            dir->sb,        /* FS superblock */
            vn_hash,        /* Hash */
            &vn,            /* Retval */
            fatfs_vncmp,    /* Comparator */
            in_fpath        /* Compared fpath */
          );
    if (err) {
        retval = -EIO;
        goto fail;
    }
    if (vn) { /* found it in vfs_hash */
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "vn found in vfs_hash (%p)\n", vn);
#endif

        *result = vn;
        retval = 0;
    } else { /* not cached */
        struct fatfs_inode * in;

#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "vn not in vfs_hash\n");
#endif

        /*
         * Create a inode and fetch data from the device.
         * This also vrefs.
         */
        err = create_inode(&in, sb, in_fpath, vn_hash, O_RDWR);
        if (err) {
            retval = err;
            goto fail;
        }

        in_fpath = NULL; /* shall not be freed. */
        *result = &in->in_vnode;
        retval = 0;
    }

fail:
    kfree(in_fpath);
    return retval;
}
Exemplo n.º 27
0
/**
 * Page table mapper init function.
 * @note This function should be called by mmu init.
 */
void ptmapper_init(void)
{
    SUBSYS_INIT();
    KERROR(KERROR_INFO, "ptmapper init started");

    /* Allocate memory for mmu_pagetable_master */
    if (ptmapper_alloc(&mmu_pagetable_master)) {
        panic("Can't allocate memory for master page table.");
    }

    mmu_pagetable_system.master_pt_addr = mmu_pagetable_master.master_pt_addr;
    if (ptmapper_alloc(&mmu_pagetable_system)) {
        panic("Can't allocate memory for system page table.");
    }

    /* Initialize system page tables */
    mmu_init_pagetable(&mmu_pagetable_master);
    mmu_init_pagetable(&mmu_pagetable_system);

    /* Init regions */
    /* Kernel ro region */
    mmu_region_kernel.num_pages  = MMU_PAGE_CNT_BY_RANGE(
            MMU_VADDR_KERNEL_START, (intptr_t)(&_rodata_end) - 1,
            MMU_PGSIZE_COARSE);
    /* Kernel rw data region */
    mmu_region_kdata.vaddr      = (intptr_t)(&_data_start);
    mmu_region_kdata.num_pages  = MMU_PAGE_CNT_BY_RANGE(
            (intptr_t)(&_data_start), MMU_VADDR_KERNEL_END,
            MMU_PGSIZE_COARSE);
    mmu_region_kdata.paddr      = (intptr_t)(&_data_start);

    /* Fill page tables with translations & attributes */
    {
#if configDEBUG >= KERROR_DEBUG
        char buf[80];
        const char str_type[2][9] = {"sections", "pages"};
#define PRINTMAPREG(region) \
        ksprintf(buf, sizeof(buf), "Mapped %s: %u %s", \
            #region, region.num_pages, \
            (region.pt->type == MMU_PTT_MASTER) ? \
                str_type[0] : str_type[1]); \
        KERROR(KERROR_DEBUG, buf);
#else
#define PRINTMAPREG(region)
#endif
#define MAP_REGION(reg) \
        mmu_map_region(&reg); \
        PRINTMAPREG(reg)

        //MAP_REGION(mmu_region_tkstack);
        MAP_REGION(mmu_region_kstack);
        MAP_REGION(mmu_region_kernel);
        MAP_REGION(mmu_region_kdata);
        MAP_REGION(mmu_region_page_tables);
        MAP_REGION(mmu_region_rpihw);
#undef MAP_REGION
#undef PRINTMAPREG
    }

    /* Copy system page table to vm version of it, this is the only easy way to
     * solve some issues now. TODO Maybe we'd like to do some major refactoring
     * some day. */
    vm_pagetable_system.pt = mmu_pagetable_system;
    vm_pagetable_system.linkcount = 1;

    /* Activate page tables */
    mmu_attach_pagetable(&mmu_pagetable_master); /* Load L1 TTB */
#if configDEBUG >= KERROR_DEBUG
    KERROR(KERROR_DEBUG, "Attached TTB mmu_pagetable_master");
#endif
    mmu_attach_pagetable(&mmu_pagetable_system); /* Add L2 pte into L1 mpt */
#if configDEBUG >= KERROR_DEBUG
    KERROR(KERROR_DEBUG, "Attached mmu_pagetable_system");
#endif

    SUBSYS_INITFINI("ptmapper OK");
}
Exemplo n.º 28
0
/**
 * Create a inode.
 * @param fpath won't be duplicated.
 * @param oflags O_CREAT, O_DIRECTORY, O_RDONLY, O_WRONLY and O_RDWR
 *               currently supported.
 *               O_WRONLY/O_RDWR creates in write mode if possible, so this
 *               should be always verified with stat.
 */
static int create_inode(struct fatfs_inode ** result, struct fatfs_sb * sb,
                        char * fpath, long vn_hash, int oflags)
{
    struct fatfs_inode * in = NULL;
    FILINFO fno;
    vnode_t * vn;
    vnode_t * xvp;
    mode_t vn_mode;
    ino_t inum;
    int err = 0, retval = 0;

#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG, "create_inode(fpath \"%s\", vn_hash %u)\n",
             fpath, (uint32_t)vn_hash);
#endif

    in = kzalloc(sizeof(struct fatfs_inode));
    if (!in) {
        retval = -ENOMEM;
        goto fail;
    }
    in->in_fpath = fpath;
    vn = &in->in_vnode;

    in->open_count = ATOMIC_INIT(0);

    memset(&fno, 0, sizeof(fno));

    if (oflags & O_DIRECTORY) {
        /* O_DIRECTORY was specified. */
        /* TODO Maybe get mp stat? */
        fno.fattrib = AM_DIR;
    } else if (oflags & O_CREAT) {
        if (sb->sb.mode_flags & MNT_RDONLY)
            return -EROFS;
    } else {
        err = f_stat(&sb->ff_fs, fpath, &fno);
        if (err) {
            retval = fresult2errno(err);
            goto fail;
        }
    }

    /* Try open */
    if (fno.fattrib & AM_DIR) {
        /* it's a directory */
        vn_mode = S_IFDIR;
        err = f_opendir(&in->dp, &sb->ff_fs, in->in_fpath);
        if (err) {
#ifdef configFATFS_DEBUG
            KERROR(KERROR_DEBUG, "Can't open a dir (err: %d)\n", err);
#endif
            retval = fresult2errno(err);
            goto fail;
        }
        inum = in->dp.ino;
    } else {
        /* it's a file */
        unsigned char fomode = 0;

        fomode |= (oflags & O_CREAT) ? FA_OPEN_ALWAYS : FA_OPEN_EXISTING;
        /* The kernel should always have RW if possible. */
        if (sb->sb.mode_flags & MNT_RDONLY) {
            fomode |= FA_READ;
        } else {
            fomode |= FA_READ | FA_WRITE;
        }

        vn_mode = S_IFREG;
        err = f_open(&in->fp, &sb->ff_fs, in->in_fpath, fomode);
        if (err) {
#ifdef configFATFS_DEBUG
            KERROR(KERROR_DEBUG, "Can't open a file (err: %d)\n", err);
#endif
            retval = fresult2errno(err);
            goto fail;
        }
        inum = in->fp.ino;
    }

#ifdef configFATFS_DEBUG
    if (oflags & O_CREAT)
        KERROR(KERROR_DEBUG, "ff: Create & open ok\n");
    else
        KERROR(KERROR_DEBUG, "ff: Open ok\n");
#endif

    init_fatfs_vnode(vn, inum, vn_mode, vn_hash, &(sb->sb));

    /* Insert to the cache */
    err = vfs_hash_insert(vn, vn_hash, &xvp, fatfs_vncmp, fpath);
    if (err) {
        retval = -ENOMEM;
        goto fail;
    }
    if (xvp) {
        /* TODO No idea what to do now */
        KERROR(KERROR_WARN,
               "create_inode(): Found it during insert: \"%s\"\n",
               fpath);
    }

#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG, "create_inode(): ok\n");
#endif

    *result = in;
    vrefset(vn, 1); /* Make ref for the caller. */
    return 0;
fail:
#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG, "create_inode(): retval %i\n", retval);
#endif

    kfree(in);
    return retval;
}
Exemplo n.º 29
0
/**
 * Mount a new fatfs.
 * @param mode      mount flags.
 * @param param     contains optional mount parameters.
 * @param parm_len  length of param string.
 * @param[out] sb   Returns the superblock of the new mount.
 * @return error code, -errno.
 */
static int fatfs_mount(const char * source, uint32_t mode,
                       const char * parm, int parm_len,
                       struct fs_superblock ** sb)
{
    static dev_t fatfs_vdev_minor;
    struct fatfs_sb * fatfs_sb = NULL;
    vnode_t * vndev;
    char pdrv;
    int err, retval = 0;

    /* Get device vnode */
    err = lookup_vnode(&vndev, curproc->croot, source, 0);
    if (err) {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "fatfs source not found\n");
#endif
        return err;
    }
    if (!S_ISBLK(vndev->vn_mode))
        return -ENOTBLK;

    /* Allocate superblock */
    fatfs_sb = kzalloc(sizeof(struct fatfs_sb));
    if (!fatfs_sb)
        return -ENOMEM;

    fs_fildes_set(&fatfs_sb->ff_devfile, vndev, O_RDWR);
    fatfs_sb->sb.vdev_id = DEV_MMTODEV(VDEV_MJNR_FATFS, fatfs_vdev_minor++);

    /* Insert sb to fatfs_sb_arr lookup array */
    fatfs_sb_arr[DEV_MINOR(fatfs_sb->sb.vdev_id)] = fatfs_sb;

    /* Mount */
    pdrv = (char)DEV_MINOR(fatfs_sb->sb.vdev_id);
    err = f_mount(&fatfs_sb->ff_fs, 0);
    if (err) {
#ifdef configFATFS_DEBUG
        KERROR(KERROR_DEBUG, "Can't init a work area for FAT (%d)\n", err);
#endif
        retval = fresult2errno(err);
        goto fail;
    }
#ifdef configFATFS_DEBUG
    KERROR(KERROR_DEBUG, "Initialized a work area for FAT\n");
#endif

#if (_FS_NOFSINFO == 0) /* Commit full scan of free clusters */
    DWORD nclst;

    f_getfree(&fatfs_sb->ff_fs, &nclst);
#endif

    /* Init super block */
    fs_init_superblock(&fatfs_sb->sb, &fatfs_fs);
    /* TODO Detect if target dev is rdonly */
    fatfs_sb->sb.mode_flags = mode;
    fatfs_sb->sb.root = create_root(fatfs_sb);
    fatfs_sb->sb.sb_dev = vndev;
    fatfs_sb->sb.sb_hashseed = fatfs_sb->sb.vdev_id;
    /* Function pointers to superblock methods */
    fatfs_sb->sb.get_vnode = NULL; /* Not implemented for FAT. */
    fatfs_sb->sb.delete_vnode = fatfs_delete_vnode;
    fatfs_sb->sb.umount = NULL;

    if (!fatfs_sb->sb.root) {
        KERROR(KERROR_ERR, "Root of fatfs not found\n");

        return -EIO;
    }
    fs_insert_superblock(&fatfs_fs, &fatfs_sb->sb);

fail:
    if (retval) {
        fatfs_sb_arr[DEV_MINOR(fatfs_sb->sb.vdev_id)] = NULL;
        kfree(fatfs_sb);
    }

    *sb = &fatfs_sb->sb;
    return retval;
}
Exemplo n.º 30
0
Arquivo: fb.c Projeto: Zeke-OS/zeke
static void fb_mm_free_callback(struct kobj * obj)
{
    struct buf * bp = containerof(obj, struct buf, b_obj);

    KERROR(KERROR_ERR, "FB buf object (%p) freed!\n", bp);
}