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