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