joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers secure_allocator.c Source File

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 }