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