/* * 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; }
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; }
/** * 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; }
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; }