Home | History | Annotate | Line # | Download | only in tspi
      1 
      2 /*
      3  * Licensed Materials - Property of IBM
      4  *
      5  * trousers - An open source TCG Software Stack
      6  *
      7  * (C) Copyright International Business Machines Corp. 2004
      8  *
      9  */
     10 
     11 
     12 #include <stdlib.h>
     13 #include <stdio.h>
     14 #include <string.h>
     15 
     16 #include "trousers/tss.h"
     17 #include "trousers_types.h"
     18 #include "spi_utils.h"
     19 #include "capabilities.h"
     20 #include "memmgr.h"
     21 #include "tsplog.h"
     22 #include "obj.h"
     23 
     24 static struct memTable *
     25 __tspi_createTable()
     26 {
     27 	struct memTable *table = NULL;
     28 	/*
     29 	 * No table has yet been created to hold the memory allocations of
     30 	 * this context, so we need to create one
     31 	 */
     32 	table = calloc(1, sizeof(struct memTable));
     33 	if (table == NULL) {
     34 		LogError("malloc of %zd bytes failed.", sizeof(struct memTable));
     35 		return NULL;
     36 	}
     37 	return (table);
     38 }
     39 
     40 /* caller needs to lock memtable lock */
     41 struct memTable *
     42 getTable(TSS_HCONTEXT tspContext)
     43 {
     44 	struct memTable *tmp;
     45 
     46 	for (tmp = SpiMemoryTable; tmp; tmp = tmp->nextTable)
     47 		if (tmp->tspContext == tspContext)
     48 			return tmp;
     49 
     50 	return NULL;
     51 }
     52 
     53 /* caller needs to lock memtable lock */
     54 static void
     55 __tspi_addTable(struct memTable *new)
     56 {
     57 	struct memTable *tmp = SpiMemoryTable;
     58 
     59 	/* base case, this is the first table */
     60 	if (SpiMemoryTable == NULL) {
     61 		SpiMemoryTable = new;
     62 		return;
     63 	}
     64 
     65 	/* else add @new onto the end */
     66 	for (; tmp; tmp = tmp->nextTable)
     67 		if (tmp->nextTable == NULL) {
     68 			tmp->nextTable = new;
     69 			break;
     70 		}
     71 }
     72 
     73 /* caller needs to lock memtable lock and be sure the context mem slot for
     74  * @tspContext exists before calling.
     75  */
     76 void
     77 __tspi_addEntry(TSS_HCONTEXT tspContext, struct memEntry *new)
     78 {
     79 	struct memTable *tmp = getTable(tspContext);
     80 	struct memEntry *tmp_entry;
     81 
     82 	if (tmp == NULL) {
     83 		if ((tmp = __tspi_createTable()) == NULL)
     84 			return;
     85 		tmp->tspContext = tspContext;
     86 		__tspi_addTable(tmp);
     87 	}
     88 
     89 	tmp_entry = tmp->entries;
     90 
     91 	if (tmp->entries == NULL) {
     92 		tmp->entries = new;
     93 		return;
     94 	}
     95 
     96 	/* else tack @new onto the end */
     97 	for (; tmp_entry; tmp_entry = tmp_entry->nextEntry) {
     98 		if (tmp_entry->nextEntry == NULL) {
     99 			tmp_entry->nextEntry = new;
    100 			break;
    101 		}
    102 	}
    103 }
    104 
    105 /* caller needs to lock memtable lock */
    106 TSS_RESULT
    107 __tspi_freeTable(TSS_HCONTEXT tspContext)
    108 {
    109 	struct memTable *prev = NULL, *index = NULL, *next = NULL;
    110 	struct memEntry *entry = NULL, *entry_next = NULL;
    111 
    112 	for(index = SpiMemoryTable; index; index = index->nextTable) {
    113 		next = index->nextTable;
    114 		if (index->tspContext == tspContext) {
    115 			for (entry = index->entries; entry; entry = entry_next) {
    116 				/* this needs to be set before we do free(entry) */
    117 				entry_next = entry->nextEntry;
    118 				free(entry->memPointer);
    119 				free(entry);
    120 			}
    121 
    122 			if (prev != NULL)
    123 				prev->nextTable = next;
    124 			else
    125 				SpiMemoryTable = NULL;
    126 
    127 			free(index);
    128 			break;
    129 		}
    130 		prev = index;
    131 	}
    132 
    133 	return TSS_SUCCESS;
    134 }
    135 
    136 TSS_RESULT
    137 __tspi_freeEntry(struct memTable *table, void *pointer)
    138 {
    139 	struct memEntry *index = NULL;
    140 	struct memEntry *prev = NULL;
    141 	struct memEntry *toKill = NULL;
    142 
    143 	for (index = table->entries; index; prev = index, index = index->nextEntry) {
    144 		if (index->memPointer == pointer) {
    145 			toKill = index;
    146 			if (prev == NULL)
    147 				table->entries = toKill->nextEntry;
    148 			else
    149 				prev->nextEntry = toKill->nextEntry;
    150 
    151 			free(pointer);
    152 			free(toKill);
    153 			return TSS_SUCCESS;
    154 		}
    155 	}
    156 
    157 	return TSPERR(TSS_E_INVALID_RESOURCE);
    158 }
    159 
    160 TSS_RESULT
    161 __tspi_add_mem_entry(TSS_HCONTEXT tspContext, void *allocd_mem)
    162 {
    163 	struct memEntry *newEntry = calloc(1, sizeof(struct memEntry));
    164 	if (newEntry == NULL) {
    165 		LogError("malloc of %zd bytes failed.", sizeof(struct memEntry));
    166 		return TSPERR(TSS_E_OUTOFMEMORY);
    167 	}
    168 
    169 	newEntry->memPointer = allocd_mem;
    170 
    171 	MUTEX_LOCK(memtable_lock);
    172 
    173 	__tspi_addEntry(tspContext, newEntry);
    174 
    175 	MUTEX_UNLOCK(memtable_lock);
    176 
    177 	return TSS_SUCCESS;
    178 }
    179 
    180 /*
    181  * calloc_tspi will be called by functions outside of this file. All locking
    182  * is done here.
    183  */
    184 void *
    185 calloc_tspi(TSS_HCONTEXT tspContext, UINT32 howMuch)
    186 {
    187 	struct memTable *table = NULL;
    188 	struct memEntry *newEntry = NULL;
    189 
    190 	MUTEX_LOCK(memtable_lock);
    191 
    192 	table = getTable(tspContext);
    193 	if (table == NULL) {
    194 		if ((table = __tspi_createTable()) == NULL) {
    195 			MUTEX_UNLOCK(memtable_lock);
    196 			return NULL;
    197 		}
    198 		table->tspContext = tspContext;
    199 		__tspi_addTable(table);
    200 	}
    201 
    202 	newEntry = calloc(1, sizeof(struct memEntry));
    203 	if (newEntry == NULL) {
    204 		LogError("malloc of %zd bytes failed.", sizeof(struct memEntry));
    205 		MUTEX_UNLOCK(memtable_lock);
    206 		return NULL;
    207 	}
    208 
    209 	newEntry->memPointer = calloc(1, howMuch);
    210 	if (newEntry->memPointer == NULL) {
    211 		LogError("malloc of %d bytes failed.", howMuch);
    212 		free(newEntry);
    213 		MUTEX_UNLOCK(memtable_lock);
    214 		return NULL;
    215 	}
    216 
    217 	/* this call must happen inside the lock or else another thread could
    218 	 * remove the context mem slot, causing a segfault
    219 	 */
    220 	__tspi_addEntry(tspContext, newEntry);
    221 
    222 	MUTEX_UNLOCK(memtable_lock);
    223 
    224 	return newEntry->memPointer;
    225 }
    226 
    227 /*
    228  * free_tspi will be called by functions outside of this file. All locking
    229  * is done here.
    230  */
    231 TSS_RESULT
    232 free_tspi(TSS_HCONTEXT tspContext, void *memPointer)
    233 {
    234 	struct memTable *index;
    235 	TSS_RESULT result;
    236 
    237 	MUTEX_LOCK(memtable_lock);
    238 
    239 	if (memPointer == NULL) {
    240 		result = __tspi_freeTable(tspContext);
    241 		MUTEX_UNLOCK(memtable_lock);
    242 		return result;
    243 	}
    244 
    245 	if ((index = getTable(tspContext)) == NULL) {
    246 		MUTEX_UNLOCK(memtable_lock);
    247 		/* Tspi_Context_FreeMemory checks that the TSP context is good before calling us,
    248 		 * so we can be sure that the problem is with memPointer */
    249 		return TSPERR(TSS_E_INVALID_RESOURCE);
    250 	}
    251 
    252 	/* just free one entry */
    253 	result = __tspi_freeEntry(index, memPointer);
    254 
    255 	MUTEX_UNLOCK(memtable_lock);
    256 
    257 	return result;
    258 }
    259 
    260 /* definition for a memset that cannot be optimized away */
    261 void * __no_optimize
    262 __tspi_memset(void *s, int c, size_t n)
    263 {
    264 	return memset(s, c, n);
    265 }
    266