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