blob: 5dcb72357e689e3afc853a0a1878de79e40c53d7 [file] [log] [blame]
/* 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);
}
#ifdef CFG_WITH_PAGER
/*
* fobj_generate_authenc_key() - Generate authentication key
*
* Generates the authentication key used in all fobjs allocated with
* fobj_rw_paged_alloc().
*/
void fobj_generate_authenc_key(void);
#else
static inline void fobj_generate_authenc_key(void)
{
}
#endif
#endif /*__MM_FOBJ_H*/