1 #ifndef __XEN_HYPFS_H__
2 #define __XEN_HYPFS_H__
3 
4 #ifdef CONFIG_HYPFS
5 #include <xen/lib.h>
6 #include <xen/list.h>
7 #include <xen/string.h>
8 #include <public/hypfs.h>
9 
10 struct hypfs_entry_leaf;
11 struct hypfs_entry_dir;
12 struct hypfs_entry;
13 
14 /*
15  * Per-node callbacks:
16  *
17  * The callbacks are always called with the hypfs lock held. In case multiple
18  * callbacks are called for a single operation the lock is held across all
19  * those callbacks.
20  *
21  * The read() callback is used to return the contents of a node (either
22  * directory or leaf). It is NOT used to get directory entries during traversal
23  * of the tree.
24  *
25  * The write() callback is used to modify the contents of a node. Writing
26  * directories is not supported (this means all nodes are added at boot time).
27  *
28  * getsize() is called in two cases:
29  * - when reading a node (directory or leaf) for filling in the size of the
30  *   node into the returned direntry
31  * - when reading a directory for each node in this directory
32  *
33  * findentry() is called for traversing a path from the root node to a node
34  * for all nodes on that path excluding the final node (so for looking up
35  * "/a/b/c" findentry() will be called for "/", "/a", and "/a/b").
36  */
37 struct hypfs_funcs {
38     const struct hypfs_entry *(*enter)(const struct hypfs_entry *entry);
39     void (*exit)(const struct hypfs_entry *entry);
40     int (*read)(const struct hypfs_entry *entry,
41                 XEN_GUEST_HANDLE_PARAM(void) uaddr);
42     int (*write)(struct hypfs_entry_leaf *leaf,
43                  XEN_GUEST_HANDLE_PARAM(const_void) uaddr, unsigned int ulen);
44     unsigned int (*getsize)(const struct hypfs_entry *entry);
45     struct hypfs_entry *(*findentry)(const struct hypfs_entry_dir *dir,
46                                      const char *name, unsigned int name_len);
47 };
48 
49 extern const struct hypfs_funcs hypfs_dir_funcs;
50 extern const struct hypfs_funcs hypfs_leaf_ro_funcs;
51 extern const struct hypfs_funcs hypfs_leaf_wr_funcs;
52 extern const struct hypfs_funcs hypfs_bool_wr_funcs;
53 extern const struct hypfs_funcs hypfs_custom_wr_funcs;
54 
55 struct hypfs_entry {
56     unsigned short type;
57     unsigned short encoding;
58     unsigned int size;
59     unsigned int max_size;
60     const char *name;
61     struct hypfs_entry *parent;
62     struct list_head list;
63     const struct hypfs_funcs *funcs;
64 };
65 
66 struct hypfs_entry_leaf {
67     struct hypfs_entry e;
68     union {
69         const void *content;
70         void *write_ptr;
71     } u;
72 };
73 
74 struct hypfs_entry_dir {
75     struct hypfs_entry e;
76     struct list_head dirlist;
77 };
78 
79 struct hypfs_dyndir_id {
80     struct hypfs_entry_dir dir;             /* Modified copy of template. */
81     struct hypfs_funcs funcs;               /* Dynamic functions. */
82     const struct hypfs_entry_dir *template; /* Template used. */
83 #define HYPFS_DYNDIR_ID_NAMELEN 12
84     char name[HYPFS_DYNDIR_ID_NAMELEN];     /* Name of hypfs entry. */
85 
86     unsigned int id;                        /* Numerical id. */
87     void *data;                             /* Data associated with id. */
88 };
89 
90 #define HYPFS_DIR_INIT_FUNC(var, nam, fn)         \
91     struct hypfs_entry_dir __read_mostly var = {  \
92         .e.type = XEN_HYPFS_TYPE_DIR,             \
93         .e.encoding = XEN_HYPFS_ENC_PLAIN,        \
94         .e.name = (nam),                          \
95         .e.size = 0,                              \
96         .e.max_size = 0,                          \
97         .e.list = LIST_HEAD_INIT(var.e.list),     \
98         .e.funcs = (fn),                          \
99         .dirlist = LIST_HEAD_INIT(var.dirlist),   \
100     }
101 
102 #define HYPFS_DIR_INIT(var, nam)                  \
103     HYPFS_DIR_INIT_FUNC(var, nam, &hypfs_dir_funcs)
104 
105 #define HYPFS_VARSIZE_INIT(var, typ, nam, msz, fn) \
106     struct hypfs_entry_leaf __read_mostly var = {  \
107         .e.type = (typ),                           \
108         .e.encoding = XEN_HYPFS_ENC_PLAIN,         \
109         .e.name = (nam),                           \
110         .e.max_size = (msz),                       \
111         .e.funcs = (fn),                           \
112     }
113 
114 /* Content and size need to be set via hypfs_string_set_reference(). */
115 #define HYPFS_STRING_INIT(var, nam)               \
116     HYPFS_VARSIZE_INIT(var, XEN_HYPFS_TYPE_STRING, nam, 0, &hypfs_leaf_ro_funcs)
117 
118 /*
119  * Set content and size of a XEN_HYPFS_TYPE_STRING node. The node will point
120  * to str, so any later modification of *str should be followed by a call
121  * to hypfs_string_set_reference() in order to update the size of the node
122  * data.
123  */
hypfs_string_set_reference(struct hypfs_entry_leaf * leaf,const char * str)124 static inline void hypfs_string_set_reference(struct hypfs_entry_leaf *leaf,
125                                               const char *str)
126 {
127     leaf->u.content = str;
128     leaf->e.size = strlen(str) + 1;
129 }
130 
131 #define HYPFS_FIXEDSIZE_INIT(var, typ, nam, contvar, fn, wr) \
132     struct hypfs_entry_leaf __read_mostly var = {            \
133         .e.type = (typ),                                     \
134         .e.encoding = XEN_HYPFS_ENC_PLAIN,                   \
135         .e.name = (nam),                                     \
136         .e.size = sizeof(contvar),                           \
137         .e.max_size = (wr) ? sizeof(contvar) : 0,            \
138         .e.funcs = (fn),                                     \
139         .u.content = &(contvar),                             \
140     }
141 
142 #define HYPFS_UINT_INIT(var, nam, contvar)                       \
143     HYPFS_FIXEDSIZE_INIT(var, XEN_HYPFS_TYPE_UINT, nam, contvar, \
144                          &hypfs_leaf_ro_funcs, 0)
145 #define HYPFS_UINT_INIT_WRITABLE(var, nam, contvar)              \
146     HYPFS_FIXEDSIZE_INIT(var, XEN_HYPFS_TYPE_UINT, nam, contvar, \
147                          &hypfs_leaf_wr_funcs, 1)
148 
149 #define HYPFS_INT_INIT(var, nam, contvar)                        \
150     HYPFS_FIXEDSIZE_INIT(var, XEN_HYPFS_TYPE_INT, nam, contvar,  \
151                          &hypfs_leaf_ro_funcs, 0)
152 #define HYPFS_INT_INIT_WRITABLE(var, nam, contvar)               \
153     HYPFS_FIXEDSIZE_INIT(var, XEN_HYPFS_TYPE_INT, nam, contvar, \
154                          &hypfs_leaf_wr_funcs, 1)
155 
156 #define HYPFS_BOOL_INIT(var, nam, contvar)                       \
157     HYPFS_FIXEDSIZE_INIT(var, XEN_HYPFS_TYPE_BOOL, nam, contvar, \
158                          &hypfs_leaf_ro_funcs, 0)
159 #define HYPFS_BOOL_INIT_WRITABLE(var, nam, contvar)              \
160     HYPFS_FIXEDSIZE_INIT(var, XEN_HYPFS_TYPE_BOOL, nam, contvar, \
161                          &hypfs_bool_wr_funcs, 1)
162 
163 extern struct hypfs_entry_dir hypfs_root;
164 
165 int hypfs_add_dir(struct hypfs_entry_dir *parent,
166                   struct hypfs_entry_dir *dir, bool nofault);
167 void hypfs_add_dyndir(struct hypfs_entry_dir *parent,
168                       struct hypfs_entry_dir *template);
169 int hypfs_add_leaf(struct hypfs_entry_dir *parent,
170                    struct hypfs_entry_leaf *leaf, bool nofault);
171 const struct hypfs_entry *cf_check hypfs_node_enter(
172     const struct hypfs_entry *entry);
173 void cf_check hypfs_node_exit(const struct hypfs_entry *entry);
174 int cf_check hypfs_read_dir(const struct hypfs_entry *entry,
175                             XEN_GUEST_HANDLE_PARAM(void) uaddr);
176 int cf_check hypfs_read_leaf(const struct hypfs_entry *entry,
177                              XEN_GUEST_HANDLE_PARAM(void) uaddr);
178 int cf_check hypfs_write_deny(struct hypfs_entry_leaf *leaf,
179                               XEN_GUEST_HANDLE_PARAM(const_void) uaddr,
180                               unsigned int ulen);
181 int cf_check hypfs_write_leaf(struct hypfs_entry_leaf *leaf,
182                               XEN_GUEST_HANDLE_PARAM(const_void) uaddr,
183                               unsigned int ulen);
184 int cf_check hypfs_write_bool(struct hypfs_entry_leaf *leaf,
185                               XEN_GUEST_HANDLE_PARAM(const_void) uaddr,
186                               unsigned int ulen);
187 int cf_check hypfs_write_custom(struct hypfs_entry_leaf *leaf,
188                                 XEN_GUEST_HANDLE_PARAM(const_void) uaddr,
189                                 unsigned int ulen);
190 unsigned int cf_check hypfs_getsize(const struct hypfs_entry *entry);
191 struct hypfs_entry *cf_check hypfs_leaf_findentry(
192     const struct hypfs_entry_dir *dir, const char *name, unsigned int name_len);
193 struct hypfs_entry *cf_check hypfs_dir_findentry(
194     const struct hypfs_entry_dir *dir, const char *name, unsigned int name_len);
195 void *hypfs_alloc_dyndata(unsigned long size);
196 #define hypfs_alloc_dyndata(type) ((type *)hypfs_alloc_dyndata(sizeof(type)))
197 void *hypfs_get_dyndata(void);
198 void hypfs_free_dyndata(void);
199 int hypfs_read_dyndir_id_entry(const struct hypfs_entry_dir *template,
200                                unsigned int id, bool is_last,
201                                XEN_GUEST_HANDLE_PARAM(void) *uaddr);
202 struct hypfs_entry *hypfs_gen_dyndir_id_entry(
203     const struct hypfs_entry_dir *template, unsigned int id, void *data);
204 unsigned int hypfs_dynid_entry_size(const struct hypfs_entry *template,
205                                     unsigned int id);
206 #endif
207 
208 #endif /* __XEN_HYPFS_H__ */
209