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 */ 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 */ 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 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 */ 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 */ 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