xref: /optee_os/core/include/mm/fobj.h (revision 9fc2442cc66c279cb962c90c4375746fc9b28bb9)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2019, Linaro Limited
4  */
5 
6 #ifndef __MM_FOBJ_H
7 #define __MM_FOBJ_H
8 
9 #include <kernel/panic.h>
10 #include <kernel/refcount.h>
11 #include <mm/tee_pager.h>
12 #include <sys/queue.h>
13 #include <tee_api_types.h>
14 #include <types_ext.h>
15 
16 /*
17  * struct fobj - file object storage abstraction
18  * @ops:	Operations pointer
19  * @num_pages:	Number of pages covered
20  * @refc:	Reference counter
21  */
22 struct fobj {
23 	const struct fobj_ops *ops;
24 	unsigned int num_pages;
25 	struct refcount refc;
26 #ifdef CFG_WITH_PAGER
27 	struct tee_pager_area_head areas;
28 #endif
29 };
30 
31 /*
32  * struct fobj_ops - operations struct for struct fobj
33  * @free:	Frees the @fobj
34  * @load_page:	Loads page with index @page_idx at address @va
35  * @save_page:	Saves page with index @page_idx from address @va
36  * @get_pa:	Returns physical address of page at @page_idx if not paged
37  */
38 struct fobj_ops {
39 	void (*free)(struct fobj *fobj);
40 #ifdef CFG_WITH_PAGER
41 	TEE_Result (*load_page)(struct fobj *fobj, unsigned int page_idx,
42 				void *va);
43 	TEE_Result (*save_page)(struct fobj *fobj, unsigned int page_idx,
44 				const void *va);
45 #endif
46 	paddr_t (*get_pa)(struct fobj *fobj, unsigned int page_idx);
47 };
48 
49 #ifdef CFG_WITH_PAGER
50 /*
51  * fobj_locked_paged_alloc() - Allocate storage which is locked in memory
52  * @num_pages:	Number of pages covered
53  *
54  * This object only supports loading pages zero initialized. Saving a page
55  * will result in an error.
56  *
57  * Returns a valid pointer on success or NULL on failure.
58  */
59 struct fobj *fobj_locked_paged_alloc(unsigned int num_pages);
60 
61 /*
62  * fobj_rw_paged_alloc() - Allocate read/write storage
63  * @num_pages:	Number of pages covered
64  *
65  * This object supports both load and saving of pages. Pages are zero
66  * initialized the first time they are loaded.
67  *
68  * Returns a valid pointer on success or NULL on failure.
69  */
70 struct fobj *fobj_rw_paged_alloc(unsigned int num_pages);
71 
72 /*
73  * fobj_ro_paged_alloc() - Allocate initialized read-only storage
74  * @num_pages:	Number of pages covered
75  * @hashes:	Hashes to verify the pages
76  * @store:	Clear text data for all pages
77  *
78  * This object only support loading pages with an already provided content
79  * in @store. When a page is loaded it will be verified against an hash in
80  * @hash. Saving a page will result in an error.
81  *
82  * Returns a valid pointer on success or NULL on failure.
83  */
84 struct fobj *fobj_ro_paged_alloc(unsigned int num_pages, void *hashes,
85 				 void *store);
86 
87 /*
88  * fobj_ro_reloc_paged_alloc() - Allocate initialized read-only storage with
89  *				 relocation
90  * @num_pages:	Number of pages covered
91  * @hashes:	Hashes to verify the pages
92  * @reloc_offs:	Offset from the base address in the relocations in @reloc
93  * @reloc:	Relocation data
94  * @reloc_len:	Length of relocation data
95  * @store:	Clear text data for all pages
96  *
97  * This object is like fobj_ro_paged_alloc() above, but in addition the
98  * relocation information is applied to a populated page. This makes sure
99  * the offset to which all pages are relocated doesn't leak out to storage.
100  *
101  * Returns a valid pointer on success or NULL on failure.
102  */
103 struct fobj *fobj_ro_reloc_paged_alloc(unsigned int num_pages, void *hashes,
104 				       unsigned int reloc_offs,
105 				       const void *reloc,
106 				       unsigned int reloc_len, void *store);
107 
108 /*
109  * fobj_load_page() - Load a page into memory
110  * @fobj:	Fobj pointer
111  * @page_index:	Index of page in @fobj
112  * @va:		Address where content should be stored and verified
113  *
114  * Returns TEE_SUCCESS on success or TEE_ERROR_* on failure.
115  */
116 static inline TEE_Result fobj_load_page(struct fobj *fobj,
117 					unsigned int page_idx, void *va)
118 {
119 	if (fobj)
120 		return fobj->ops->load_page(fobj, page_idx, va);
121 
122 	return TEE_ERROR_GENERIC;
123 }
124 
125 /*
126  * fobj_save_page() - Save a page into storage
127  * @fobj:	Fobj pointer
128  * @page_index:	Index of page in @fobj
129  * @va:		Address of the page to store.
130  *
131  * Returns TEE_SUCCESS on success or TEE_ERROR_* on failure.
132  */
133 static inline TEE_Result fobj_save_page(struct fobj *fobj,
134 					unsigned int page_idx, const void *va)
135 {
136 	if (fobj)
137 		return fobj->ops->save_page(fobj, page_idx, va);
138 
139 	return TEE_ERROR_GENERIC;
140 }
141 #endif
142 
143 /*
144  * fobj_ta_mem_alloc() - Allocates TA memory
145  * @num_pages:	Number of pages
146  *
147  * If paging of user TAs read/write paged fobj is allocated otherwise a
148  * fobj which uses unpaged secure memory directly.
149  *
150  * Returns a valid pointer on success or NULL on failure.
151  */
152 #ifdef CFG_PAGED_USER_TA
153 #define fobj_ta_mem_alloc(num_pages)	fobj_rw_paged_alloc(num_pages)
154 #else
155 /*
156  * fobj_sec_mem_alloc() - Allocates storage directly in secure memory
157  * @num_pages:	Number of pages
158  *
159  * Returns a valid pointer on success or NULL on failure.
160  */
161 struct fobj *fobj_sec_mem_alloc(unsigned int num_pages);
162 
163 #define fobj_ta_mem_alloc(num_pages)	fobj_sec_mem_alloc(num_pages)
164 #endif
165 
166 /*
167  * fobj_get() - Increase fobj reference count
168  * @fobj:	Fobj pointer
169  *
170  * Returns @fobj, if @fobj isn't NULL its reference counter is first
171  * increased.
172  */
173 static inline struct fobj *fobj_get(struct fobj *fobj)
174 {
175 	if (fobj && !refcount_inc(&fobj->refc))
176 		panic();
177 
178 	return fobj;
179 }
180 
181 /*
182  * fobj_put() - Decrease reference counter of fobj
183  * @fobj:	Fobj pointer
184  *
185  * If reference counter reaches 0, matching the numbers of fobj_alloc_*() +
186  * fobj_get(), the fobj is freed.
187  */
188 static inline void fobj_put(struct fobj *fobj)
189 {
190 	if (fobj && refcount_dec(&fobj->refc))
191 		fobj->ops->free(fobj);
192 }
193 
194 #endif /*__MM_FOBJ_H*/
195