Ejemplo n.º 1
0
Archivo: fb.c Proyecto: 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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
Archivo: mbr.c Proyecto: 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;
}