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