Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MAX44000 PWM_Tone_Library nexpaq_mdk
Fork of LED_Demo by
secure_allocator.c
00001 /* 00002 * Copyright (c) 2016, ARM Limited, All Rights Reserved 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00006 * not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "rt_TypeDef.h" 00019 #include "rt_Memory.h" 00020 00021 #include "secure_allocator.h" 00022 #include "uvisor-lib/uvisor-lib.h" 00023 00024 #include <stdio.h> 00025 #include <stdlib.h> 00026 #include <string.h> 00027 00028 /* Use printf with caution inside malloc: printf may allocate memory itself, 00029 so using printf in malloc may lead to recursive calls! */ 00030 #define DPRINTF(...) {} 00031 00032 /* offsetof is a gcc built-in function, this is the manual implementation */ 00033 #define OFFSETOF(type, member) ((uint32_t) (&(((type *)(0))->member))) 00034 00035 /* Internal structure currently only contains the page table. */ 00036 typedef struct { 00037 UvisorPageTable table; 00038 } SecureAllocatorInternal; 00039 00040 static inline UvisorPageTable * table(SecureAllocator allocator) { 00041 return &(((SecureAllocatorInternal *) allocator)->table); 00042 } 00043 00044 SecureAllocator secure_allocator_create_with_pool( 00045 void * mem, 00046 size_t bytes) 00047 { 00048 SecureAllocatorInternal * allocator = mem; 00049 /* Signal that this is non-page allocated memory. */ 00050 allocator->table.page_size = bytes; 00051 allocator->table.page_count = 0; 00052 /* The internal rt_Memory MEMP structure must be placed AFTER table.page_origins[0] !!! */ 00053 size_t offset = OFFSETOF(SecureAllocatorInternal, table.page_origins) + sizeof(((UvisorPageTable) {0}).page_origins); 00054 /* Create MEMP structure inside the memory. */ 00055 if (rt_init_mem(mem + offset, bytes - offset)) { 00056 /* Abort if failed. */ 00057 DPRINTF("secure_allocator_create_with_pool: MEMP allocator creation failed\n\n"); 00058 return NULL; 00059 } 00060 /* Remember the MEMP pointer though. */ 00061 allocator->table.page_origins[0] = mem + offset; 00062 DPRINTF("secure_allocator_create_with_pool: Created MEMP allocator %p with offset %d\n\n", mem + offset, offset); 00063 return allocator; 00064 } 00065 00066 SecureAllocator secure_allocator_create_with_pages( 00067 size_t size, 00068 size_t maximum_malloc_size) 00069 { 00070 const uint32_t page_size = uvisor_get_page_size(); 00071 /* The rt_Memory allocator puts one MEMP structure at both the 00072 * beginning and end of the memory pool. */ 00073 const size_t block_overhead = 2 * sizeof(MEMP); 00074 const size_t page_size_with_overhead = page_size + block_overhead; 00075 /* Calculate the integer part of required the page count. */ 00076 size_t page_count = size / page_size_with_overhead; 00077 /* Add another page if the remainder is not zero. */ 00078 if (size - page_count * page_size_with_overhead) { 00079 page_count++; 00080 } 00081 DPRINTF("secure_allocator_create_with_pages: Requesting %u pages for at least %uB\n", page_count, size); 00082 00083 /* Compute the maximum allocation within our blocks. */ 00084 size_t maximum_allocation_size = page_size - block_overhead; 00085 /* If the required maximum allocation is larger than we can provide, abort. */ 00086 if (maximum_malloc_size > maximum_allocation_size) { 00087 DPRINTF("secure_allocator_create_with_pages: Maximum allocation request %uB is larger then available %uB\n\n", maximum_malloc_size, maximum_allocation_size); 00088 return NULL; 00089 } 00090 00091 /* Compute the required memory size for the page table. */ 00092 size_t allocator_type_size = sizeof(SecureAllocatorInternal); 00093 /* Add size for each additional page. */ 00094 allocator_type_size += (page_count - 1) * sizeof(((UvisorPageTable) {0}).page_origins); 00095 /* Allocate this much memory. */ 00096 SecureAllocatorInternal * const allocator = malloc(allocator_type_size); 00097 /* If malloc failed, abort. */ 00098 if (allocator == NULL) { 00099 DPRINTF("secure_allocator_create_with_pages: SecureAllocatorInternal failed to be allocated!\n\n"); 00100 return NULL; 00101 } 00102 00103 /* Prepare the page table. */ 00104 allocator->table.page_size = page_size; 00105 allocator->table.page_count = page_count; 00106 /* Get me some pages. */ 00107 if (uvisor_page_malloc((UvisorPageTable *) &(allocator->table))) { 00108 free(allocator); 00109 DPRINTF("secure_allocator_create_with_pages: Not enough free pages available!\n\n"); 00110 return NULL; 00111 } 00112 00113 /* Initialize a MEMP structure in all pages. */ 00114 for(size_t ii = 0; ii < page_count; ii++) { 00115 /* Add each page as a pool. */ 00116 rt_init_mem(allocator->table.page_origins[ii], page_size); 00117 DPRINTF("secure_allocator_create_with_pages: Created MEMP allocator %p with offset %d\n", allocator->table.page_origins[ii], 0); 00118 } 00119 DPRINTF("\n"); 00120 /* Aaaand across the line. */ 00121 return (SecureAllocator) allocator; 00122 } 00123 00124 int secure_allocator_destroy( 00125 SecureAllocator allocator) 00126 { 00127 DPRINTF("secure_allocator_destroy: Destroying MEMP allocator at %p\n", table(allocator)->page_origins[0]); 00128 00129 /* Check if we are working on statically allocated memory. */ 00130 SecureAllocatorInternal * alloc = (SecureAllocatorInternal * const) allocator; 00131 if (alloc->table.page_count == 0) { 00132 DPRINTF("secure_allocator_destroy: %p is not page-backed memory, not freeing!\n", allocator); 00133 return -1; 00134 } 00135 00136 /* Free all pages. */ 00137 if (uvisor_page_free(&(alloc->table))) { 00138 DPRINTF("secure_allocator_destroy: Unable to free pages!\n\n"); 00139 return -1; 00140 } 00141 00142 /* Free the allocator structure. */ 00143 free(allocator); 00144 00145 DPRINTF("\n"); 00146 return 0; 00147 } 00148 00149 void * secure_malloc( 00150 SecureAllocator allocator, 00151 size_t size) 00152 { 00153 size_t index = 0; 00154 do { 00155 /* Search in this page. */ 00156 void * mem = rt_alloc_mem(table(allocator)->page_origins[index], size); 00157 /* Return if we found something. */ 00158 if (mem) { 00159 DPRINTF("secure_malloc: Found %4uB in page %u at %p\n", size, index, mem); 00160 return mem; 00161 } 00162 /* Otherwise, go to the next page. */ 00163 index++; 00164 } /* Continue search if more pages are available. */ 00165 while (index < table(allocator)->page_count); 00166 00167 DPRINTF("secure_malloc: Out of memory in allocator %p \n", allocator); 00168 /* We found nothing. */ 00169 return NULL; 00170 } 00171 00172 void * secure_realloc( 00173 SecureAllocator allocator, 00174 void * ptr, 00175 size_t new_size) 00176 { 00177 /* TODO: THIS IS A NAIVE IMPLEMENTATION, which always allocates new 00178 memory, and copies the memory, then frees the old memory. */ 00179 00180 /* Allocate new memory. */ 00181 void * new_ptr = secure_malloc(allocator, new_size); 00182 /* If memory allocation failed, abort. */ 00183 if (new_ptr == NULL) { 00184 return NULL; 00185 } 00186 00187 /* Passing NULL as ptr is legal, realloc acts as malloc then. */ 00188 if (ptr) { 00189 /* Get the size of the ptr memory. */ 00190 size_t size = ((MEMP *) ((uint32_t) ptr - sizeof(MEMP)))->len; 00191 /* Copy the memory to the new location, min(new_size, size). */ 00192 memcpy(new_ptr, ptr, new_size < size ? new_size : size); 00193 /* Free the previous memory. */ 00194 secure_free(allocator, ptr); 00195 } 00196 return new_ptr; 00197 } 00198 00199 void secure_free( 00200 SecureAllocator allocator, 00201 void * ptr) 00202 { 00203 size_t index = 0; 00204 do { 00205 /* Search in this page. */ 00206 int ret = rt_free_mem(table(allocator)->page_origins[index], ptr); 00207 /* Return if free was successful. */ 00208 if (ret == 0) { 00209 DPRINTF("secure_free: Freed %p in page %u.\n", ptr, index); 00210 return; 00211 } 00212 /* Otherwise, go to the next page. */ 00213 index++; 00214 } /* Continue search if more pages are available. */ 00215 while (index < table(allocator)->page_count); 00216 00217 DPRINTF("secure_free: %p not found in allocator %p!\n", ptr, allocator); 00218 /* We found nothing. */ 00219 return; 00220 }
Generated on Tue Jul 12 2022 12:28:48 by
