Use readstr() for #device text buffers
[akaros.git] / kern / drivers / dev / kfs.c
index 2419fba..aedf7a9 100644 (file)
@@ -224,8 +224,8 @@ static int add_kfs_entry(struct cpio_bin_hdr *c_bhdr, void *cb_arg)
                break;
        default:
                cclose(c);
-               printk("Unknown file type %d in the CPIO!",
-                      c_bhdr->c_mode & CPIO_FILE_MASK);
+               warn("Unknown file type %d in the CPIO!",
+                    c_bhdr->c_mode & CPIO_FILE_MASK);
                return -1;
        }
        if (!c)
@@ -241,20 +241,44 @@ static int add_kfs_entry(struct cpio_bin_hdr *c_bhdr, void *cb_arg)
        return 0;
 }
 
-static void kfs_extract_cpio(void)
+struct cpio_info {
+       void *base;
+       size_t sz;
+};
+
+static void kfs_get_cpio_info(struct cpio_info *ci)
 {
        extern uint8_t _binary_obj_kern_initramfs_cpio_size[];
        extern uint8_t _binary_obj_kern_initramfs_cpio_start[];
 
-       void *cpio_base = (void*)_binary_obj_kern_initramfs_cpio_start;
-       size_t cpio_sz = (size_t)_binary_obj_kern_initramfs_cpio_size;
+       ci->base = (void*)_binary_obj_kern_initramfs_cpio_start;
+       ci->sz = (size_t)_binary_obj_kern_initramfs_cpio_size;
+}
 
-       parse_cpio_entries(cpio_base, cpio_sz, add_kfs_entry, kfs.tfs.root);
+static void kfs_extract_cpio(struct cpio_info *ci)
+{
+       parse_cpio_entries(ci->base, ci->sz, add_kfs_entry, kfs.tfs.root);
+}
+
+static void kfs_free_cpio(struct cpio_info *ci)
+{
+       void *base = ci->base;
+       size_t sz = ci->sz;
+
+       /* The base arena requires page aligned, page sized segments. */
+       sz -= ROUNDUP(base, PGSIZE) - base;
+       sz = ROUNDDOWN(sz, PGSIZE);
+       base = ROUNDUP(base, PGSIZE);
+       /* Careful - the CPIO is part of the kernel blob and a code address. */
+       base = KBASEADDR(base);
+       printk("Freeing %d MB of CPIO RAM\n", sz >> 20);
+       arena_add(base_arena, base, sz, MEM_WAIT);
 }
 
 static void kfs_init(void)
 {
        struct tree_filesystem *tfs = &kfs.tfs;
+       struct cpio_info ci[1];
 
        /* This gives us one ref on tfs->root. */
        tfs_init(tfs);
@@ -264,7 +288,9 @@ static void kfs_init(void)
        __kfs_tf_init(tfs->root, &kfs_devtab - devtab, 0, &eve, DMDIR | 0777);
        /* Other devices might want to create things like kthreads that run the LRU
         * pruner or PM sweeper. */
-       kfs_extract_cpio();
+       kfs_get_cpio_info(ci);
+       kfs_extract_cpio(ci);
+       kfs_free_cpio(ci);
        /* This has another kref.  Note that each attach gets a ref and each new
         * process gets a ref. */
        kern_slash = tree_file_alloc_chan(kfs.tfs.root, &kfs_devtab, "/");
@@ -276,6 +302,18 @@ static struct chan *kfs_attach(char *spec)
        return tree_file_alloc_chan(kfs.tfs.root, &kfs_devtab, "#kfs");
 }
 
+static unsigned long kfs_chan_ctl(struct chan *c, int op, unsigned long a1,
+                                  unsigned long a2, unsigned long a3,
+                                  unsigned long a4)
+{
+       switch (op) {
+       case CCTL_SYNC:
+               return 0;
+       default:
+               return tree_chan_ctl(c, op, a1, a2, a3, a4);
+       }
+}
+
 struct dev kfs_devtab __devtab = {
        .name = "kfs",
        .reset = devreset,
@@ -292,8 +330,10 @@ struct dev kfs_devtab __devtab = {
        .write = tree_chan_write,
        .bwrite = devbwrite,
        .remove = tree_chan_remove,
+       .rename = tree_chan_rename,
        .wstat = tree_chan_wstat,
        .power = devpower,
        .chaninfo = devchaninfo,
        .mmap = tree_chan_mmap,
+       .chan_ctl = kfs_chan_ctl,
 };