diff options
-rw-r--r-- | core/tee/tee_rpmb_fs.c | 583 | ||||
-rw-r--r-- | mk/config.mk | 20 |
2 files changed, 439 insertions, 164 deletions
diff --git a/core/tee/tee_rpmb_fs.c b/core/tee/tee_rpmb_fs.c index 5cb9c4dd..febdfcb9 100644 --- a/core/tee/tee_rpmb_fs.c +++ b/core/tee/tee_rpmb_fs.c @@ -44,6 +44,14 @@ #define TEE_RPMB_FS_FILENAME_LENGTH 224 /** + * Utilized when caching is enabled, i.e., when CFG_RPMB_FS_CACHE_ENTRIES > 0. + * Cache size + the number of entries that are repeatedly read in and buffered + * once the cache is full. + */ +#define RPMB_BUF_MAX_ENTRIES (CFG_RPMB_FS_CACHE_ENTRIES + \ + CFG_RPMB_FS_RD_ENTRIES) + +/** * FS parameters: Information often used by internal functions. * fat_start_address will be set by rpmb_fs_setup(). * rpmb_fs_parameters can be read by any other function. @@ -66,6 +74,28 @@ struct rpmb_fat_entry { }; /** + * Structure that describes buffered/cached FAT FS entries in RPMB storage. + * This structure is used in functions traversing the FAT FS. + */ +struct rpmb_fat_entry_dir { + /* + * Buffer storing the FAT FS entries read in from RPMB storage. It + * includes the optional cache entries (CFG_RPMB_FS_CACHE_ENTRIES) + * and entries temporary read for current FAT FS traversal + * (CFG_RPMB_FS_RD_ENTRIES) when not found from cached entries. + */ + struct rpmb_fat_entry *rpmb_fat_entry_buf; + /* Current index of FAT FS entry to read from buffer. */ + uint32_t idx_curr; + /* Total number of FAT FS entries in buffer. */ + uint32_t num_buffered; + /* Total number of FAT FS entries read during traversal. */ + uint32_t num_total_read; + /* Indicates that last FAT FS entry was read. */ + bool last_reached; +}; + +/** * FAT entry context with reference to a FAT entry and its * location in RPMB. */ @@ -110,6 +140,7 @@ struct tee_fs_dir { }; static struct rpmb_fs_parameters *fs_par; +static struct rpmb_fat_entry_dir *fat_entry_dir; /* * Lower interface to RPMB device @@ -1472,54 +1503,323 @@ func_exit: */ static TEE_Result get_fat_start_address(uint32_t *addr); +static TEE_Result rpmb_fs_setup(void); -#if (TRACE_LEVEL >= TRACE_FLOW) -static void dump_fat(void) +/** + * fat_entry_dir_free: Free the FAT entry dir. + */ +static void fat_entry_dir_free(void) +{ + if (fat_entry_dir) { + free(fat_entry_dir->rpmb_fat_entry_buf); + free(fat_entry_dir); + fat_entry_dir = NULL; + } +} + +/** + * fat_entry_dir_init: Initialize the FAT FS entry buffer/cache + * This function must be called before reading FAT FS entries using the + * function fat_entry_dir_get_next. This initializes the buffer/cache with the + * first FAT FS entries. + */ +static TEE_Result fat_entry_dir_init(void) { TEE_Result res = TEE_ERROR_GENERIC; - struct rpmb_fat_entry *fat_entries = NULL; - uint32_t fat_address; - size_t size; - int i; - bool last_entry_found = false; + struct rpmb_fat_entry *fe = NULL; + uint32_t fat_address = 0; + uint32_t num_elems_read = 0; + + if (fat_entry_dir) + return TEE_SUCCESS; + + res = rpmb_fs_setup(); + if (res) + return res; res = get_fat_start_address(&fat_address); - if (res != TEE_SUCCESS) - goto out; + if (res) + return res; + + fat_entry_dir = calloc(1, sizeof(struct rpmb_fat_entry_dir)); + if (!fat_entry_dir) + return TEE_ERROR_OUT_OF_MEMORY; - size = CFG_RPMB_FS_RD_ENTRIES * sizeof(struct rpmb_fat_entry); - fat_entries = malloc(size); - if (!fat_entries) { + /* + * If caching is enabled, read in up to the maximum cache size, but + * never more than the single read in size. Otherwise, read in as many + * entries fit into the temporary buffer. + */ + if (CFG_RPMB_FS_CACHE_ENTRIES) + num_elems_read = MIN(CFG_RPMB_FS_CACHE_ENTRIES, + CFG_RPMB_FS_RD_ENTRIES); + else + num_elems_read = CFG_RPMB_FS_RD_ENTRIES; + + /* + * Allocate memory for the FAT FS entries to read in. + */ + fe = calloc(num_elems_read, sizeof(struct rpmb_fat_entry)); + if (!fe) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } - while (!last_entry_found) { - res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address, - (uint8_t *)fat_entries, size, NULL, NULL); - if (res != TEE_SUCCESS) - goto out; + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address, (uint8_t *)fe, + num_elems_read * sizeof(*fe), NULL, NULL); + if (res) + goto out; - for (i = 0; i < CFG_RPMB_FS_RD_ENTRIES; i++) { + fat_entry_dir->rpmb_fat_entry_buf = fe; - FMSG("flags 0x%x, size %d, address 0x%x, filename '%s'", - fat_entries[i].flags, - fat_entries[i].data_size, - fat_entries[i].start_address, - fat_entries[i].filename); + /* + * We use this variable when getting next entries from the buffer/cache + * to see whether we have to read in more entries from storage. + */ + fat_entry_dir->num_buffered = num_elems_read; - if ((fat_entries[i].flags & FILE_IS_LAST_ENTRY) != 0) { - last_entry_found = true; - break; - } + return TEE_SUCCESS; +out: + fat_entry_dir_free(); + free(fe); + return res; +} - /* Move to next fat_entry. */ - fat_address += sizeof(struct rpmb_fat_entry); +/** + * fat_entry_dir_deinit: If caching is enabled, free the temporary buffer for + * FAT FS entries in case the cache was too small. Keep the elements in the + * cache. Reset the counter variables to start the next traversal from fresh + * from the first cached entry. If caching is disabled, just free the + * temporary buffer by calling fat_entry_dir_free and return. + */ +static void fat_entry_dir_deinit(void) +{ + struct rpmb_fat_entry *fe = NULL; + + if (!fat_entry_dir) + return; + + if (!CFG_RPMB_FS_CACHE_ENTRIES) { + fat_entry_dir_free(); + return; + } + + fe = fat_entry_dir->rpmb_fat_entry_buf; + fat_entry_dir->idx_curr = 0; + fat_entry_dir->num_total_read = 0; + fat_entry_dir->last_reached = false; + + if (fat_entry_dir->num_buffered > CFG_RPMB_FS_CACHE_ENTRIES) { + fat_entry_dir->num_buffered = CFG_RPMB_FS_CACHE_ENTRIES; + + fe = realloc(fe, fat_entry_dir->num_buffered * sizeof(*fe)); + + /* + * In case realloc fails, we are on the safe side if we destroy + * the whole structure. Upon the next init, the cache has to be + * re-established, but this case should not happen in practice. + */ + if (!fe) + fat_entry_dir_free(); + else + fat_entry_dir->rpmb_fat_entry_buf = fe; + } +} + +/** + * fat_entry_dir_update: Updates a persisted FAT FS entry in the cache. + * This function updates the FAT entry fat_entry that was written to address + * fat_address onto RPMB storage in the cache. + */ +static TEE_Result __maybe_unused fat_entry_dir_update + (struct rpmb_fat_entry *fat_entry, + uint32_t fat_address) +{ + uint32_t fat_entry_buf_idx = 0; + /* Use a temp var to avoid compiler warning if caching disabled. */ + uint32_t max_cache_entries = CFG_RPMB_FS_CACHE_ENTRIES; + + assert(!(fat_address - RPMB_FS_FAT_START_ADDRESS) % + sizeof(struct rpmb_fat_entry)); + + /* Nothing to update if the cache is not initialized. */ + if (!fat_entry_dir) + return TEE_SUCCESS; + + fat_entry_buf_idx = (fat_address - RPMB_FS_FAT_START_ADDRESS) / + sizeof(struct rpmb_fat_entry); + + /* Only need to write if index points to an entry in cache. */ + if (fat_entry_buf_idx < max_cache_entries) { + memcpy(fat_entry_dir->rpmb_fat_entry_buf + fat_entry_buf_idx, + fat_entry, sizeof(struct rpmb_fat_entry)); + } + + return TEE_SUCCESS; +} + +/** + * fat_entry_dir_get_next: Get next FAT FS entry. + * Read either from cache/buffer, or by reading from RPMB storage if the + * elements in the buffer/cache are fully read. When reading in from RPMB + * storage, the buffer is overwritten in case caching is disabled. + * In case caching is enabled, the cache is either further filled, or a + * temporary buffer populated if the cache is already full. + * The FAT FS entry is written to fat_entry. The respective address in RPMB + * storage is written to fat_address, if not NULL. When the last FAT FS entry + * was previously read, the function indicates this case by writing a NULL + * pointer to fat_entry. + * Returns a value different TEE_SUCCESS if the next FAT FS entry could not be + * retrieved. + */ +static TEE_Result fat_entry_dir_get_next(struct rpmb_fat_entry **fat_entry, + uint32_t *fat_address) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct rpmb_fat_entry *fe = NULL; + uint32_t num_elems_read = 0; + uint32_t fat_address_local = 0; + + assert(fat_entry_dir && fat_entry); + + /* Don't read further if we previously read the last FAT FS entry. */ + if (fat_entry_dir->last_reached) { + *fat_entry = NULL; + return TEE_SUCCESS; + } + + fe = fat_entry_dir->rpmb_fat_entry_buf; + + /* Determine address of FAT FS entry in RPMB storage. */ + fat_address_local = RPMB_FS_FAT_START_ADDRESS + + (fat_entry_dir->num_total_read * + sizeof(struct rpmb_fat_entry)); + + /* + * We've read all so-far buffered elements, so we need to + * read in more entries from RPMB storage. + */ + if (fat_entry_dir->idx_curr >= fat_entry_dir->num_buffered) { + /* + * This is the case where we do not cache entries, so just read + * in next set of FAT FS entries into the buffer. + * Goto the end of the when statement if that is done. + */ + if (!CFG_RPMB_FS_CACHE_ENTRIES) { + num_elems_read = CFG_RPMB_FS_RD_ENTRIES; + fat_entry_dir->idx_curr = 0; + + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, + fat_address_local, (uint8_t *)fe, + num_elems_read * sizeof(*fe), NULL, + NULL); + if (res) + return res; + goto post_read_in; + } + + /* + * We cache FAT FS entries, and the buffer is not completely + * filled. Further keep on extending the buffer up to its max + * size by reading in from RPMB. + */ + if (fat_entry_dir->num_total_read < RPMB_BUF_MAX_ENTRIES) { + /* + * Read at most as many elements as fit in the buffer + * and no more than the defined number of entries to + * read in at once. + */ + num_elems_read = MIN(RPMB_BUF_MAX_ENTRIES - + fat_entry_dir->num_total_read, + (uint32_t)CFG_RPMB_FS_RD_ENTRIES); + + /* + * Expand the buffer to fit in the additional entries. + */ + fe = realloc(fe, + (fat_entry_dir->num_buffered + + num_elems_read) * sizeof(*fe)); + if (!fe) + return TEE_ERROR_OUT_OF_MEMORY; + + fat_entry_dir->rpmb_fat_entry_buf = fe; + + /* Read in to the next free slot in the buffer/cache. */ + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, + fat_address_local, + (uint8_t *)(fe + + fat_entry_dir->num_total_read), + num_elems_read * sizeof(*fe), + NULL, NULL); + if (res) + return res; + + fat_entry_dir->num_buffered += num_elems_read; + } else { + /* + * This happens when we have read as many elements as + * can possibly fit into the buffer. + * As the first part of the buffer serves as our cache, + * we only overwrite the last part that serves as our + * temporary buffer used to iteratively read in entries + * when the cache is full. Read in the temporary buffer + * maximum size. + */ + num_elems_read = CFG_RPMB_FS_RD_ENTRIES; + /* Reset index to beginning of the temporary buffer. */ + fat_entry_dir->idx_curr = CFG_RPMB_FS_CACHE_ENTRIES; + + /* Read in elements after the end of the cache. */ + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, + fat_address_local, + (uint8_t *)(fe + + fat_entry_dir->idx_curr), + num_elems_read * sizeof(*fe), + NULL, NULL); + if (res) + return res; } } -out: - free(fat_entries); +post_read_in: + if (fat_address) + *fat_address = fat_address_local; + + *fat_entry = fe + fat_entry_dir->idx_curr; + + fat_entry_dir->idx_curr++; + fat_entry_dir->num_total_read++; + + /* + * Indicate last entry was read. + * Ensures we return a zero value for fat_entry on next invocation. + */ + if ((*fat_entry)->flags & FILE_IS_LAST_ENTRY) + fat_entry_dir->last_reached = true; + + return TEE_SUCCESS; +} + +#if (TRACE_LEVEL >= TRACE_FLOW) +static void dump_fat(void) +{ + TEE_RESULT res; + struct rpmb_fat_entry *fe = NULL; + + if (fat_entry_dir_init()) + return; + + while (true) { + res = fat_entry_dir_get_next(&fe, NULL); + if (res || !fe) + break; + + FMSG("flags %#"PRIx32", size %"PRIu32", address %#"PRIx32 + ", filename '%s'", + fe->flags, fe->data_size, fe->start_address, fe->filename); + } + + fat_entry_dir_deinit(); } #else static void dump_fat(void) @@ -1580,7 +1880,7 @@ static TEE_Result write_fat_entry(struct rpmb_file_handle *fh, if (update_write_counter) { res = tee_rpmb_get_write_counter(CFG_RPMB_FS_DEV_ID, &fh->fat_entry.write_counter); - if (res != TEE_SUCCESS) + if (res) goto out; } @@ -1590,12 +1890,17 @@ static TEE_Result write_fat_entry(struct rpmb_file_handle *fh, dump_fat(); + /* If caching enabled, update a successfully written entry in cache. */ + if (CFG_RPMB_FS_CACHE_ENTRIES && !res) + res = fat_entry_dir_update(&fh->fat_entry, + fh->rpmb_fat_address); + out: return res; } /** - * rpmb_fs_setup: Setup rpmb fs. + * rpmb_fs_setup: Setup RPMB FS. * Set initial partition and FS values and write to RPMB. * Store frequently used data in RAM. */ @@ -1716,31 +2021,17 @@ static TEE_Result read_fat(struct rpmb_file_handle *fh, tee_mm_pool_t *p) { TEE_Result res = TEE_ERROR_GENERIC; tee_mm_entry_t *mm = NULL; - struct rpmb_fat_entry *fat_entries = NULL; + struct rpmb_fat_entry *fe = NULL; uint32_t fat_address; - size_t size; - int i; bool entry_found = false; - bool last_entry_found = false; bool expand_fat = false; struct rpmb_file_handle last_fh; DMSG("fat_address %d", fh->rpmb_fat_address); - res = rpmb_fs_setup(); - if (res != TEE_SUCCESS) - goto out; - - res = get_fat_start_address(&fat_address); - if (res != TEE_SUCCESS) - goto out; - - size = CFG_RPMB_FS_RD_ENTRIES * sizeof(struct rpmb_fat_entry); - fat_entries = malloc(size); - if (!fat_entries) { - res = TEE_ERROR_OUT_OF_MEMORY; + res = fat_entry_dir_init(); + if (res) goto out; - } /* * The pool is used to represent the current RPMB layout. To find @@ -1748,56 +2039,46 @@ static TEE_Result read_fat(struct rpmb_file_handle *fh, tee_mm_pool_t *p) * if it is not NULL the entire FAT must be traversed to fill in * the pool. */ - while (!last_entry_found && (!entry_found || p)) { - res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address, - (uint8_t *)fat_entries, size, NULL, NULL); - if (res != TEE_SUCCESS) - goto out; + while (true) { + res = fat_entry_dir_get_next(&fe, &fat_address); + if (res || !fe) + break; - for (i = 0; i < CFG_RPMB_FS_RD_ENTRIES; i++) { - /* - * Look for an entry, matching filenames. (read, rm, - * rename and stat.). Only store first filename match. - */ - if (fh->filename && - (strcmp(fh->filename, - fat_entries[i].filename) == 0) && - (fat_entries[i].flags & FILE_IS_ACTIVE) && - (!entry_found)) { - entry_found = true; - fh->rpmb_fat_address = fat_address; - memcpy(&fh->fat_entry, &fat_entries[i], - sizeof(struct rpmb_fat_entry)); - if (!p) - break; - } + /* + * Look for an entry, matching filenames. (read, rm, + * rename and stat.). Only store first filename match. + */ + if (fh->filename && (!strcmp(fh->filename, fe->filename)) && + (fe->flags & FILE_IS_ACTIVE) && !entry_found) { + entry_found = true; + fh->rpmb_fat_address = fat_address; + memcpy(&fh->fat_entry, fe, sizeof(*fe)); + if (!p) + break; + } - /* Add existing files to memory pool. (write) */ - if (p) { - if ((fat_entries[i].flags & FILE_IS_ACTIVE) && - (fat_entries[i].data_size > 0)) { - - mm = tee_mm_alloc2 - (p, - fat_entries[i].start_address, - fat_entries[i].data_size); - if (!mm) { - res = TEE_ERROR_OUT_OF_MEMORY; - goto out; - } - } + /* Add existing files to memory pool. (write) */ + if (p) { + if ((fe->flags & FILE_IS_ACTIVE) && fe->data_size > 0) { - /* Unused FAT entries can be reused (write) */ - if (((fat_entries[i].flags & FILE_IS_ACTIVE) == - 0) && (fh->rpmb_fat_address == 0)) { - fh->rpmb_fat_address = fat_address; - memcpy(&fh->fat_entry, &fat_entries[i], - sizeof(struct rpmb_fat_entry)); + mm = tee_mm_alloc2(p, fe->start_address, + fe->data_size); + if (!mm) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; } } - if ((fat_entries[i].flags & FILE_IS_LAST_ENTRY) != 0) { - last_entry_found = true; + /* Unused FAT entries can be reused (write) */ + if (((fe->flags & FILE_IS_ACTIVE) == 0) && + fh->rpmb_fat_address == 0) { + fh->rpmb_fat_address = fat_address; + memcpy(&fh->fat_entry, fe, + sizeof(struct rpmb_fat_entry)); + } + + if (((fe->flags & FILE_IS_LAST_ENTRY) != 0) && + fh->rpmb_fat_address == fat_address) { /* * If the last entry was reached and was chosen @@ -1808,16 +2089,13 @@ static TEE_Result read_fat(struct rpmb_file_handle *fh, tee_mm_pool_t *p) * is the current FAT entry address being * compared. */ - if (p && fh->rpmb_fat_address == fat_address) - expand_fat = true; - break; + expand_fat = true; } - - /* Move to next fat_entry. */ - fat_address += sizeof(struct rpmb_fat_entry); } } + if (res) + goto out; /* * Represent the FAT table in the pool. */ @@ -1857,7 +2135,7 @@ static TEE_Result read_fat(struct rpmb_file_handle *fh, tee_mm_pool_t *p) res = TEE_ERROR_ITEM_NOT_FOUND; out: - free(fat_entries); + fat_entry_dir_deinit(); return res; } @@ -2315,91 +2593,69 @@ static TEE_Result rpmb_fs_dir_populate(const char *path, struct tee_fs_dir *dir) { struct tee_rpmb_fs_dirent *current = NULL; - struct rpmb_fat_entry *fat_entries = NULL; + struct rpmb_fat_entry *fe = NULL; uint32_t fat_address; uint32_t filelen; char *filename; - int i; - bool last_entry_found = false; bool matched; struct tee_rpmb_fs_dirent *next = NULL; uint32_t pathlen; TEE_Result res = TEE_ERROR_GENERIC; - uint32_t size; char temp; mutex_lock(&rpmb_mutex); - res = rpmb_fs_setup(); - if (res != TEE_SUCCESS) - goto out; - - res = get_fat_start_address(&fat_address); - if (res != TEE_SUCCESS) - goto out; - - size = CFG_RPMB_FS_RD_ENTRIES * sizeof(struct rpmb_fat_entry); - fat_entries = malloc(size); - if (!fat_entries) { - res = TEE_ERROR_OUT_OF_MEMORY; + res = fat_entry_dir_init(); + if (res) goto out; - } pathlen = strlen(path); - while (!last_entry_found) { - res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address, - (uint8_t *)fat_entries, size, NULL, NULL); - if (res != TEE_SUCCESS) - goto out; - for (i = 0; i < CFG_RPMB_FS_RD_ENTRIES; i++) { - filename = fat_entries[i].filename; - if (fat_entries[i].flags & FILE_IS_ACTIVE) { - matched = false; - filelen = strlen(filename); - if (filelen > pathlen) { - temp = filename[pathlen]; - filename[pathlen] = '\0'; - if (strcmp(filename, path) == 0) - matched = true; - - filename[pathlen] = temp; - } + while (true) { + res = fat_entry_dir_get_next(&fe, &fat_address); + if (res || !fe) + break; + + filename = fe->filename; + if (fe->flags & FILE_IS_ACTIVE) { + matched = false; + filelen = strlen(filename); + if (filelen > pathlen) { + temp = filename[pathlen]; + filename[pathlen] = '\0'; + if (strcmp(filename, path) == 0) + matched = true; + + filename[pathlen] = temp; + } - if (matched) { - next = malloc(sizeof(*next)); - if (!next) { - res = TEE_ERROR_OUT_OF_MEMORY; - goto out; - } + if (matched) { + next = malloc(sizeof(*next)); + if (!next) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } - next->entry.oidlen = tee_hs2b( - (uint8_t *)&filename[pathlen], + next->entry.oidlen = tee_hs2b((uint8_t *) + &filename[pathlen], next->entry.oid, filelen - pathlen, sizeof(next->entry.oid)); - if (next->entry.oidlen) { - SIMPLEQ_INSERT_TAIL(&dir->next, - next, link); - current = next; - } else { - free(next); - next = NULL; - } - + if (next->entry.oidlen) { + SIMPLEQ_INSERT_TAIL(&dir->next, + next, link); + current = next; + } else { + free(next); + next = NULL; } } - - if (fat_entries[i].flags & FILE_IS_LAST_ENTRY) { - last_entry_found = true; - break; - } - - /* Move to next fat_entry. */ - fat_address += sizeof(struct rpmb_fat_entry); } } + if (res) + goto out; + if (current) res = TEE_SUCCESS; else @@ -2407,10 +2663,9 @@ static TEE_Result rpmb_fs_dir_populate(const char *path, out: mutex_unlock(&rpmb_mutex); - if (res != TEE_SUCCESS) + fat_entry_dir_deinit(); + if (res) rpmb_fs_dir_free(dir); - if (fat_entries) - free(fat_entries); return res; } diff --git a/mk/config.mk b/mk/config.mk index 148a4b42..c00a1461 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -154,6 +154,26 @@ CFG_RPMB_FS_DEV_ID ?= 0 # config files CFG_RPMB_FS_RD_ENTRIES ?= 8 +# Enables caching of FAT FS entries when set to a value greater than zero. +# When enabled, the cache stores the first 'CFG_RPMB_FS_CACHE_ENTRIES' FAT FS +# entries. The cache is populated when FAT FS entries are initially read in. +# When traversing the FAT FS entries, we read from the cache instead of reading +# in the entries from RPMB storage. Consequently, when a FAT FS entry is +# written, the cache is updated. In scenarios where an estimate of the number +# of FAT FS entries can be made, the cache may be specifically tailored to +# store all entries. The caching can improve RPMB I/O at the cost +# of additional memory. +# Without caching, we temporarily require +# CFG_RPMB_FS_RD_ENTRIES*sizeof(struct rpmb_fat_entry) bytes of heap memory +# while traversing the FAT FS (e.g. in read_fat). +# For example 8*256 bytes = 2kB while in read_fat. +# With caching, we constantly require up to +# CFG_RPMB_FS_CACHE_ENTRIES*sizeof(struct rpmb_fat_entry) bytes of heap memory +# depending on how many elements are in the cache, and additional temporary +# CFG_RPMB_FS_RD_ENTRIES*sizeof(struct rpmb_fat_entry) bytes of heap memory +# in case the cache is too small to hold all elements when traversing. +CFG_RPMB_FS_CACHE_ENTRIES ?= 0 + # Enables RPMB key programming by the TEE, in case the RPMB partition has not # been configured yet. # !!! Security warning !!! |