1 /*
2  * Copyright © 2014 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *     Wei Lin<wei.w.lin@intel.com>
26  *     Yuting Yang<yuting.yang@intel.com>
27  */
28 
29 #include "os_utilities.h"
30 #include "os_util_debug.h"
31 #include <fcntl.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <time.h>
35 #include <sys/stat.h>
36 #include <dlfcn.h>
37 #include <math.h>
38 
39 #include <sys/ipc.h>
40 #include <sys/types.h>
41 #include <sys/sem.h>
42 #include <signal.h>
43 #include "string.h"
44 #include <unistd.h>
45 
46 INT32 GenOsMemAllocCounter;
47 #define GENOS_MEMNINJA_ALLOC_MESSAGE(ptr, size)                   \
48    GENOS_OS_VERBOSEMESSAGE(                                                                     \
49        "<MemNinjaSysAllocPtr memPtr = \"%d\" size = \"%d\" memType = \"Sys\"/>.", ptr, size); \
50    GENOS_OS_VERBOSEMESSAGE(                                                                     \
51        "<MemNinjaSysLastFuncCall memPtr = \"%d\" functionName = \"%s\" file = \"%s\" "    \
52        "memType = \"Sys\" line = \"%d\"/>.", ptr, __func__, __FILE__, __LINE__);
53 
54 #define GENOS_MEMNINJA_FREE_MESSAGE(ptr)                                                        \
55    GENOS_OS_VERBOSEMESSAGE("GenOsMemAllocCounter = %d, Addr = 0x%x.", GenOsMemAllocCounter, ptr);   \
56    GENOS_OS_VERBOSEMESSAGE("<MemNinjaSysFreePtr memPtr = \"%d\" memType = \"Sys\"/>.", ptr);
57 
58 #define _aligned_malloc(size, alignment)  aligned_alloc(alignment, size)
59 #define _aligned_free(ptr)                free(ptr)
60 
GENOS_AlignedAllocMemory(SIZE_T size,SIZE_T alignment)61 PVOID GENOS_AlignedAllocMemory(SIZE_T size, SIZE_T alignment)
62 {
63 	PVOID ptr;
64 
65 	ptr = _aligned_malloc(size, alignment);
66 
67 	GENOS_OS_ASSERT(ptr != NULL);
68 
69 	if (ptr != NULL) {
70 		GENOS_MEMNINJA_ALLOC_MESSAGE(ptr, size);
71 		GenOsMemAllocCounter++;
72 	}
73 
74 	return ptr;
75 }
76 
GENOS_AlignedFreeMemory(PVOID ptr)77 VOID GENOS_AlignedFreeMemory(PVOID ptr)
78 {
79 	GENOS_OS_ASSERT(ptr != NULL);
80 
81 	if (ptr != NULL) {
82 		GenOsMemAllocCounter--;
83 
84 		GENOS_MEMNINJA_FREE_MESSAGE(ptr);
85 
86 		_aligned_free(ptr);
87 	}
88 }
89 
GENOS_AllocMemory(SIZE_T size)90 PVOID GENOS_AllocMemory(SIZE_T size)
91 {
92 	PVOID ptr;
93 
94 	ptr = malloc(size);
95 
96 	GENOS_OS_ASSERT(ptr != NULL);
97 
98 	if (ptr != NULL) {
99 		GENOS_MEMNINJA_ALLOC_MESSAGE(ptr, size);
100 		GenOsMemAllocCounter++;
101 	}
102 
103 	return ptr;
104 }
105 
GENOS_AllocAndZeroMemory(SIZE_T size)106 PVOID GENOS_AllocAndZeroMemory(SIZE_T size)
107 {
108 	PVOID ptr;
109 
110 	ptr = malloc(size);
111 
112 	GENOS_OS_ASSERT(ptr != NULL);
113 
114 	if (ptr != NULL) {
115 		GENOS_ZeroMemory(ptr, size);
116 
117 		GENOS_MEMNINJA_ALLOC_MESSAGE(ptr, size);
118 
119 		GenOsMemAllocCounter++;
120 	}
121 
122 	return ptr;
123 }
124 
GENOS_FreeMemory(PVOID ptr)125 VOID GENOS_FreeMemory(PVOID ptr)
126 {
127 	if (ptr != NULL) {
128 		GenOsMemAllocCounter--;
129 
130 		GENOS_MEMNINJA_FREE_MESSAGE(ptr);
131 
132 		free(ptr);
133 	}
134 }
135 
GENOS_ZeroMemory(PVOID pDestination,SIZE_T stLength)136 VOID GENOS_ZeroMemory(PVOID pDestination, SIZE_T stLength)
137 {
138 	GENOS_OS_ASSERT(pDestination != NULL);
139 
140 	if (pDestination != NULL) {
141 		memset(pDestination, 0, stLength);
142 	}
143 }
144 
GENOS_FillMemory(PVOID pDestination,SIZE_T stLength,UINT8 bFill)145 VOID GENOS_FillMemory(PVOID pDestination, SIZE_T stLength, UINT8 bFill)
146 {
147 	GENOS_OS_ASSERT(pDestination != NULL);
148 
149 	if (pDestination != NULL) {
150 		memset(pDestination, bFill, stLength);
151 	}
152 }
153 
GENOS_SecureStrcat(PCHAR strDestination,SIZE_T numberOfElements,const PCCHAR strSource)154 GENOS_STATUS GENOS_SecureStrcat(PCHAR strDestination, SIZE_T numberOfElements,
155 				const PCCHAR strSource)
156 {
157 	if ((strDestination == NULL) || (strSource == NULL)) {
158 		return GENOS_STATUS_INVALID_PARAMETER;
159 	}
160 
161 	if (strnlen(strDestination, numberOfElements) == numberOfElements) {
162 		return GENOS_STATUS_INVALID_PARAMETER;
163 	}
164 
165 	if ((strlen(strDestination) + strlen(strSource)) >= numberOfElements) {
166 		return GENOS_STATUS_INVALID_PARAMETER;
167 	}
168 
169 	strcat(strDestination, strSource);
170 	return GENOS_STATUS_SUCCESS;
171 }
172 
GENOS_SecureStrtok(PCHAR strToken,PCCHAR strDelimit,PCHAR * contex)173 PCHAR GENOS_SecureStrtok(PCHAR strToken, PCCHAR strDelimit, PCHAR * contex)
174 {
175 	return strtok_r(strToken, strDelimit, contex);
176 }
177 
GENOS_SecureStrcpy(PCHAR strDestination,SIZE_T numberOfElements,const PCCHAR strSource)178 GENOS_STATUS GENOS_SecureStrcpy(PCHAR strDestination, SIZE_T numberOfElements,
179 				const PCCHAR strSource)
180 {
181 	if ((strDestination == NULL) || (strSource == NULL)) {
182 		return GENOS_STATUS_INVALID_PARAMETER;
183 	}
184 
185 	if (numberOfElements <= strlen(strSource)) {
186 		return GENOS_STATUS_INVALID_PARAMETER;
187 	}
188 
189 	strcpy(strDestination, strSource);
190 
191 	return GENOS_STATUS_SUCCESS;
192 }
193 
GENOS_SecureMemcpy(PVOID pDestination,SIZE_T dstLength,PCVOID pSource,SIZE_T srcLength)194 GENOS_STATUS GENOS_SecureMemcpy(PVOID pDestination, SIZE_T dstLength,
195 				PCVOID pSource, SIZE_T srcLength)
196 {
197 	if ((pDestination == NULL) || (pSource == NULL)) {
198 		return GENOS_STATUS_INVALID_PARAMETER;
199 	}
200 
201 	if (dstLength < srcLength) {
202 		return GENOS_STATUS_INVALID_PARAMETER;
203 	}
204 
205 	memcpy(pDestination, pSource, srcLength);
206 
207 	return GENOS_STATUS_SUCCESS;
208 }
209 
GENOS_SecureStringPrint(PCHAR buffer,SIZE_T bufSize,SIZE_T length,const PCCHAR format,...)210 INT32 GENOS_SecureStringPrint(PCHAR buffer, SIZE_T bufSize, SIZE_T length,
211 			      const PCCHAR format, ...)
212 {
213 	INT32 iRet = -1;
214 	va_list var_args;
215 
216 	if ((buffer == NULL) || (format == NULL) || (bufSize < length)) {
217 		return iRet;
218 	}
219 
220 	va_start(var_args, format);
221 
222 	iRet = vsnprintf(buffer, length, format, var_args);
223 
224 	va_end(var_args);
225 
226 	return iRet;
227 }
228 
GENOS_SecureVStringPrint(PCHAR buffer,SIZE_T bufSize,SIZE_T length,const PCCHAR format,va_list var_args)229 GENOS_STATUS GENOS_SecureVStringPrint(PCHAR buffer, SIZE_T bufSize,
230 				      SIZE_T length, const PCCHAR format,
231 				      va_list var_args)
232 {
233 	if ((buffer == NULL) || (format == NULL) || (bufSize < length)) {
234 		return GENOS_STATUS_INVALID_PARAMETER;
235 	}
236 
237 	vsnprintf(buffer, length, format, var_args);
238 
239 	return GENOS_STATUS_SUCCESS;
240 }
241 
GENOS_CloseHandle(HANDLE hObject)242 BOOL GENOS_CloseHandle(HANDLE hObject)
243 {
244 	BOOL iRet = FALSE;
245 
246 	if (hObject != 0) {
247 		close((INT32) hObject);
248 		iRet = TRUE;
249 	}
250 
251 	return iRet;
252 }
253 
GENOS_LoadLibrary(const PCCHAR lpLibFileName,PHMODULE phModule)254 GENOS_STATUS GENOS_LoadLibrary(const PCCHAR lpLibFileName, PHMODULE phModule)
255 {
256 	if (lpLibFileName == NULL) {
257 		return GENOS_STATUS_INVALID_PARAMETER;
258 	}
259 
260 	*phModule = dlopen((const PCHAR)lpLibFileName, RTLD_LAZY);
261 
262 	return ((*phModule !=
263 		 NULL) ? GENOS_STATUS_SUCCESS :
264 		GENOS_STATUS_LOAD_LIBRARY_FAILED);
265 }
266 
GENOS_FreeLibrary(HMODULE hLibModule)267 BOOL GENOS_FreeLibrary(HMODULE hLibModule)
268 {
269 	UINT32 iRet = 10;
270 
271 	if (hLibModule != NULL) {
272 		iRet = dlclose(hLibModule);
273 	}
274 	return (iRet == 0) ? TRUE : FALSE;
275 }
276 
GENOS_GetProcAddress(HMODULE hModule,PCCHAR lpProcName)277 PVOID GENOS_GetProcAddress(HMODULE hModule, PCCHAR lpProcName)
278 {
279 	PVOID pSym = NULL;
280 
281 	if (hModule == NULL || lpProcName == NULL) {
282 		GENOS_OS_ASSERTMESSAGE("Invalid parameter.");
283 	} else {
284 		pSym = dlsym(hModule, lpProcName);
285 	}
286 
287 	return pSym;
288 }
289 
GENOS_QueryPerformanceFrequency(PUINT64 pFrequency)290 BOOL GENOS_QueryPerformanceFrequency(PUINT64 pFrequency)
291 {
292 	struct timespec Res;
293 	INT32 iRet;
294 
295 	if (pFrequency == NULL) {
296 		return FALSE;
297 	}
298 
299 	if ((iRet = clock_getres(CLOCK_MONOTONIC, &Res)) != 0) {
300 		return FALSE;
301 	}
302 	if (Res.tv_sec != 0) {
303 		return FALSE;
304 	}
305 	*pFrequency = (UINT64) ((1000 * 1000 * 1000) / Res.tv_nsec);
306 
307 	return TRUE;
308 }
309 
GENOS_QueryPerformanceCounter(PUINT64 pPerformanceCount)310 BOOL GENOS_QueryPerformanceCounter(PUINT64 pPerformanceCount)
311 {
312 	struct timespec Res;
313 	struct timespec t;
314 	INT32 iRet;
315 
316 	if (pPerformanceCount == NULL) {
317 		return FALSE;
318 	}
319 	if ((iRet = clock_getres(CLOCK_MONOTONIC, &Res)) != 0) {
320 		return FALSE;
321 	}
322 	if (Res.tv_sec != 0) {
323 		return FALSE;
324 	}
325 	if ((iRet = clock_gettime(CLOCK_MONOTONIC, &t)) != 0) {
326 		return FALSE;
327 	}
328 	*pPerformanceCount =
329 	    (UINT64) ((1000 * 1000 * 1000 * t.tv_sec +
330 		       t.tv_nsec) / Res.tv_nsec);
331 
332 	return TRUE;
333 }
334 
GENOS_Sleep(UINT32 mSec)335 VOID GENOS_Sleep(UINT32 mSec)
336 {
337 	usleep(1000 * mSec);
338 }
339 
GENOS_CreateThread(PVOID ThreadFunction,PVOID ThreadData)340 GENOS_THREADHANDLE GENOS_CreateThread(PVOID ThreadFunction, PVOID ThreadData)
341 {
342 	GENOS_THREADHANDLE Thread;
343 
344 	if (0 !=
345 	    pthread_create(&Thread, NULL, (VOID * (*)(PVOID)) ThreadFunction,
346 			   ThreadData)) {
347 		Thread = 0;
348 	}
349 
350 	return Thread;
351 }
352 
GENOS_CreateMutex()353 PGENOS_MUTEX GENOS_CreateMutex()
354 {
355 	PGENOS_MUTEX pMutex;
356 
357 	pMutex = (PGENOS_MUTEX) GENOS_AllocMemory(sizeof(*pMutex));
358 	if (pMutex != NULL) {
359 		if (pthread_mutex_init(pMutex, NULL)) {
360 			pMutex = NULL;
361 		}
362 	}
363 
364 	return pMutex;
365 }
366 
GENOS_DestroyMutex(PGENOS_MUTEX pMutex)367 HRESULT GENOS_DestroyMutex(PGENOS_MUTEX pMutex)
368 {
369 	HRESULT hr = S_OK;
370 
371 	if (pMutex) {
372 		if (pthread_mutex_destroy(pMutex)) {
373 			hr = E_FAIL;
374 		}
375 		GENOS_FreeMemory(pMutex);
376 	}
377 
378 	return hr;
379 }
380 
GENOS_LockMutex(PGENOS_MUTEX pMutex)381 HRESULT GENOS_LockMutex(PGENOS_MUTEX pMutex)
382 {
383 	HRESULT hr = S_OK;
384 
385 	if (pthread_mutex_lock(pMutex)) {
386 		hr = E_FAIL;
387 	}
388 
389 	return hr;
390 }
391 
GENOS_UnlockMutex(PGENOS_MUTEX pMutex)392 HRESULT GENOS_UnlockMutex(PGENOS_MUTEX pMutex)
393 {
394 	HRESULT hr = S_OK;
395 
396 	if (pthread_mutex_unlock(pMutex)) {
397 		hr = E_FAIL;
398 	}
399 
400 	return hr;
401 }
402 
GENOS_CreateSemaphore(UINT uiInitialCount,UINT uiMaximumCount)403 PGENOS_SEMAPHORE GENOS_CreateSemaphore(UINT uiInitialCount, UINT uiMaximumCount)
404 {
405 	PGENOS_SEMAPHORE pSemaphore = NULL;
406 
407 	pSemaphore = (PGENOS_SEMAPHORE) GENOS_AllocMemory(sizeof(*pSemaphore));
408 	if (sem_init(pSemaphore, 0, uiInitialCount)) {
409 		pSemaphore = NULL;
410 	}
411 
412 	return pSemaphore;
413 }
414 
GENOS_DestroySemaphore(PGENOS_SEMAPHORE pSemaphore)415 HRESULT GENOS_DestroySemaphore(PGENOS_SEMAPHORE pSemaphore)
416 {
417 	GENOS_SafeFreeMemory(pSemaphore);
418 
419 	return S_OK;
420 }
421 
GENOS_WaitSemaphore(PGENOS_SEMAPHORE pSemaphore,UINT uiMilliseconds)422 HRESULT GENOS_WaitSemaphore(PGENOS_SEMAPHORE pSemaphore, UINT uiMilliseconds)
423 {
424 	HRESULT hr = S_OK;
425 
426 	if (uiMilliseconds == INFINITE) {
427 		if (sem_wait(pSemaphore)) {
428 			hr = E_FAIL;
429 		}
430 	} else {
431 		struct timespec time = {
432 			(LONG) uiMilliseconds / 1000000,
433 			((LONG) uiMilliseconds % 1000000) * 1000
434 		};
435 
436 		if (sem_timedwait(pSemaphore, &time)) {
437 			hr = E_FAIL;
438 		}
439 	}
440 
441 	return hr;
442 }
443 
GENOS_PostSemaphore(PGENOS_SEMAPHORE pSemaphore,UINT uiPostCount)444 HRESULT GENOS_PostSemaphore(PGENOS_SEMAPHORE pSemaphore, UINT uiPostCount)
445 {
446 	HRESULT hr = S_OK;
447 
448 	if (uiPostCount > 0) {
449 		while (uiPostCount--) {
450 			if (sem_post(pSemaphore)) {
451 				hr = E_FAIL;
452 				break;
453 			}
454 		}
455 	} else {
456 		hr = E_FAIL;
457 	}
458 
459 	return hr;
460 }
461 
GENOS_StatusToOsResult(GENOS_STATUS eStatus)462 VAStatus GENOS_StatusToOsResult(GENOS_STATUS eStatus)
463 {
464 	switch (eStatus) {
465 	case GENOS_STATUS_SUCCESS:
466 		return VA_STATUS_SUCCESS;
467 	case GENOS_STATUS_NO_SPACE:
468 		return VA_STATUS_ERROR_ALLOCATION_FAILED;
469 	case GENOS_STATUS_INVALID_PARAMETER:
470 		return VA_STATUS_ERROR_INVALID_PARAMETER;
471 	case GENOS_STATUS_INVALID_HANDLE:
472 		return VA_STATUS_ERROR_INVALID_BUFFER;
473 	case GENOS_STATUS_NULL_POINTER:
474 		return VA_STATUS_ERROR_INVALID_CONTEXT;
475 	default:
476 		return VA_STATUS_ERROR_OPERATION_FAILED;
477 	}
478 
479 	return VA_STATUS_ERROR_OPERATION_FAILED;
480 }
481 
OsResultToGENOS_Status(VAStatus eResult)482 GENOS_STATUS OsResultToGENOS_Status(VAStatus eResult)
483 {
484 	switch (eResult) {
485 	case VA_STATUS_SUCCESS:
486 		return GENOS_STATUS_SUCCESS;
487 	case VA_STATUS_ERROR_ALLOCATION_FAILED:
488 		return GENOS_STATUS_NO_SPACE;
489 	case VA_STATUS_ERROR_INVALID_PARAMETER:
490 		return GENOS_STATUS_INVALID_PARAMETER;
491 	case VA_STATUS_ERROR_INVALID_BUFFER:
492 		return GENOS_STATUS_INVALID_HANDLE;
493 	case VA_STATUS_ERROR_INVALID_CONTEXT:
494 		return GENOS_STATUS_NULL_POINTER;
495 	default:
496 		return GENOS_STATUS_UNKNOWN;
497 	}
498 
499 	return GENOS_STATUS_UNKNOWN;
500 }
501