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 24static 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 */ 41struct memTable * 42getTable(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 */ 54static 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 */ 76void 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 */ 106TSS_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 136TSS_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 160TSS_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 */ 184void * 185calloc_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 */ 231TSS_RESULT 232free_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 */ 261void * __no_optimize 262__tspi_memset(void *s, int c, size_t n) 263{ 264 return memset(s, c, n); 265} 266