1 /*
2 * Copyright (c) 2019-2022, 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 "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file        mos_utilities_specific.cpp
24 //! \brief       This module implements the MOS wrapper functions for Linux/Android
25 //!
26 
27 #include <fcntl.h>     // open
28 #include <stdlib.h>    // atoi
29 #include <string.h>    // strlen, strcat, etc.
30 #include <errno.h>     // strerror(errno)
31 #include <time.h>      // get_clocktime
32 #include <dlfcn.h>     // dlopen, dlsym, dlclose
33 #include <unistd.h>
34 #include <signal.h>
35 #include <unistd.h>  // fork
36 #include <algorithm>
37 #include <sys/types.h>
38 #include <sys/stat.h>  // fstat
39 #include <sys/ipc.h>  // System V IPC
40 #include <sys/types.h>
41 #include <sys/sem.h>
42 #include <sys/mman.h>
43 #include "mos_user_setting.h"
44 #include "mos_utilities_specific.h"
45 #include "mos_utilities.h"
46 #include "mos_util_debug.h"
47 #include "inttypes.h"
48 
49 int32_t g_mosMemAllocCounter         = 0;
50 int32_t g_mosMemAllocFakeCounter     = 0;
51 int32_t g_mosMemAllocCounterGfx      = 0;
52 uint8_t g_mosUltFlag                 = 0;
53 int32_t g_mosMemAllocIndex           = 0;
54 
55 int32_t *MosUtilities::m_mosMemAllocCounter       = &g_mosMemAllocCounter;
56 int32_t *MosUtilities::m_mosMemAllocFakeCounter   = &g_mosMemAllocFakeCounter;
57 int32_t *MosUtilities::m_mosMemAllocCounterGfx    = &g_mosMemAllocCounterGfx;
58 uint8_t *MosUtilities::m_mosUltFlag               = &g_mosUltFlag;
59 int32_t *MosUtilities::m_mosMemAllocIndex         = &g_mosMemAllocIndex;
60 
61 const char           *MosUtilitiesSpecificNext::m_szUserFeatureFile     = USER_FEATURE_FILE;
62 MOS_PUF_KEYLIST      MosUtilitiesSpecificNext::m_ufKeyList              = nullptr;
63 
64 #if (_DEBUG || _RELEASE_INTERNAL)
65 int32_t g_mosMemoryFailSimulateAllocCounter = 0;
66 int32_t *MosUtilities::m_mosAllocMemoryFailSimulateAllocCounter = &g_mosMemoryFailSimulateAllocCounter;
67 #endif
68 
MosGetTime()69 double MosUtilities::MosGetTime()
70 {
71     struct timespec ts = {};
72     clock_gettime(CLOCK_REALTIME, &ts);
73     return double(ts.tv_sec) * 1000000.0 + double(ts.tv_nsec) / 1000.0;
74 }
75 
76 //!
77 //! \brief Linux specific user feature define, used in MosUtilities::MosUserFeatureParsePath
78 //!        They can be unified with the win definitions, since they are identical.
79 //!
80 #define MOS_UF_SEPARATOR  "\\"
81 #define MOS_UFKEY_EXT     "UFKEY_EXTERNAL"
82 #define MOS_UFKEY_INT     "UFKEY_INTERNAL"
83 
84 //!
85 //! \brief trace setting definition
86 //!
87 #define TRACE_SETTING_PATH             "/dev/shm/GFX_MEDIA_TRACE"
88 #define TRACE_SETTING_SIZE             sizeof(MtControlData)
89 
90 //!
91 //! \brief Linux specific trace entry path and file description.
92 //!
93 const char *const MosUtilitiesSpecificNext::m_mosTracePath  = "/sys/kernel/debug/tracing/trace_marker_raw";
94 int32_t           MosUtilitiesSpecificNext::m_mosTraceFd    = -1;
95 uint64_t          MosUtilitiesSpecificNext::m_filterEnv     = 0;
96 uint32_t          MosUtilitiesSpecificNext::m_levelEnv      = 0;
97 
98 MosMutex          MosUtilitiesSpecificNext::m_userSettingMutex;
99 
100 //!
101 //! \brief trace event size definition
102 //!
103 #define TRACE_EVENT_MAX_SIZE           (3072)
104 #define TRACE_EVENT_HEADER_SIZE        (sizeof(uint32_t)*3)
105 #define TRACE_EVENT_MAX_DATA_SIZE      (TRACE_EVENT_MAX_SIZE - TRACE_EVENT_HEADER_SIZE - sizeof(uint16_t)) // Trace info data size section is in uint16_t
106 
107 //!
108 //! \brief for int64_t/uint64_t format print warning
109 //!
110 #if __WORDSIZE == 64
111 #define __MOS64_PREFIX    "l"
112 #else
113 #define __MOS64_PREFIX    "ll"
114 #endif
115 
116 #define MOSd64     __MOS64_PREFIX "d"
117 #define MOSu64     __MOS64_PREFIX "u"
118 
119 
120 //!
121 //! \brief mutex for mos utilities multi-threading protection
122 //!
123 MosMutex MosUtilities::m_mutexLock;
124 uint32_t MosUtilities::m_mosUtilInitCount = 0; // number count of mos utilities init
125 
126 MediaUserSettingsMgr *MosUtilities::m_mediaUserFeatureSpecific  = nullptr;
127 
MosSecureStrcat(char * strDestination,size_t numberOfElements,const char * const strSource)128 MOS_STATUS MosUtilities::MosSecureStrcat(char  *strDestination, size_t numberOfElements, const char * const strSource)
129 {
130     if ( (strDestination == nullptr) || (strSource == nullptr) )
131     {
132         return MOS_STATUS_INVALID_PARAMETER;
133     }
134 
135     if(strnlen(strDestination, numberOfElements) == numberOfElements) // Not null terminated
136     {
137         return MOS_STATUS_INVALID_PARAMETER;
138     }
139 
140     if((strlen(strDestination) + strlen(strSource)) >= numberOfElements) // checks space for null termination.
141     {
142         return MOS_STATUS_INVALID_PARAMETER;
143     }
144 
145     strcat(strDestination, strSource);
146     return MOS_STATUS_SUCCESS;
147 }
148 
MosSecureStrtok(char * strToken,const char * strDelimit,char ** contex)149 char  *MosUtilities::MosSecureStrtok(
150     char                *strToken,
151     const char          *strDelimit,
152     char                **contex)
153 {
154     return strtok_r(strToken, strDelimit, contex);
155 }
156 
MosSecureStrcpy(char * strDestination,size_t numberOfElements,const char * const strSource)157 MOS_STATUS MosUtilities::MosSecureStrcpy(char  *strDestination, size_t numberOfElements, const char * const strSource)
158 {
159     if ( (strDestination == nullptr) || (strSource == nullptr) )
160     {
161         return MOS_STATUS_INVALID_PARAMETER;
162     }
163 
164     if ( numberOfElements <= strlen(strSource) ) // checks if there is space for null termination after copy.
165     {
166         return MOS_STATUS_INVALID_PARAMETER;
167     }
168 
169     strcpy(strDestination, strSource);
170 
171     return MOS_STATUS_SUCCESS;
172 }
173 
MosSecureStrncpy(char * strDestination,size_t destSz,const char * const strSource,size_t maxCount)174 MOS_STATUS MosUtilities::MosSecureStrncpy(char *strDestination, size_t destSz, const char* const strSource, size_t maxCount)
175 {
176     if ( (strDestination == nullptr) || (strSource == nullptr) )
177     {
178         return MOS_STATUS_INVALID_PARAMETER;
179     }
180 
181     if ( destSz <= maxCount ) // checks if there is space for null termination after copy.
182     {
183         return MOS_STATUS_INVALID_PARAMETER;
184     }
185 
186     strncpy(strDestination, strSource, maxCount);
187 
188     return MOS_STATUS_SUCCESS;
189 }
190 
MosSecureMemcpy(void * pDestination,size_t dstLength,PCVOID pSource,size_t srcLength)191 MOS_STATUS MosUtilities::MosSecureMemcpy(void  *pDestination, size_t dstLength, PCVOID pSource, size_t srcLength)
192 {
193     if ( (pDestination == nullptr) || (pSource == nullptr) )
194     {
195         return MOS_STATUS_INVALID_PARAMETER;
196     }
197 
198     if ( dstLength < srcLength )
199     {
200         return MOS_STATUS_INVALID_PARAMETER;
201     }
202     if(pDestination != pSource)
203     {
204         memcpy(pDestination, pSource, srcLength);
205     }
206 
207     return MOS_STATUS_SUCCESS;
208 }
209 
MosSecureFileOpen(FILE ** ppFile,const char * filename,const char * mode)210 MOS_STATUS MosUtilities::MosSecureFileOpen(
211     FILE       **ppFile,
212     const char *filename,
213     const char *mode)
214 {
215     PFILE fp;
216 
217     if ((ppFile == nullptr) || (filename == nullptr) || (mode == nullptr))
218     {
219         return MOS_STATUS_INVALID_PARAMETER;
220     }
221 
222     fp = fopen(filename, mode);
223 
224     if (fp == nullptr)
225     {
226         *ppFile = nullptr;
227         return MOS_STATUS_FILE_OPEN_FAILED;
228     }
229     else
230     {
231         *ppFile = fp;
232         return MOS_STATUS_SUCCESS;
233     }
234 }
235 
MosSecureStringPrint(char * buffer,size_t bufSize,size_t length,const char * const format,...)236 int32_t MosUtilities::MosSecureStringPrint(char  *buffer, size_t bufSize, size_t length, const char * const format, ...)
237 {
238     int32_t iRet = -1;
239     va_list var_args;
240 
241     if((buffer == nullptr) || (format == nullptr) || (bufSize < length))
242     {
243         return iRet;
244     }
245 
246     va_start(var_args, format);
247 
248     iRet = vsnprintf(buffer, length, format, var_args);
249 
250     va_end(var_args);
251 
252     return iRet;
253 }
254 
MosSecureVStringPrint(char * buffer,size_t bufSize,size_t length,const char * const format,va_list var_args)255 MOS_STATUS MosUtilities::MosSecureVStringPrint(char  *buffer, size_t bufSize, size_t length, const char * const format, va_list var_args)
256 {
257     if((buffer == nullptr) || (format == nullptr) || (bufSize < length))
258     {
259         return MOS_STATUS_INVALID_PARAMETER;
260     }
261 
262     vsnprintf(buffer, length, format, var_args);
263 
264     return MOS_STATUS_SUCCESS;
265 }
266 
MosGetFileSize(HANDLE hFile,uint32_t * lpFileSizeLow,uint32_t * lpFileSizeHigh)267 MOS_STATUS MosUtilities::MosGetFileSize(
268     HANDLE              hFile,
269     uint32_t            *lpFileSizeLow,
270     uint32_t            *lpFileSizeHigh)
271 {
272     struct stat     Buf;
273     MOS_UNUSED(lpFileSizeHigh);
274 
275     if((hFile == nullptr) || (lpFileSizeLow == nullptr))
276     {
277         return MOS_STATUS_INVALID_PARAMETER;
278     }
279 
280     if ( (fstat((intptr_t)hFile, &Buf)) < 0 )
281     {
282         *lpFileSizeLow = 0;
283         return MOS_STATUS_INVALID_FILE_SIZE;
284     }
285     *lpFileSizeLow  = (uint32_t)Buf.st_size;
286 
287     //to-do, lpFileSizeHigh store high 32-bit of File size
288     return MOS_STATUS_SUCCESS;
289 }
290 
MosCreateDirectory(char * const lpPathName)291 MOS_STATUS MosUtilities::MosCreateDirectory(
292     char * const       lpPathName)
293 {
294     uint32_t   mode;
295 
296     MOS_OS_CHK_NULL_RETURN(lpPathName);
297 
298     // Set read/write access right for usr/group.
299     mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP;
300     if (mkdir(lpPathName, mode) < 0 &&
301         errno != EEXIST) // Directory already exists, don't return failure in this case.
302     {
303         MOS_OS_ASSERTMESSAGE("Failed to create the directory '%s'. Error = %s", lpPathName, strerror(errno));
304         return MOS_STATUS_DIR_CREATE_FAILED;
305     }
306 
307     return MOS_STATUS_SUCCESS;
308 }
309 
MosCreateFile(PHANDLE pHandle,char * const lpFileName,uint32_t iOpenFlag)310 MOS_STATUS MosUtilities::MosCreateFile(
311     PHANDLE             pHandle,
312     char * const        lpFileName,
313     uint32_t            iOpenFlag)
314 {
315     int32_t             iFileDescriptor;
316     uint32_t            mode;
317 
318     if((lpFileName == nullptr) || (pHandle == nullptr))
319     {
320         return MOS_STATUS_INVALID_PARAMETER;
321     }
322     //set read/write access right for usr/group, mMode only takes effect when
323     //O_CREAT is set
324     mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
325     if ( (iFileDescriptor = open(lpFileName, iOpenFlag, mode)) < 0 )
326     {
327         *pHandle = (HANDLE)((intptr_t) iFileDescriptor);
328         return MOS_STATUS_INVALID_HANDLE;
329     }
330 
331     *pHandle = (HANDLE)((intptr_t) iFileDescriptor);
332     return MOS_STATUS_SUCCESS;
333 }
334 
MosReadFile(HANDLE hFile,void * lpBuffer,uint32_t bytesToRead,uint32_t * pBytesRead,void * lpOverlapped)335 MOS_STATUS MosUtilities::MosReadFile(
336     HANDLE  hFile,
337     void    *lpBuffer,
338     uint32_t bytesToRead,
339     uint32_t *pBytesRead,
340     void    *lpOverlapped)
341 {
342     size_t  nNumBytesToRead;
343     ssize_t nNumBytesRead;
344     MOS_UNUSED(lpOverlapped);
345 
346     if((hFile == nullptr) || (lpBuffer == nullptr) || (pBytesRead == nullptr))
347     {
348         return MOS_STATUS_INVALID_PARAMETER;
349     }
350 
351     nNumBytesToRead   = (size_t)bytesToRead;
352     nNumBytesRead     = 0;
353 
354     //To-do: process lpOverlapped
355 
356     if ((nNumBytesRead = read((intptr_t)hFile, lpBuffer, nNumBytesToRead)) < 0)
357     {
358         *pBytesRead = 0;
359         return MOS_STATUS_FILE_READ_FAILED;
360     }
361 
362     *pBytesRead = (uint32_t)nNumBytesRead;
363     return MOS_STATUS_SUCCESS;
364 }
365 
MosWriteFile(HANDLE hFile,void * lpBuffer,uint32_t bytesToWrite,uint32_t * pbytesWritten,void * lpOverlapped)366 MOS_STATUS MosUtilities::MosWriteFile(
367     HANDLE    hFile,
368     void      *lpBuffer,
369     uint32_t  bytesToWrite,
370     uint32_t  *pbytesWritten,
371     void      *lpOverlapped)
372 {
373     size_t    nNumBytesToWrite;
374     ssize_t   nNumBytesWritten;
375     MOS_UNUSED(lpOverlapped);
376 
377     if((hFile == nullptr) || (lpBuffer == nullptr) || (pbytesWritten == nullptr))
378     {
379         return MOS_STATUS_INVALID_PARAMETER;
380     }
381 
382     nNumBytesToWrite = (size_t)bytesToWrite;
383     nNumBytesWritten = 0;
384 
385     //To-do, process lpOverlapped
386 
387     if ((nNumBytesWritten = write((intptr_t)hFile, lpBuffer, nNumBytesToWrite)) < 0)
388     {
389         *pbytesWritten = 0;
390         return MOS_STATUS_FILE_WRITE_FAILED;
391     }
392 
393     *pbytesWritten = (uint32_t)nNumBytesWritten;
394     return MOS_STATUS_SUCCESS;
395 }
396 
MosSetFilePointer(HANDLE hFile,int32_t lDistanceToMove,int32_t * lpDistanceToMoveHigh,int32_t dwMoveMethod)397 MOS_STATUS MosUtilities::MosSetFilePointer(
398     HANDLE        hFile,
399     int32_t       lDistanceToMove,
400     int32_t       *lpDistanceToMoveHigh,
401     int32_t       dwMoveMethod)
402 {
403     int32_t     iOffSet;
404     int32_t     iCurPos;
405 
406     if(hFile == nullptr)
407     {
408         return MOS_STATUS_INVALID_PARAMETER;
409     }
410 
411     if (lpDistanceToMoveHigh == nullptr)
412     {
413         iOffSet = lDistanceToMove;
414     }
415     else
416     {
417         //to-do, let lpDistanceToMoveHigh and lDistanceToMove form a 64-bit iOffSet
418         iOffSet = (int32_t)lDistanceToMove;
419     }
420 
421     if ((iCurPos = lseek((intptr_t)hFile, iOffSet, dwMoveMethod)) < 0)
422     {
423         return MOS_STATUS_SET_FILE_POINTER_FAILED;
424     }
425 
426     return MOS_STATUS_SUCCESS;
427 }
428 
MosCloseHandle(HANDLE hObject)429 int32_t MosUtilities::MosCloseHandle(HANDLE hObject)
430 {
431     int32_t iRet = false;
432 
433     if(hObject != nullptr)
434     {
435         close((intptr_t)hObject);
436         iRet = true;
437     }
438 
439     return iRet;
440 }
441 
442 //library
MosLoadLibrary(const char * const lpLibFileName,PHMODULE phModule)443 MOS_STATUS MosUtilities::MosLoadLibrary(const char * const lpLibFileName, PHMODULE phModule)
444 {
445     if (lpLibFileName == nullptr)
446     {
447         return MOS_STATUS_INVALID_PARAMETER;
448     }
449 
450     *phModule = dlopen((const char *)lpLibFileName, RTLD_LAZY);
451 
452     return ((*phModule != nullptr) ? MOS_STATUS_SUCCESS : MOS_STATUS_LOAD_LIBRARY_FAILED);
453 }
454 
MosFreeLibrary(HMODULE hLibModule)455 int32_t MosUtilities::MosFreeLibrary(HMODULE hLibModule)
456 {
457     uint32_t iRet = 10;   // Initialize to some non-zero value
458 
459     if(hLibModule != nullptr)
460     {
461         iRet = dlclose(hLibModule);
462     }
463     return (iRet == 0) ? true : false;
464 }
465 
MosGetProcAddress(HMODULE hModule,const char * lpProcName)466 void  *MosUtilities::MosGetProcAddress(HMODULE hModule, const char *lpProcName)
467 {
468     void  *pSym = nullptr;
469 
470     if (hModule    == nullptr ||
471         lpProcName == nullptr)
472     {
473         MOS_OS_ASSERTMESSAGE("Invalid parameter.");
474     }
475     else
476     {
477         pSym = dlsym(hModule, lpProcName);
478     }
479 
480     return pSym;
481 }
482 
MosGetPid()483 int32_t MosUtilities::MosGetPid()
484 {
485     return(getpid());
486 }
487 
488 //Performace
MosQueryPerformanceFrequency(uint64_t * pFrequency)489 int32_t MosUtilities::MosQueryPerformanceFrequency(uint64_t *pFrequency)
490 {
491     struct timespec  Res;
492     int32_t          iRet;
493 
494     if(pFrequency == nullptr)
495     {
496         return false;
497     }
498 
499     if ( (iRet = clock_getres(CLOCK_MONOTONIC, &Res)) != 0 )
500     {
501         return false;
502     }
503 
504     // resolution (precision) can't be in seconds for current machine and OS
505     if (Res.tv_sec != 0)
506     {
507         return false;
508     }
509     *pFrequency = (uint64_t)((1000 * 1000 * 1000) / Res.tv_nsec);
510 
511     return true;
512 }
513 
MosQueryPerformanceCounter(uint64_t * pPerformanceCount)514 int32_t MosUtilities::MosQueryPerformanceCounter(uint64_t *pPerformanceCount)
515 {
516     struct timespec     Res;
517     struct timespec     t;
518     int32_t             iRet;
519 
520     if(pPerformanceCount == nullptr)
521     {
522         return false;
523     }
524     if ( (iRet = clock_getres (CLOCK_MONOTONIC, &Res)) != 0 )
525     {
526         return false;
527     }
528     if (Res.tv_sec != 0)
529     { // resolution (precision) can't be in seconds for current machine and OS
530         return false;
531     }
532     if( (iRet = clock_gettime(CLOCK_MONOTONIC, &t)) != 0)
533     {
534         return false;
535     }
536     *pPerformanceCount = (uint64_t)((1000 * 1000 * 1000 * t.tv_sec + t.tv_nsec) / Res.tv_nsec);
537 
538     return true;
539 }
540 
MosSleep(uint32_t mSec)541 void MosUtilities::MosSleep(uint32_t mSec)
542 {
543     usleep(1000 * mSec);
544 }
545 
546 //User Feature
UserFeatureFindKey(MOS_PUF_KEYLIST pKeyList,char * const pcKeyName)547  MOS_UF_KEY* MosUtilitiesSpecificNext::UserFeatureFindKey(MOS_PUF_KEYLIST pKeyList, char * const pcKeyName)
548 {
549     int32_t           iResult;
550     MOS_PUF_KEYLIST   pTempNode;
551 
552     iResult = -1;
553 
554     for(pTempNode = pKeyList; pTempNode; pTempNode = pTempNode->pNext)
555     {
556         iResult = strcmp(pTempNode->pElem->pcKeyName, pcKeyName);
557         if ( iResult == 0 )
558         {
559             return pTempNode->pElem;
560         }
561     }
562     return nullptr; //not found
563 }
564 
UserFeatureFindValue(MOS_UF_KEY UFKey,char * const pcValueName)565  int32_t MosUtilitiesSpecificNext::UserFeatureFindValue(MOS_UF_KEY UFKey, char * const pcValueName)
566 {
567     int32_t iResult;
568     int32_t i;
569 
570     iResult = -1;
571 
572     for ( i = 0; i < UFKey.valueNum; i++ )
573     {
574         iResult = strcmp(UFKey.pValueArray[i].pcValueName, pcValueName);
575         if ( iResult == 0 )
576         {
577             return i;
578         }
579     }
580     return NOT_FOUND;
581 }
582 
UserFeatureAdd(MOS_PUF_KEYLIST * pKeyList,MOS_UF_KEY * NewKey)583 MOS_STATUS MosUtilitiesSpecificNext::UserFeatureAdd(MOS_PUF_KEYLIST *pKeyList, MOS_UF_KEY *NewKey)
584 {
585     MOS_UF_KEYNODE  *pNewNode;
586     MOS_UF_KEYNODE  *pTempNode;
587     MOS_UF_KEYNODE  *pStartNode;
588 
589     pNewNode   =  nullptr;
590     pTempNode  =  nullptr;
591     pStartNode =  *pKeyList;
592 
593     if ( NewKey == nullptr )
594     {
595         return MOS_STATUS_INVALID_PARAMETER;
596     }
597 
598     pNewNode = (MOS_UF_KEYNODE *)MOS_AllocAndZeroMemory(sizeof(MOS_UF_KEYNODE));
599     if (pNewNode == nullptr)
600     {
601         return MOS_STATUS_NO_SPACE;
602     }
603     pNewNode->pElem = NewKey;
604 
605     if (*pKeyList == nullptr ) // the key list is empty
606     {
607         pNewNode->pNext = nullptr;
608         (*pKeyList) = pNewNode;
609     }
610     else // the key list is not empty, append to the front
611     {
612         pTempNode = pStartNode->pNext;
613         pStartNode->pNext = pNewNode;
614         pNewNode->pNext = pTempNode;
615     }
616     return MOS_STATUS_SUCCESS;
617 }
618 
UserFeatureSet(MOS_PUF_KEYLIST * pKeyList,MOS_UF_KEY NewKey)619 MOS_STATUS MosUtilitiesSpecificNext::UserFeatureSet(MOS_PUF_KEYLIST *pKeyList, MOS_UF_KEY NewKey)
620 {
621     int32_t       iPos;
622     MOS_UF_VALUE  *pValueArray;
623     MOS_UF_KEY    *Key;
624     void          *ulValueBuf;
625 
626     iPos         = -1;
627     pValueArray  = nullptr;
628 
629     if ( (Key = UserFeatureFindKey(*pKeyList, NewKey.pcKeyName)) == nullptr )
630     {
631         // can't find key in File
632         return MOS_STATUS_UNKNOWN;
633     }
634 
635     // Prepare the ValueBuff of the NewKey
636     if ((ulValueBuf = MOS_AllocAndZeroMemory(NewKey.pValueArray[0].ulValueLen)) == nullptr)
637     {
638          return MOS_STATUS_NO_SPACE;
639     }
640     MosUtilities::MosAtomicIncrement(MosUtilities::m_mosMemAllocFakeCounter);  //ulValueBuf does not count it, because it is freed after the MEMNJA final report.
641     MOS_OS_NORMALMESSAGE("ulValueBuf %p for key %s", ulValueBuf, NewKey.pValueArray[0].pcValueName);
642 
643     m_userSettingMutex.Lock();
644     if ((iPos = UserFeatureFindValue(*Key, NewKey.pValueArray[0].pcValueName)) == NOT_FOUND)
645     {
646         //not found, add a new value to key struct.
647         //reallocate memory for appending this value.
648         iPos = MosUtilities::MosAtomicIncrement(&Key->valueNum);
649         iPos = iPos - 1;
650         if (iPos >= UF_CAPABILITY)
651         {
652             MOS_OS_ASSERTMESSAGE("user setting requires iPos (%d) < UF_CAPABILITY(64)", iPos);
653             Key->valueNum = UF_CAPABILITY;
654             MOS_SafeFreeMemory(ulValueBuf);
655             m_userSettingMutex.Unlock();
656             return MOS_STATUS_USER_FEATURE_KEY_READ_FAILED;
657         }
658         MosUtilities::MosSecureStrcpy(Key->pValueArray[iPos].pcValueName,
659             MAX_USERFEATURE_LINE_LENGTH,
660             NewKey.pValueArray[0].pcValueName);
661     }
662     else
663     {
664         //if found, the previous value buffer needs to be freed before reallocating
665         MOS_FreeMemory(Key->pValueArray[iPos].ulValueBuf);
666         MosUtilities::MosAtomicDecrement(MosUtilities::m_mosMemAllocFakeCounter);
667         MOS_OS_NORMALMESSAGE("ulValueBuf %p for key %s", ulValueBuf, NewKey.pValueArray[0].pcValueName);
668     }
669 
670     Key->pValueArray[iPos].ulValueLen  = NewKey.pValueArray[0].ulValueLen;
671     Key->pValueArray[iPos].ulValueType = NewKey.pValueArray[0].ulValueType;
672     Key->pValueArray[iPos].ulValueBuf  = ulValueBuf;
673 
674     MosUtilities::MosZeroMemory(Key->pValueArray[iPos].ulValueBuf, NewKey.pValueArray[0].ulValueLen);
675 
676     MosUtilities::MosSecureMemcpy(Key->pValueArray[iPos].ulValueBuf,
677                      NewKey.pValueArray[0].ulValueLen,
678                      NewKey.pValueArray[0].ulValueBuf,
679                      NewKey.pValueArray[0].ulValueLen);
680 
681     m_userSettingMutex.Unlock();
682     return MOS_STATUS_SUCCESS;
683 }
684 
UserFeatureQuery(MOS_PUF_KEYLIST pKeyList,MOS_UF_KEY * NewKey)685 MOS_STATUS MosUtilitiesSpecificNext::UserFeatureQuery(MOS_PUF_KEYLIST pKeyList, MOS_UF_KEY *NewKey)
686 {
687     int32_t       iPos;
688     MOS_UF_VALUE  *pValueArray;
689     MOS_UF_KEY    *Key;
690 
691     iPos         = -1;
692     pValueArray  = nullptr;
693 
694     // can't find key in user feature
695     if ( (Key = UserFeatureFindKey(pKeyList, NewKey->pcKeyName)) == nullptr )
696     {
697         return MOS_STATUS_UNKNOWN;
698     }
699 
700     // can't find Value in the key
701     if ( (iPos = UserFeatureFindValue(*Key, NewKey->pValueArray[0].pcValueName)) == NOT_FOUND)
702     {
703         return MOS_STATUS_UNKNOWN;
704     }
705 
706     //get key content from user feature
707     MosUtilities::MosSecureMemcpy(NewKey->pValueArray[0].ulValueBuf,
708                      Key->pValueArray[iPos].ulValueLen,
709                      Key->pValueArray[iPos].ulValueBuf,
710                      Key->pValueArray[iPos].ulValueLen);
711 
712     NewKey->pValueArray[0].ulValueLen    =  Key->pValueArray[iPos].ulValueLen;
713     NewKey->pValueArray[0].ulValueType   =  Key->pValueArray[iPos].ulValueType;
714 
715     return MOS_STATUS_SUCCESS;
716 }
717 
UserFeatureReadNextTokenFromFile(FILE * pFile,const char * szFormat,char * szToken)718 MOS_STATUS  MosUtilitiesSpecificNext::UserFeatureReadNextTokenFromFile(FILE *pFile, const char *szFormat, char  *szToken)
719 {
720     size_t nTokenSize = 0;
721 
722     // Reads the next token from the given pFile.
723     if (fscanf(pFile, szFormat, szToken) <= 0)
724     {
725         MOS_OS_VERBOSEMESSAGE("Failed reading the next token from the user feature file. This is probably because the token does not exist in the user feature file.");
726         return MOS_STATUS_FILE_READ_FAILED;
727     }
728 
729     // Converts to Unix-style line endings to prevent compatibility problems.
730     nTokenSize = strnlen(szToken, MAX_USERFEATURE_LINE_LENGTH);
731     if (szToken[nTokenSize-1] == '\r')
732     {
733         szToken[nTokenSize-1] = '\0';
734     }
735 
736     return MOS_STATUS_SUCCESS;
737 }
738 
UserFeatureDumpFile(const char * const szFileName,MOS_PUF_KEYLIST * pKeyList)739 MOS_STATUS  MosUtilitiesSpecificNext::UserFeatureDumpFile(const char * const szFileName, MOS_PUF_KEYLIST* pKeyList)
740 {
741     MOS_UF_KEY      *CurKey;
742     MOS_UF_VALUE    *CurValue;
743     char            szTmp[MAX_USERFEATURE_LINE_LENGTH];
744     int32_t         iResult;
745     size_t          nSize;
746     int32_t         bFirst;
747     int32_t         iCount;
748     PFILE           File;
749     int32_t         bEmpty;
750     uint32_t        iCurId;
751     MOS_STATUS      eStatus;
752     char            *tmpChar; // Used in the 64-bit case to read uint64_t
753 
754     CurValue  =  nullptr;
755     nSize     =  0;
756     bFirst    =  1;    // 1 stand for "is the first key".
757     iCount    =  0;
758     File      =  nullptr;
759     bEmpty    =  0;
760     iCurId    =  0;
761     eStatus  =  MOS_STATUS_SUCCESS;
762 
763     CurKey = (MOS_UF_KEY *)MOS_AllocAndZeroMemory(sizeof(MOS_UF_KEY));
764     if (CurKey == nullptr)
765     {
766         return MOS_STATUS_NO_SPACE;
767     }
768     CurKey->valueNum        = 0;
769     CurKey->pcKeyName[0]    = '\0';
770     CurKey->pValueArray     = nullptr;
771 
772     if ( (File = fopen(szFileName, "r")) == nullptr)
773     {
774         MOS_FreeMemory(CurKey);
775         return MOS_STATUS_USER_FEATURE_KEY_READ_FAILED;
776     }
777     while (feof(File) != EOF)
778     {
779         MosUtilities::MosZeroMemory(szTmp, MAX_USERFEATURE_LINE_LENGTH*sizeof(char ));
780         if (MOS_FAILED(UserFeatureReadNextTokenFromFile(File, MAX_UF_LINE_STRING_FORMAT, szTmp)))
781         {
782             break;
783         }
784 
785         // set szDumpData with extracted File content.
786         iResult = strcmp(szTmp, UF_KEY_ID);
787         if ( iResult == 0 )
788         {
789             // It is a new key starting!
790             if (! bFirst )
791             {
792                 // Add last key struct to contents when the key is not first.
793                 // otherwise, continue to load key struct data.
794                 CurKey->pValueArray   = CurValue;
795                 CurKey->valueNum      = iCount;
796                 if(UserFeatureAdd(pKeyList, CurKey) != MOS_STATUS_SUCCESS)
797                 {
798                     // if the CurKey didn't be added in pKeyList, free it.
799                     MOS_FreeMemory(CurKey);
800                 }
801                 CurKey = (MOS_UF_KEY *)MOS_AllocAndZeroMemory(sizeof(MOS_UF_KEY));
802                 if (CurKey == nullptr)
803                 {
804                     eStatus = MOS_STATUS_NO_SPACE;
805                     break;
806                 }
807             } // if (! bFirst )
808 
809             if (fscanf(File, "%x\n", &iCurId) <= 0)
810             {
811                 break;
812             }
813 
814             CurKey->UFKey = (void *)(intptr_t)iCurId;
815 
816             MosUtilities::MosZeroMemory(szTmp, MAX_USERFEATURE_LINE_LENGTH * sizeof(char));
817             if (MOS_FAILED(UserFeatureReadNextTokenFromFile(File, MAX_UF_LINE_STRING_FORMAT, szTmp)))
818             {
819                 break;
820             }
821 
822             MosUtilities::MosSecureStrcpy(CurKey->pcKeyName, MAX_USERFEATURE_LINE_LENGTH, szTmp);
823             CurKey->valueNum = 0;
824 
825             // allocate capability length for valuearray.
826             CurValue = (MOS_UF_VALUE *)MOS_AllocAndZeroMemory(sizeof(MOS_UF_VALUE) * UF_CAPABILITY);
827             if (CurValue == nullptr)
828             {
829                 eStatus = MOS_STATUS_NO_SPACE;
830                 break;
831             }
832             bFirst = 0;
833             iCount = 0;  // next key's array number.
834             bEmpty = 1;
835         } // if ( iResult == 0 )
836         else // not a key
837         {
838             // Is it a value starting?
839             iResult = strcmp(szTmp, UF_VALUE_ID);
840             if ( iResult == 0 )
841             {
842                 if (MOS_FAILED(UserFeatureReadNextTokenFromFile(File, MAX_UF_LINE_STRING_FORMAT, szTmp)))
843                 {
844                     break;
845                 }
846 
847                 if (CurValue == nullptr)
848                 {
849                     break;
850                 }
851 
852                 // Out of bounds technically based on how much memory we allocated
853                 if (iCount < 0 || iCount >= UF_CAPABILITY)
854                 {
855                     eStatus = MOS_STATUS_USER_FEATURE_KEY_READ_FAILED;
856                     MOS_OS_ASSERTMESSAGE("user setting value icount %d, and it must meet  0 < icount < UF_CAPABILITY(64)", iCount);
857                     break;
858                 }
859 
860                 // Load value name;
861                 MosUtilities::MosSecureStrcpy(CurValue[iCount].pcValueName, MAX_USERFEATURE_LINE_LENGTH, szTmp);
862 
863                 // Load value type
864                 if (MOS_FAILED(UserFeatureReadNextTokenFromFile(File, MAX_UF_LINE_STRING_FORMAT, szTmp)))
865                 {
866                     break;
867                 }
868 
869                 CurValue[iCount].ulValueType = atoi(szTmp);
870 
871                 // Load value buffer.
872                 switch ( CurValue[iCount].ulValueType )
873                 {
874                 case UF_DWORD: // 32-bit
875                     if (MOS_FAILED(UserFeatureReadNextTokenFromFile(File, MAX_UF_LINE_STRING_FORMAT, szTmp)))
876                     {
877                         break;
878                     }
879 
880                     CurValue[iCount].ulValueLen = sizeof(uint32_t);
881                     CurValue[iCount].ulValueBuf = MOS_AllocMemory(sizeof(uint32_t));
882                     if(CurValue[iCount].ulValueBuf == nullptr)
883                     {
884                         eStatus = MOS_STATUS_NO_SPACE;
885                         break;
886                     }
887                     *(uint32_t*)(CurValue[iCount].ulValueBuf) = atoi(szTmp);
888                     break;
889                 case UF_QWORD: // 64-bit
890                     if (MOS_FAILED(UserFeatureReadNextTokenFromFile(File, MAX_UF_LINE_STRING_FORMAT, szTmp)))
891                     {
892                         break;
893                     }
894 
895                     CurValue[iCount].ulValueLen = sizeof(uint64_t);
896                     CurValue[iCount].ulValueBuf = MOS_AllocMemory(sizeof(uint64_t));
897                     if(CurValue[iCount].ulValueBuf == nullptr)
898                     {
899                         eStatus = MOS_STATUS_NO_SPACE;
900                         break;
901                     }
902                     tmpChar = &szTmp[0];
903                     *(uint64_t*)(CurValue[iCount].ulValueBuf) = strtoll(tmpChar,&tmpChar,0);
904                     break;
905                 case UF_SZ:
906                 case UF_MULTI_SZ:
907                     if (MOS_FAILED(UserFeatureReadNextTokenFromFile(File, MAX_UF_LINE_STRING_FORMAT, szTmp)))
908                     {
909                         break;
910                     }
911 
912                     nSize = strlen(szTmp);
913                     CurValue[iCount].ulValueLen = (nSize+1)*sizeof(char );
914                     CurValue[iCount].ulValueBuf = MOS_AllocMemory(nSize+1);
915                     if(CurValue[iCount].ulValueBuf == nullptr)
916                     {
917                         eStatus = MOS_STATUS_NO_SPACE;
918                         break;
919                     }
920                     MosUtilities::MosZeroMemory(CurValue[iCount].ulValueBuf, nSize+1);
921                     MosUtilities::MosSecureMemcpy(CurValue[iCount].ulValueBuf, nSize, szTmp, nSize);
922                     break;
923                 default:
924                     eStatus = MOS_STATUS_UNKNOWN;
925                 }
926                 if (eStatus != MOS_STATUS_SUCCESS)
927                 {
928                     break;
929                 }
930 
931                 iCount ++; // do the error checking near the top
932 
933             } // if ( iResult == 0 )
934             else   // It is not a value starting, it's bad User Feature File.
935             {
936                 int32_t iResult = strcmp(szTmp, "");
937                 if ( !iResult )
938                 {
939                     continue;
940                 }
941                 else
942                 {
943                     eStatus =  MOS_STATUS_INVALID_PARAMETER;
944                     break;
945                 }
946             } // else ( iResult == 0 )
947         }
948     } // while (feof(File) != EOF)
949 
950     if (eStatus == MOS_STATUS_SUCCESS)
951     {
952         if ( bEmpty && (strlen(CurKey->pcKeyName) > 0) &&
953             (CurKey->valueNum == 0) )
954         {
955             CurKey->pValueArray = CurValue;
956             CurKey->valueNum    = iCount;
957             if(UserFeatureAdd(pKeyList, CurKey) != MOS_STATUS_SUCCESS)
958             {
959                 // if the CurKey didn't be added in pKeyList, free it.
960                 for (uint32_t i = 0; i < iCount; i++)
961                 {
962                     if (CurValue)
963                     {
964                         MOS_FreeMemory(CurValue[i].ulValueBuf);
965                     }
966                 }
967                 MOS_FreeMemory(CurValue);
968                 MOS_FreeMemory(CurKey);
969             }
970         }
971         else
972         {
973             for (uint32_t i = 0; i < iCount; i++)
974             {
975                 if (CurValue)
976                 {
977                     MOS_FreeMemory(CurValue[i].ulValueBuf);
978                 }
979             }
980             MOS_FreeMemory(CurValue);
981             MOS_FreeMemory(CurKey);
982         }
983     }
984     else
985     {
986         for (uint32_t i = 0; i < iCount; i++)
987         {
988             if (CurValue)
989             {
990                 MOS_FreeMemory(CurValue[i].ulValueBuf);
991             }
992         }
993         MOS_FreeMemory(CurValue);
994         MOS_FreeMemory(CurKey);
995     }
996     fclose(File);
997     return eStatus;
998 }
999 
UserFeatureDumpDataToFile(const char * szFileName,MOS_PUF_KEYLIST pKeyList)1000 MOS_STATUS MosUtilitiesSpecificNext::UserFeatureDumpDataToFile(const char *szFileName, MOS_PUF_KEYLIST pKeyList)
1001 {
1002     int32_t           iResult;
1003     PFILE             File;
1004     MOS_PUF_KEYLIST   pKeyTmp;
1005     int32_t           j;
1006 
1007    // For release version: writes to the file if it exists,
1008 // skips if it does not exist
1009 // For other version: always writes to the file
1010 
1011 #if(_RELEASE)
1012     File = fopen(szFileName, "r");
1013     if (File == NULL)
1014     {
1015         return MOS_STATUS_SUCCESS;
1016     }
1017     else
1018     {
1019         fclose(File);
1020         File = fopen(szFileName, "w+");
1021     }
1022 #else
1023     File = fopen(szFileName, "w+");
1024 #endif
1025 
1026     if ( !File )
1027     {
1028         return MOS_STATUS_USER_FEATURE_KEY_WRITE_FAILED;
1029     }
1030 
1031     for (pKeyTmp = pKeyList; pKeyTmp; pKeyTmp = pKeyTmp->pNext)
1032     {
1033         fprintf(File, "%s\n", UF_KEY_ID);
1034         fprintf(File,  "\t0x%.8x\n", (uint32_t)(uintptr_t)pKeyTmp->pElem->UFKey);
1035         fprintf(File,  "\t%s\n", pKeyTmp->pElem->pcKeyName);
1036         for ( j = 0; j < pKeyTmp->pElem->valueNum; j ++ )
1037         {
1038             fprintf(File, "\t\t%s\n", UF_VALUE_ID);
1039             if ( strlen(pKeyTmp->pElem->pValueArray[j].pcValueName) > 0 )
1040             {
1041                 fprintf(File, "\t\t\t%s\n",
1042                     pKeyTmp->pElem->pValueArray[j].pcValueName);
1043             }
1044             fprintf(File, "\t\t\t%d\n", pKeyTmp->pElem->pValueArray[j].ulValueType);
1045             if (pKeyTmp->pElem->pValueArray[j].ulValueBuf != nullptr)
1046             {
1047                 switch (pKeyTmp->pElem->pValueArray[j].ulValueType)
1048                 {
1049                 case UF_SZ:
1050                     fprintf(File,  "\t\t\t%s\n",
1051                         (char *)(pKeyTmp->pElem->pValueArray[j].ulValueBuf));
1052                     break;
1053                 case UF_DWORD:
1054                     fprintf(File, "\t\t\t%u\n",
1055                         *(uint32_t*)(pKeyTmp->pElem->pValueArray[j].ulValueBuf));
1056                     break;
1057                 case UF_QWORD:
1058                     fprintf(File, "\t\t\t%" PRIu64"\n", *(uint64_t*)(pKeyTmp->pElem->pValueArray[j].ulValueBuf));
1059                     break;
1060                 default:
1061                     fprintf(File, "\t\t\t%s\n",
1062                         (char *)(pKeyTmp->pElem->pValueArray[j].ulValueBuf));
1063                     break;
1064                 } //switch (pKeyTmp->pElem->pValueArray[j].ulValueType)
1065             }
1066         } // for ( j = 0; j < pKeyTmp->pElem->valueNum; j ++ )
1067     } //for (pKeyTmp = pKeyList; pKeyTmp; pKeyTmp = pKeyTmp->pNext)
1068     fclose(File);
1069 
1070     return MOS_STATUS_SUCCESS;
1071 }
1072 
UserFeatureFreeKeyList(MOS_PUF_KEYLIST pKeyList)1073 void MosUtilitiesSpecificNext::UserFeatureFreeKeyList(MOS_PUF_KEYLIST pKeyList)
1074 {
1075     MOS_PUF_KEYLIST     pKeyTmp;
1076     MOS_PUF_KEYLIST     pKeyTmpNext;
1077     uint32_t            i;
1078 
1079     pKeyTmp = pKeyList;
1080     while(pKeyTmp)
1081     {
1082         pKeyTmpNext = pKeyTmp->pNext;
1083         for(i=0;i<pKeyTmp->pElem->valueNum;i++)
1084         {
1085             MOS_FreeMemory(pKeyTmp->pElem->pValueArray[i].ulValueBuf);
1086         }
1087         MOS_FreeMemory(pKeyTmp->pElem->pValueArray);
1088         MOS_FreeMemory(pKeyTmp->pElem);
1089         MOS_FreeMemory(pKeyTmp);
1090         pKeyTmp = pKeyTmpNext;
1091     }
1092     return;
1093 }
1094 
UserFeatureSetValue(char * const strKey,const char * const pcValueName,uint32_t uiValueType,void * pData,int32_t nDataSize)1095 MOS_STATUS  MosUtilitiesSpecificNext::UserFeatureSetValue(
1096     char * const        strKey,
1097     const char * const  pcValueName,
1098     uint32_t            uiValueType,
1099     void                *pData,
1100     int32_t             nDataSize)
1101 {
1102     MOS_UF_KEY          NewKey;
1103     MOS_UF_VALUE        NewValue;
1104     MOS_STATUS          eStatus;
1105 
1106     eStatus   = MOS_STATUS_UNKNOWN;
1107 
1108     if ((strKey == nullptr) || (pcValueName == nullptr) || (m_ufKeyList == nullptr))
1109     {
1110         return MOS_STATUS_INVALID_PARAMETER;
1111     }
1112 
1113     MosUtilities::MosZeroMemory(NewValue.pcValueName, MAX_USERFEATURE_LINE_LENGTH);
1114     MosUtilities::MosSecureStrcpy(NewValue.pcValueName, MAX_USERFEATURE_LINE_LENGTH, pcValueName);
1115     NewValue.ulValueType    = uiValueType;
1116     if( NewValue.ulValueType == UF_DWORD)
1117     {
1118         NewValue.ulValueLen = sizeof(uint32_t);
1119     }
1120     else
1121     {
1122         NewValue.ulValueLen = nDataSize;
1123     }
1124     NewValue.ulValueBuf     = pData;
1125 
1126     MosUtilities::MosZeroMemory(NewKey.pcKeyName, MAX_USERFEATURE_LINE_LENGTH);
1127     MosUtilities::MosSecureStrcpy(NewKey.pcKeyName, MAX_USERFEATURE_LINE_LENGTH, strKey);
1128     NewKey.pValueArray = &NewValue;
1129     NewKey.valueNum    = 1;
1130 
1131     if ( ( eStatus = UserFeatureSet(&MosUtilitiesSpecificNext::m_ufKeyList, NewKey)) == MOS_STATUS_SUCCESS )
1132     {
1133         MosUtilities::MosUserFeatureNotifyChangeKeyValue(nullptr, false, nullptr, true);
1134     }
1135 
1136     return eStatus;
1137 }
1138 
UserFeatureQueryValue(char * const strKey,const char * const pcValueName,uint32_t * uiValueType,void * pData,int32_t * nDataSize)1139 MOS_STATUS MosUtilitiesSpecificNext::UserFeatureQueryValue(
1140     char * const        strKey,
1141     const char * const  pcValueName,
1142     uint32_t            *uiValueType,
1143     void                *pData,
1144     int32_t             *nDataSize)
1145 {
1146     MOS_UF_KEY          NewKey;
1147     MOS_UF_VALUE        NewValue;
1148     size_t              nKeyLen, nValueLen;
1149     MOS_STATUS          eStatus;
1150     MOS_PUF_KEYLIST     pKeyList;
1151     char                strTempKey[MAX_USERFEATURE_LINE_LENGTH];
1152     char                strTempValueName[MAX_USERFEATURE_LINE_LENGTH];
1153 
1154     eStatus   = MOS_STATUS_UNKNOWN;
1155     pKeyList   = MosUtilitiesSpecificNext::m_ufKeyList;
1156 
1157     if ( (strKey == nullptr) || (pcValueName == nullptr) || (pKeyList == nullptr))
1158     {
1159         return MOS_STATUS_INVALID_PARAMETER;
1160     }
1161     MosUtilities::MosZeroMemory(NewValue.pcValueName, MAX_USERFEATURE_LINE_LENGTH);
1162     MosUtilities::MosSecureStrcpy(NewValue.pcValueName, MAX_USERFEATURE_LINE_LENGTH, pcValueName);
1163     NewValue.ulValueBuf     = pData;
1164 
1165     MosUtilities::MosZeroMemory(NewKey.pcKeyName, MAX_USERFEATURE_LINE_LENGTH);
1166     MosUtilities::MosSecureStrcpy(NewKey.pcKeyName, MAX_USERFEATURE_LINE_LENGTH, strKey);
1167     NewKey.pValueArray = &NewValue;
1168     NewKey.valueNum    = 1;
1169 
1170     if ( (eStatus = UserFeatureQuery(pKeyList, &NewKey)) == MOS_STATUS_SUCCESS )
1171     {
1172         if(uiValueType != nullptr)
1173         {
1174             *uiValueType = NewKey.pValueArray[0].ulValueType;
1175         }
1176         if (nDataSize != nullptr)
1177         {
1178             *nDataSize   = NewKey.pValueArray[0].ulValueLen;
1179         }
1180     }
1181 
1182     return eStatus;
1183 }
1184 
UserFeatureGetKeyIdbyName(const char * pcKeyName,void ** pUFKey)1185 MOS_STATUS MosUtilitiesSpecificNext::UserFeatureGetKeyIdbyName(const char  *pcKeyName, void **pUFKey)
1186 {
1187     MOS_PUF_KEYLIST     pKeyList;
1188     int32_t             iResult;
1189     MOS_STATUS          eStatus;
1190     MOS_PUF_KEYLIST     pTempNode;
1191 
1192     pKeyList   = MosUtilitiesSpecificNext::m_ufKeyList;
1193     iResult    = -1;
1194 
1195     eStatus    = MOS_STATUS_INVALID_PARAMETER;
1196 
1197     for(pTempNode=pKeyList; pTempNode; pTempNode=pTempNode->pNext)
1198     {
1199         iResult = strcmp(pTempNode->pElem->pcKeyName, pcKeyName);
1200         if ( iResult == 0 )
1201         {
1202             *pUFKey = pTempNode->pElem->UFKey;
1203             eStatus = MOS_STATUS_SUCCESS;
1204             break;
1205         }
1206     }
1207 
1208     return eStatus;
1209 }
1210 
UserFeatureGetKeyNamebyId(void * UFKey,char * pcKeyName)1211 MOS_STATUS MosUtilitiesSpecificNext::UserFeatureGetKeyNamebyId(void  *UFKey, char  *pcKeyName)
1212 {
1213     MOS_PUF_KEYLIST     pKeyList;
1214     MOS_PUF_KEYLIST     pTempNode;
1215     MOS_STATUS          eStatus;
1216 
1217     pKeyList   = MosUtilitiesSpecificNext::m_ufKeyList;
1218 
1219     switch((uintptr_t)UFKey)
1220     {
1221     case UFKEY_INTERNAL:
1222         MosUtilities::MosSecureStrcpy(pcKeyName, MAX_USERFEATURE_LINE_LENGTH, USER_FEATURE_KEY_INTERNAL);
1223         eStatus = MOS_STATUS_SUCCESS;
1224         break;
1225     case UFKEY_EXTERNAL:
1226         MosUtilities::MosSecureStrcpy(pcKeyName, MAX_USERFEATURE_LINE_LENGTH, USER_FEATURE_KEY_EXTERNAL);
1227         eStatus = MOS_STATUS_SUCCESS;
1228         break;
1229     default:
1230         eStatus   = MOS_STATUS_UNKNOWN;
1231 
1232         for(pTempNode=pKeyList;pTempNode;pTempNode=pTempNode->pNext)
1233         {
1234             if(pTempNode->pElem->UFKey == UFKey)
1235             {
1236                 MosUtilities::MosSecureStrcpy(pcKeyName, MAX_USERFEATURE_LINE_LENGTH, pTempNode->pElem->pcKeyName);
1237                 eStatus = MOS_STATUS_SUCCESS;
1238                 break;
1239             }
1240         }
1241         break;
1242     }
1243 
1244     return eStatus;
1245 
1246 }
1247 
MosUserFeatureOpenKeyFile(void * UFKey,const char * lpSubKey,uint32_t ulOptions,uint32_t samDesired,void ** phkResult)1248 MOS_STATUS MosUtilitiesSpecificNext::MosUserFeatureOpenKeyFile(
1249     void       *UFKey,
1250     const char *lpSubKey,
1251     uint32_t   ulOptions,  // reserved
1252     uint32_t   samDesired,
1253     void       **phkResult)
1254 {
1255     char           pcKeyName[MAX_USERFEATURE_LINE_LENGTH];
1256     MOS_STATUS     iRet;
1257     uintptr_t      h_key = (uintptr_t)UFKey;
1258     MOS_UNUSED(ulOptions);
1259     MOS_UNUSED(samDesired);
1260 
1261     if((h_key == 0) /*|| (lpSubKey == nullptr)*/ || (phkResult == nullptr))    //[SH]: subkey can be NULL???
1262     {
1263         return MOS_STATUS_INVALID_PARAMETER;
1264     }
1265 
1266     MosUtilities::MosZeroMemory(pcKeyName, MAX_USERFEATURE_LINE_LENGTH*sizeof(char));
1267     switch(h_key)
1268     {
1269     case UFKEY_INTERNAL:
1270         MosUtilities::MosSecureStrcpy(pcKeyName, MAX_USERFEATURE_LINE_LENGTH, USER_FEATURE_KEY_INTERNAL);
1271         break;
1272     case UFKEY_EXTERNAL:
1273         MosUtilities::MosSecureStrcpy(pcKeyName, MAX_USERFEATURE_LINE_LENGTH, USER_FEATURE_KEY_EXTERNAL);
1274         break;
1275     default:
1276         break;
1277     }
1278 
1279     MosUtilities::MosSecureStrcat(pcKeyName, sizeof(pcKeyName), lpSubKey);
1280     iRet = UserFeatureGetKeyIdbyName(pcKeyName, phkResult);
1281 
1282     return iRet;
1283 }
1284 
MosUserFeatureGetValueFile(void * UFKey,const char * lpSubKey,const char * lpValue,uint32_t dwFlags,uint32_t * pdwType,void * pvData,uint32_t * pcbData)1285 MOS_STATUS MosUtilitiesSpecificNext::MosUserFeatureGetValueFile(
1286     void       *UFKey,
1287     const char *lpSubKey,
1288     const char *lpValue,
1289     uint32_t   dwFlags,
1290     uint32_t   *pdwType,
1291     void       *pvData,
1292     uint32_t   *pcbData)
1293 {
1294     char          pcKeyName[MAX_USERFEATURE_LINE_LENGTH];
1295     MOS_STATUS    eStatus;
1296     MOS_UNUSED(dwFlags);
1297 
1298     if(UFKey == nullptr)
1299     {
1300         return MOS_STATUS_INVALID_PARAMETER;
1301     }
1302 
1303     eStatus = MOS_STATUS_UNKNOWN;
1304     MosUtilities::MosZeroMemory(pcKeyName, MAX_USERFEATURE_LINE_LENGTH * sizeof(char));
1305     if ( (eStatus = UserFeatureGetKeyNamebyId(UFKey,pcKeyName)) != MOS_STATUS_SUCCESS)
1306     {
1307         return eStatus;
1308     }
1309 
1310     if(lpSubKey != nullptr)
1311     {
1312         MosUtilities::MosSecureStrcat(pcKeyName, sizeof(pcKeyName), lpSubKey);
1313     }
1314     eStatus = UserFeatureQueryValue(pcKeyName,
1315                                   lpValue,
1316                                   (uint32_t*)pdwType,
1317                                   pvData,
1318                                   (int32_t*)pcbData);
1319 
1320     return eStatus;
1321 }
1322 
MosUserFeatureSetValueExFile(void * UFKey,const char * lpValueName,uint32_t Reserved,uint32_t dwType,uint8_t * lpData,uint32_t cbData)1323 MOS_STATUS MosUtilitiesSpecificNext::MosUserFeatureSetValueExFile(
1324     void            *UFKey,
1325     const char      *lpValueName,
1326     uint32_t        Reserved,
1327     uint32_t        dwType,
1328     uint8_t         *lpData,
1329     uint32_t        cbData)
1330 {
1331     char    pcKeyName[MAX_USERFEATURE_LINE_LENGTH];
1332     MOS_STATUS  eStatus;
1333     MOS_UNUSED(Reserved);
1334 
1335     if (UFKey == nullptr)
1336     {
1337         return MOS_STATUS_INVALID_PARAMETER;
1338     }
1339     MosUtilities::MosZeroMemory(pcKeyName, MAX_USERFEATURE_LINE_LENGTH*sizeof(char));
1340     if ((eStatus = UserFeatureGetKeyNamebyId(UFKey,pcKeyName)) != MOS_STATUS_SUCCESS)
1341     {
1342         return eStatus;
1343     }
1344 
1345     eStatus = UserFeatureSetValue(pcKeyName,lpValueName,dwType,lpData,cbData);
1346 
1347     return eStatus;
1348 }
1349 
MosOsUtilitiesInit(MediaUserSettingSharedPtr userSettingPtr)1350 MOS_STATUS MosUtilities::MosOsUtilitiesInit(MediaUserSettingSharedPtr userSettingPtr)
1351 {
1352     MOS_STATUS     eStatus = MOS_STATUS_SUCCESS;
1353 
1354     // lock mutex to avoid multi init in multi-threading env
1355     m_mutexLock.Lock();
1356 
1357 #if (_DEBUG || _RELEASE_INTERNAL)
1358     // Get use user feature file from env, instead of default.
1359     FILE* fp = nullptr;
1360     static char* tmpFile = getenv("GFX_FEATURE_FILE");
1361 
1362     if (tmpFile != nullptr)
1363     {
1364       if ((fp = fopen(tmpFile, "r")) != nullptr)
1365       {
1366           MosUtilitiesSpecificNext::m_szUserFeatureFile = tmpFile;
1367           fclose(fp);
1368           MOS_OS_NORMALMESSAGE("using %s for USER_FEATURE_FILE", MosUtilitiesSpecificNext::m_szUserFeatureFile);
1369       }
1370       else
1371       {
1372           MOS_OS_ASSERTMESSAGE("Can't open %s for USER_FEATURE_FILE!!!", tmpFile);
1373           m_mutexLock.Unlock();
1374           return MOS_STATUS_FILE_NOT_FOUND;
1375       }
1376     }
1377 #endif
1378 
1379     //The user setting is device based, no need to guard with the reference count.
1380     //It will be destroyed in media context termiation.
1381     eStatus = MosUserSetting::InitMosUserSetting(userSettingPtr);
1382 
1383     if (m_mosUtilInitCount == 0)
1384     {
1385         //Init MOS User Feature Key from mos desc table
1386         MosUtilitiesSpecificNext::UserFeatureDumpFile(MosUtilitiesSpecificNext::m_szUserFeatureFile, &MosUtilitiesSpecificNext::m_ufKeyList);
1387         MosDeclareUserFeature();
1388 
1389 #if MOS_MESSAGES_ENABLED
1390         // Initialize MOS message params structure and HLT
1391         MosUtilDebug::MosMessageInit(userSettingPtr);
1392 #endif // MOS_MESSAGES_ENABLED
1393         if (m_mosMemAllocCounter &&
1394             m_mosMemAllocCounterGfx &&
1395             m_mosMemAllocFakeCounter)
1396         {
1397             *m_mosMemAllocCounter     = 0;
1398             *m_mosMemAllocFakeCounter = 0;
1399             *m_mosMemAllocCounterGfx  = 0;
1400         }
1401         else
1402         {
1403             MOS_OS_ASSERTMESSAGE("MemNinja count pointers are nullptr");
1404         }
1405 
1406         MosTraceEventInit();
1407     }
1408     m_mosUtilInitCount++;
1409 
1410     m_mutexLock.Unlock();
1411     return eStatus;
1412 }
1413 
MosOsUtilitiesClose(MediaUserSettingSharedPtr userSettingPtr)1414 MOS_STATUS MosUtilities::MosOsUtilitiesClose(MediaUserSettingSharedPtr userSettingPtr)
1415 {
1416     int32_t                             memoryCounter = 0;
1417     MOS_STATUS                          eStatus = MOS_STATUS_SUCCESS;
1418 
1419     // lock mutex to avoid multi close in multi-threading env
1420     m_mutexLock.Lock();
1421     m_mosUtilInitCount--;
1422     if (m_mosUtilInitCount == 0)
1423     {
1424         MosTraceEventClose();
1425         if (m_mosMemAllocCounter &&
1426             m_mosMemAllocCounterGfx &&
1427             m_mosMemAllocFakeCounter)
1428         {
1429             *m_mosMemAllocCounter -= *m_mosMemAllocFakeCounter;
1430             memoryCounter = *m_mosMemAllocCounter + *m_mosMemAllocCounterGfx;
1431             m_mosMemAllocCounterNoUserFeature    = *m_mosMemAllocCounter;
1432             m_mosMemAllocCounterNoUserFeatureGfx = *m_mosMemAllocCounterGfx;
1433             MOS_OS_VERBOSEMESSAGE("MemNinja leak detection end");
1434             ReportUserSetting(
1435                 userSettingPtr,
1436                 __MEDIA_USER_FEATURE_VALUE_MEMNINJA_COUNTER,
1437                 memoryCounter,
1438                 MediaUserSetting::Group::Device);
1439         }
1440         MosDestroyUserFeature();
1441 
1442 #if (_DEBUG || _RELEASE_INTERNAL)
1443         // MOS maintains a reference counter,
1444         // so if there still is another active lib instance, logs would still be printed.
1445         MosUtilDebug::MosMessageClose();
1446 #endif
1447         MosUtilitiesSpecificNext::UserFeatureDumpDataToFile(MosUtilitiesSpecificNext::m_szUserFeatureFile, MosUtilitiesSpecificNext::m_ufKeyList);
1448         MosUtilitiesSpecificNext::UserFeatureFreeKeyList(MosUtilitiesSpecificNext::m_ufKeyList);
1449         MosUtilitiesSpecificNext::m_ufKeyList = nullptr;
1450     }
1451     m_mutexLock.Unlock();
1452     return eStatus;
1453 }
1454 
MosUserFeatureOpenKey(void * ufKey,const char * lpSubKey,uint32_t ulOptions,uint32_t samDesired,void ** phkResult,MOS_USER_FEATURE_KEY_PATH_INFO * ufInfo)1455 MOS_STATUS MosUtilities::MosUserFeatureOpenKey(
1456     void       *ufKey,
1457     const char *lpSubKey,
1458     uint32_t   ulOptions,
1459     uint32_t   samDesired,
1460     void       **phkResult,
1461     MOS_USER_FEATURE_KEY_PATH_INFO  *ufInfo)
1462 {
1463     MOS_UNUSED(ufInfo);
1464 
1465     return MosUtilitiesSpecificNext::MosUserFeatureOpenKeyFile(ufKey, lpSubKey, ulOptions, samDesired, phkResult);
1466 }
1467 
MosUserFeatureCloseKey(void * ufKey)1468 MOS_STATUS MosUtilities::MosUserFeatureCloseKey(void  *ufKey)
1469 {
1470     MOS_UNUSED(ufKey);
1471     //always return success, because we actually dong't have a key opened.
1472     return MOS_STATUS_SUCCESS;
1473 }
1474 
MosUserFeatureGetValue(void * UFKey,const char * lpSubKey,const char * lpValue,uint32_t dwFlags,uint32_t * pdwType,void * pvData,uint32_t * pcbData)1475 MOS_STATUS MosUtilities::MosUserFeatureGetValue(
1476     void       *UFKey,
1477     const char *lpSubKey,
1478     const char *lpValue,
1479     uint32_t   dwFlags,
1480     uint32_t   *pdwType,
1481     void       *pvData,
1482     uint32_t   *pcbData)
1483 {
1484     return MosUtilitiesSpecificNext::MosUserFeatureGetValueFile(UFKey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData);
1485 
1486 }
1487 
MosUserFeatureQueryValueEx(void * UFKey,char * lpValueName,uint32_t * lpReserved,uint32_t * lpType,char * lpData,uint32_t * lpcbData)1488 MOS_STATUS MosUtilities::MosUserFeatureQueryValueEx(
1489     void            *UFKey,
1490     char            *lpValueName,
1491     uint32_t        *lpReserved,
1492     uint32_t        *lpType,
1493     char            *lpData,
1494     uint32_t        *lpcbData)
1495 {
1496     MOS_UNUSED(lpReserved);
1497     return MosUserFeatureGetValue(UFKey, "", lpValueName, 0, lpType, lpData, lpcbData);
1498 }
1499 
MosUserFeatureSetValueEx(void * UFKey,const char * lpValueName,uint32_t Reserved,uint32_t dwType,uint8_t * lpData,uint32_t cbData)1500 MOS_STATUS MosUtilities::MosUserFeatureSetValueEx(
1501     void            *UFKey,
1502     const char      *lpValueName,
1503     uint32_t        Reserved,
1504     uint32_t        dwType,
1505     uint8_t         *lpData,
1506     uint32_t        cbData)
1507 {
1508     if (dwType == UF_SZ || dwType == UF_MULTI_SZ)
1509     {
1510         if (lpData == nullptr || strlen((const char*)lpData) == 0)
1511         {
1512             MOS_OS_NORMALMESSAGE("NULL string, skip to report");
1513             return MOS_STATUS_SUCCESS;
1514         }
1515     }
1516 
1517     return MosUtilitiesSpecificNext::MosUserFeatureSetValueExFile(UFKey, lpValueName, Reserved, dwType, lpData, cbData);
1518 }
1519 
MosUserFeatureNotifyChangeKeyValue(void * UFKey,int32_t bWatchSubtree,HANDLE hEvent,int32_t fAsynchronous)1520 MOS_STATUS MosUtilities::MosUserFeatureNotifyChangeKeyValue(
1521     void                *UFKey,
1522     int32_t             bWatchSubtree,
1523     HANDLE              hEvent,
1524     int32_t             fAsynchronous)
1525 {
1526     key_t          key;
1527     int32_t        semid;
1528     struct sembuf  operation[1] ;
1529 
1530     key = ftok(MosUtilitiesSpecificNext::m_szUserFeatureFile, 1);
1531     semid = semget(key,1,0);
1532     //change semaphore
1533     operation[0].sem_op  = 1;
1534     operation[0].sem_num = 0;
1535     operation[0].sem_flg = SEM_UNDO;
1536     semop(semid, operation, 1);
1537 
1538     return MOS_STATUS_SUCCESS;
1539 }
1540 
MosInitializeReg(RegBufferMap & regBufferMap)1541 MOS_STATUS MosUtilities::MosInitializeReg(RegBufferMap &regBufferMap)
1542 {
1543     MOS_STATUS status = MOS_STATUS_SUCCESS;
1544 
1545     std::ifstream regStream;
1546     try
1547     {
1548         regStream.open(USER_FEATURE_FILE_NEXT);
1549         if (regStream.good())
1550         {
1551             std::string id       = "";
1552             while(!regStream.eof())
1553             {
1554                 std::string line = "";
1555                 std::getline(regStream, line);
1556                 auto endIndex = line.find("\r");
1557                 if(endIndex != std::string::npos)
1558                 {
1559                     line = line.substr(0, endIndex);
1560                 }
1561                 if (std::string::npos != line.find(USER_SETTING_CONFIG_PATH))
1562                 {
1563                     id = USER_SETTING_CONFIG_PATH;
1564                 }
1565                 else if (std::string::npos != line.find(USER_SETTING_REPORT_PATH))
1566                 {
1567                     id = USER_SETTING_REPORT_PATH;
1568                 }
1569                 else if (line.find("]") != std::string::npos)
1570                 {
1571                     auto mkPos = line.find_last_of("]");
1572                     id = line.substr(0, mkPos+1);
1573                 }
1574                 else
1575                 {
1576                     if (id == USER_SETTING_REPORT_PATH)
1577                     {
1578                         continue;
1579                     }
1580 
1581                     std::size_t pos = line.find("=");
1582                     if (std::string::npos != pos && !id.empty())
1583                     {
1584                         std::string name = line.substr(0,pos);
1585                         std::string value = line.substr(pos+1);
1586                         if (name.size() > 0 && value.size() > 0)
1587                         {
1588                             auto &keys = regBufferMap[id];
1589                             keys[name] = value;
1590                         }
1591                     }
1592                 }
1593             }
1594 
1595         }
1596     }
1597     catch(const std::exception &e)
1598     {
1599         status = MOS_STATUS_FILE_OPEN_FAILED;
1600     }
1601 
1602     regStream.close();
1603 
1604     return status;
1605 }
1606 
MosUninitializeReg(RegBufferMap & regBufferMap)1607 MOS_STATUS MosUtilities::MosUninitializeReg(RegBufferMap &regBufferMap)
1608 {
1609     MOS_STATUS status = MOS_STATUS_SUCCESS;
1610 
1611     if (regBufferMap.size() == 0)
1612     {
1613         return MOS_STATUS_SUCCESS;
1614     }
1615 
1616     auto iter = regBufferMap.find(USER_SETTING_REPORT_PATH);
1617     // No need to write the user setting files if no session [report].
1618     // The session [config] is read only.
1619     if(iter == regBufferMap.end() || iter->second.size() == 0)
1620     {
1621         MOS_OS_NORMALMESSAGE("no report session");
1622         return MOS_STATUS_SUCCESS;
1623     }
1624 
1625     std::ofstream regStream;
1626     try
1627     {
1628 // For release version: writes to the file if it exists,
1629 // skips if it does not exist
1630 // For other version: always writes to the file
1631 #if(_RELEASE)
1632         std::ifstream regFile(USER_FEATURE_FILE_NEXT);
1633         if (regFile.good())
1634         {
1635             regFile.close();
1636             regStream.open(USER_FEATURE_FILE_REPORT, std::ios::out | std::ios::trunc);
1637         }
1638         else
1639         {
1640             regFile.close();
1641             return status;
1642         }
1643 #else
1644         regStream.open(USER_FEATURE_FILE_REPORT, std::ios::out | std::ios::trunc);
1645 #endif
1646         if (regStream.good())
1647         {
1648             regStream << iter->first << "\n";
1649 
1650             auto &keys = iter->second;
1651             for (auto key: keys)
1652             {
1653                 auto name = key.first;
1654                 regStream << key.first << "=" << key.second << "\n";
1655             }
1656 
1657             keys.clear();
1658             regStream << std::endl;
1659             regBufferMap.clear();
1660             regStream.flush();
1661         }
1662     }
1663     catch(const std::exception &e)
1664     {
1665         status = MOS_STATUS_FILE_WRITE_FAILED;
1666     }
1667 
1668     regStream.close();
1669     return status;
1670 }
1671 
MosCreateRegKey(UFKEY_NEXT keyHandle,const std::string & subKey,uint32_t samDesired,PUFKEY_NEXT key,RegBufferMap & regBufferMap)1672 MOS_STATUS MosUtilities::MosCreateRegKey(
1673     UFKEY_NEXT keyHandle,
1674     const std::string &subKey,
1675     uint32_t samDesired,
1676     PUFKEY_NEXT key,
1677     RegBufferMap &regBufferMap)
1678 {
1679     MOS_UNUSED(keyHandle);
1680     MOS_UNUSED(samDesired);
1681     MOS_OS_CHK_NULL_RETURN(key);
1682     auto ret = regBufferMap.find(subKey);
1683 
1684     if (ret == regBufferMap.end())
1685     {
1686         regBufferMap[subKey] = {};
1687     }
1688 
1689     *key = subKey;
1690     return MOS_STATUS_SUCCESS;
1691 }
1692 
MosOpenRegKey(UFKEY_NEXT keyHandle,const std::string & subKey,uint32_t samDesired,PUFKEY_NEXT key,RegBufferMap & regBufferMap)1693 MOS_STATUS MosUtilities::MosOpenRegKey(
1694     UFKEY_NEXT keyHandle,
1695     const std::string &subKey,
1696     uint32_t samDesired,
1697     PUFKEY_NEXT key,
1698     RegBufferMap &regBufferMap)
1699 {
1700     std::string tempSubKey = subKey;
1701 
1702     if (subKey.find_first_of("\\") != std::string::npos)
1703     {
1704         tempSubKey = subKey.substr(1);
1705     }
1706 
1707     if (tempSubKey.find_first_of("[") == std::string::npos)
1708     {
1709         tempSubKey = "[" + tempSubKey + "]";
1710     }
1711     return MosCreateRegKey(keyHandle, tempSubKey, samDesired, key, regBufferMap);
1712 }
1713 
MosCloseRegKey(UFKEY_NEXT keyHandle)1714 MOS_STATUS MosUtilities::MosCloseRegKey(
1715     UFKEY_NEXT keyHandle)
1716 {
1717     MOS_UNUSED(keyHandle);
1718     return MOS_STATUS_SUCCESS;
1719 }
1720 
MosReadEnvVariable(const std::string & envName,MOS_USER_FEATURE_VALUE_TYPE defaultType,MediaUserSetting::Value & data)1721 MOS_STATUS MosUtilities::MosReadEnvVariable(
1722     const std::string           &envName,
1723     MOS_USER_FEATURE_VALUE_TYPE defaultType,
1724     MediaUserSetting::Value     &data)
1725 {
1726     char *retVal = getenv(envName.c_str());
1727     if (retVal != nullptr)
1728     {
1729         std::string strData = retVal;
1730         auto status = StrToMediaUserSettingValue(strData, defaultType, data);
1731         return status;
1732     }
1733 
1734     return MOS_STATUS_INVALID_PARAMETER;
1735 }
1736 
MosEnvVariableEqual(const std::string envName,const std::string targetVal)1737 bool MosUtilities::MosEnvVariableEqual(
1738     const std::string            envName,
1739     const std::string            targetVal)
1740 {
1741     char *retVal = getenv(envName.c_str());
1742     bool res = false;
1743     if (retVal != nullptr)
1744     {
1745         res = strcmp(retVal, targetVal.c_str()) ? false : true;
1746     }
1747     return res;
1748 }
1749 
MosGetRegValue(UFKEY_NEXT keyHandle,const std::string & valueName,MOS_USER_FEATURE_VALUE_TYPE defaultType,MediaUserSetting::Value & data,RegBufferMap & regBufferMap)1750 MOS_STATUS MosUtilities::MosGetRegValue(
1751     UFKEY_NEXT keyHandle,
1752     const std::string &valueName,
1753     MOS_USER_FEATURE_VALUE_TYPE defaultType,
1754     MediaUserSetting::Value &data,
1755     RegBufferMap &regBufferMap)
1756 {
1757     MOS_STATUS status = MOS_STATUS_SUCCESS;
1758 
1759     if (regBufferMap.end() == regBufferMap.find(keyHandle))
1760     {
1761         return MOS_STATUS_USER_FEATURE_KEY_OPEN_FAILED;
1762     }
1763 
1764     try
1765     {
1766         auto keys = regBufferMap[keyHandle];
1767         auto it = keys.find(valueName);
1768         if (it == keys.end())
1769         {
1770             return MOS_STATUS_USER_FEATURE_KEY_OPEN_FAILED;
1771         }
1772         status = MosUtilities::StrToMediaUserSettingValue(it->second, defaultType, data);
1773     }
1774     catch(const std::exception &e)
1775     {
1776         status = MOS_STATUS_INVALID_PARAMETER;
1777     }
1778 
1779     return status;
1780 }
1781 
MosPrintCPUAllocateMemory(int32_t event_id,int32_t level,int32_t param_id_1,int64_t value_1,int32_t param_id_2,int64_t value_2,const char * funName,const char * fileName,int32_t line)1782 MOS_STATUS MosUtilities::MosPrintCPUAllocateMemory(int32_t event_id, int32_t level, int32_t param_id_1, int64_t value_1, int32_t param_id_2, int64_t value_2,
1783     const char *funName, const char *fileName, int32_t line)
1784 {
1785 #if (_RELEASE_INTERNAL)
1786     if (MOS_IS_MEMORY_FOOT_PRINT_ENABLED())
1787     {
1788         MosAtomicIncrement(m_mosMemAllocIndex);
1789         MT_LOG3(event_id, level, param_id_1, value_1, MT_MEMORY_INDEX, *MosUtilities::m_mosMemAllocIndex, param_id_2, value_2);
1790     }
1791 
1792 #endif
1793     return MOS_STATUS_SUCCESS;
1794 }
1795 
MosPrintCPUDestroyMemory(int32_t event_id,int32_t level,int32_t param_id_1,int64_t value_1,const char * funName,const char * fileName,int32_t line)1796 MOS_STATUS MosUtilities::MosPrintCPUDestroyMemory(int32_t event_id, int32_t level, int32_t param_id_1, int64_t value_1,
1797     const char *funName, const char *fileName, int32_t line)
1798 {
1799 #if (_RELEASE_INTERNAL)
1800     if (MOS_IS_MEMORY_FOOT_PRINT_ENABLED())
1801     {
1802         MosAtomicDecrement(m_mosMemAllocIndex);
1803         MT_LOG2(event_id, level, param_id_1, value_1, MT_MEMORY_INDEX, *MosUtilities::m_mosMemAllocIndex);
1804     }
1805 #endif
1806     return MOS_STATUS_SUCCESS;
1807 }
1808 
MosSetRegValue(UFKEY_NEXT keyHandle,const std::string & valueName,const MediaUserSetting::Value & data,RegBufferMap & regBufferMap)1809 MOS_STATUS MosUtilities::MosSetRegValue(
1810     UFKEY_NEXT keyHandle,
1811     const std::string &valueName,
1812     const MediaUserSetting::Value &data,
1813     RegBufferMap &regBufferMap)
1814 {
1815     if (regBufferMap.end() == regBufferMap.find(keyHandle))
1816     {
1817         return MOS_STATUS_INVALID_PARAMETER;
1818     }
1819 
1820     MOS_STATUS status = MOS_STATUS_SUCCESS;
1821     try
1822     {
1823         auto &keys = regBufferMap[keyHandle];
1824 
1825         keys[valueName] = data.ConstString();
1826     }
1827     catch(const std::exception &e)
1828     {
1829         status = MOS_STATUS_INVALID_PARAMETER;
1830     }
1831 
1832     return status;
1833 }
1834 
MosCreateEventEx(void * lpEventAttributes,char * lpName,uint32_t dwFlags)1835 HANDLE MosUtilities::MosCreateEventEx(
1836     void                *lpEventAttributes,
1837     char                *lpName,
1838     uint32_t            dwFlags)
1839 {
1840     int32_t     semid;
1841     key_t       key;
1842     union semun
1843     {
1844         int32_t val;
1845         struct semid_ds *Buf;
1846         unsigned short *array;
1847     } semctl_arg;
1848 
1849     semid = 0;
1850 
1851     //Generate a unique key, U can also supply a value instead
1852     key = ftok(MosUtilitiesSpecificNext::m_szUserFeatureFile, 1);
1853     semid = semget(key,  1, 0666 | IPC_CREAT );
1854     semctl_arg.val = 0; //Setting semval to 0
1855     semctl(semid, 0, SETVAL, semctl_arg);
1856 
1857     HANDLE ret = reinterpret_cast<HANDLE>(semid);
1858 
1859     return ret;
1860 }
1861 
MosUserFeatureWaitForSingleObject(PTP_WAIT * phNewWaitObject,HANDLE hObject,void * Callback,void * Context)1862 int32_t MosUtilities::MosUserFeatureWaitForSingleObject(
1863     PTP_WAIT*           phNewWaitObject,
1864     HANDLE              hObject,
1865     void                *Callback,
1866     void                *Context)
1867 {
1868     int32_t                  iRet;
1869     int32_t                  semid;
1870     struct sembuf            operation[1];
1871     pid_t                    pid;
1872     MOS_UserFeatureCallback  pCallback;
1873     LARGE_INTEGER            largeInteger;
1874 
1875     pCallback = (MOS_UserFeatureCallback)Callback;
1876 
1877     iRet  = 0;
1878 
1879     largeInteger.QuadPart = (int64_t)hObject;
1880 
1881     semid = largeInteger.u.LowPart;
1882 
1883     if ((pid=fork()) == -1)
1884     {
1885         printf("error\n");
1886     }
1887     else if(pid == 0)
1888     {
1889         while(1)
1890         {
1891             operation[0].sem_op = -1;
1892             operation[0].sem_num = 0;
1893             //now waiting
1894             semop(semid, operation, 1);
1895             pCallback(Context, 0);
1896         }
1897         exit(0);
1898     }
1899     else
1900     {
1901         iRet = pid;
1902     }
1903 
1904     *phNewWaitObject = reinterpret_cast<PTP_WAIT>(iRet);
1905 
1906     return (iRet != 0);
1907 }
1908 
MosUnregisterWaitEx(PTP_WAIT hWaitHandle)1909 int32_t MosUtilities::MosUnregisterWaitEx(PTP_WAIT hWaitHandle)
1910 {
1911     int32_t       iPid;
1912     LARGE_INTEGER largeInteger;
1913 
1914     largeInteger.QuadPart = (int64_t)hWaitHandle;
1915 
1916     iPid = largeInteger.u.LowPart;
1917     kill(iPid, SIGKILL);
1918     return true;
1919 }
1920 
1921 #if (_DEBUG || _RELEASE_INTERNAL)
MosGetApoMosEnabledUserFeatureFile()1922 MOS_STATUS MosUtilities::MosGetApoMosEnabledUserFeatureFile()
1923 {
1924     // Get use user feature file from env, instead of default.
1925     FILE *       fp      = nullptr;
1926     static char *tmpFile = getenv("GFX_FEATURE_FILE");
1927 
1928     if (tmpFile != nullptr)
1929     {
1930         if ((fp = fopen(tmpFile, "r")) != nullptr)
1931         {
1932             if (MosUtilitiesSpecificNext::m_szUserFeatureFile != tmpFile)
1933                 MosUtilitiesSpecificNext::m_szUserFeatureFile = tmpFile;
1934             fclose(fp);
1935             MOS_OS_NORMALMESSAGE("using %s for USER_FEATURE_FILE", MosUtilitiesSpecificNext::m_szUserFeatureFile);
1936         }
1937         else
1938         {
1939             MOS_OS_ASSERTMESSAGE("Can't open %s for USER_FEATURE_FILE!!!", tmpFile);
1940             return MOS_STATUS_FILE_NOT_FOUND;
1941         }
1942     }
1943     return MOS_STATUS_SUCCESS;
1944 }
1945 #endif
1946 
MosReadMediaSoloEnabledUserFeature(bool & mediasoloEnabled)1947 MOS_STATUS MosUtilities::MosReadMediaSoloEnabledUserFeature(bool &mediasoloEnabled)
1948 {
1949     MOS_STATUS eStatus  = MOS_STATUS_SUCCESS;
1950 
1951 #if MOS_MEDIASOLO_SUPPORTED
1952 
1953     void *     UFKey    = nullptr;
1954     uint32_t   dwUFSize = 0;
1955     uint32_t   data     = 0;
1956 
1957 #if (_DEBUG || _RELEASE_INTERNAL)
1958     eStatus = MosGetApoMosEnabledUserFeatureFile();
1959     if (eStatus != MOS_STATUS_SUCCESS)
1960     {
1961         MOS_OS_NORMALMESSAGE("Failed to get user feature file, error status %d.", eStatus);
1962         return eStatus;
1963     }
1964 #endif
1965 
1966     eStatus = MosUserFeatureOpen(
1967         MOS_USER_FEATURE_TYPE_USER,
1968         __MEDIA_USER_FEATURE_SUBKEY_INTERNAL,
1969         KEY_READ,
1970         &UFKey,
1971         nullptr);
1972 
1973     if (eStatus != MOS_STATUS_SUCCESS)
1974     {
1975         MOS_OS_NORMALMESSAGE("Failed to open user feature key , error status %d.", eStatus);
1976         return eStatus;
1977     }
1978 
1979     eStatus = MosUserFeatureGetValue(
1980         UFKey,
1981         nullptr,
1982         __MEDIA_USER_FEATURE_VALUE_MEDIASOLO_ENABLE,
1983         RRF_RT_UF_DWORD,
1984         nullptr,
1985         &data,
1986         &dwUFSize);
1987 
1988     if (eStatus == MOS_STATUS_SUCCESS && data > 0)
1989     {
1990         mediasoloEnabled = true;
1991     }
1992     MosUserFeatureCloseKey(UFKey);
1993 
1994 #endif
1995     return eStatus;
1996 }
1997 
MosReadApoDdiEnabledUserFeature(uint32_t & userfeatureValue,char * path,MediaUserSettingSharedPtr userSettingPtr)1998 MOS_STATUS MosUtilities::MosReadApoDdiEnabledUserFeature(uint32_t &userfeatureValue, char *path, MediaUserSettingSharedPtr userSettingPtr)
1999 {
2000     MOS_STATUS eStatus  = MOS_STATUS_SUCCESS;
2001     MOS_UNUSED(path);
2002 
2003     uint32_t enableApoDdi = 0;
2004     eStatus = ReadUserSetting(
2005         userSettingPtr,
2006         enableApoDdi,
2007         "ApoDdiEnable",
2008         MediaUserSetting::Group::Device);
2009 
2010     if (eStatus != MOS_STATUS_SUCCESS)
2011     {
2012         // It could be there is no this use feature key.
2013         MOS_OS_NORMALMESSAGE("Failed to read ApoDdiEnable user feature key value, error status %d", eStatus);
2014     }
2015     userfeatureValue = enableApoDdi ? true : false;
2016     return eStatus;
2017 }
2018 
MosReadApoMosEnabledUserFeature(uint32_t & userfeatureValue,char * path,MediaUserSettingSharedPtr userSettingPtr)2019 MOS_STATUS MosUtilities::MosReadApoMosEnabledUserFeature(uint32_t &userfeatureValue, char *path, MediaUserSettingSharedPtr userSettingPtr)
2020 {
2021     MOS_STATUS eStatus  = MOS_STATUS_SUCCESS;
2022     MOS_USER_FEATURE_VALUE_DATA userFeatureData     = {};
2023     MOS_UNUSED(path);
2024 
2025 
2026     uint32_t enableApoMos = 0;
2027     eStatus = ReadUserSetting(
2028         userSettingPtr,
2029         enableApoMos,
2030         "ApoMosEnable",
2031         MediaUserSetting::Group::Device);
2032 
2033     if (eStatus != MOS_STATUS_SUCCESS)
2034     {
2035         // It could be there is no this use feature key.
2036         MOS_OS_NORMALMESSAGE("Failed to read ApoMosEnable  user feature key value, error status %d", eStatus);
2037     }
2038     userfeatureValue = enableApoMos ? true : false;
2039     return eStatus;
2040 }
2041 
MosUserFeatureParsePath(PMOS_USER_FEATURE_INTERFACE pOsUserFeatureInterface,char * const pInputPath,PMOS_USER_FEATURE_TYPE pUserFeatureType,char ** ppSubPath)2042 MOS_STATUS MosUtilities::MosUserFeatureParsePath(
2043     PMOS_USER_FEATURE_INTERFACE     pOsUserFeatureInterface,
2044     char * const                    pInputPath,
2045     PMOS_USER_FEATURE_TYPE          pUserFeatureType,
2046     char                            **ppSubPath)
2047 {
2048     char                            *pValue;
2049     MOS_USER_FEATURE_TYPE           UserFeatureType;
2050     size_t                          uUFKeyLen;
2051     size_t                          uHKeyLen;
2052     size_t                          uValLen;
2053     size_t                          uSepLen;
2054     MOS_UNUSED(pOsUserFeatureInterface);
2055 
2056     //-------------------------------------------
2057     // the UserFeature interface is not currently an actual interface, just a collection
2058     // of functions, so pOsUserFeatureInterface will always be nullptr until this changes
2059     //MOS_OS_ASSERT(pOsUserFeatureInterface);
2060     MOS_OS_ASSERT(pInputPath);
2061     MOS_OS_ASSERT(strlen(pInputPath) > 0);
2062     MOS_OS_ASSERT(pUserFeatureType);
2063     MOS_OS_ASSERT(ppSubPath);
2064     //-------------------------------------------
2065 
2066     pValue = nullptr;
2067 
2068     pValue = strstr(pInputPath, MOS_UF_SEPARATOR);
2069 
2070     if (!pValue)
2071     {
2072         MOS_OS_ASSERTMESSAGE("Invalid user feature key %s.", pInputPath);
2073         return MOS_STATUS_INVALID_PARAMETER;
2074     }
2075 
2076     uUFKeyLen   = strlen(pInputPath);
2077     uValLen     = strlen(pValue);
2078     uSepLen     = strlen(MOS_UF_SEPARATOR);
2079     uHKeyLen    = uUFKeyLen - uValLen;
2080 
2081     if (uHKeyLen == 0)
2082     {
2083         MOS_OS_ASSERTMESSAGE("Invalid user feature key %s. Path separator in the begining.", pInputPath);
2084         return MOS_STATUS_INVALID_PARAMETER;
2085     }
2086 
2087     if (uValLen <= uSepLen)
2088     {
2089         MOS_OS_ASSERTMESSAGE("Invalid user feature key %s. No value after path separator.", pInputPath);
2090         return MOS_STATUS_INVALID_PARAMETER;
2091     }
2092 
2093     if ((uHKeyLen == strlen(MOS_UFKEY_EXT)) &&
2094         (strncmp(pInputPath, MOS_UFKEY_EXT, uHKeyLen) == 0))
2095     {
2096         UserFeatureType = MOS_USER_FEATURE_TYPE_SYSTEM;
2097     }
2098     else if ((uHKeyLen == strlen(MOS_UFKEY_INT)) &&
2099         (strncmp(pInputPath, MOS_UFKEY_INT, uHKeyLen) == 0))
2100     {
2101         UserFeatureType = MOS_USER_FEATURE_TYPE_USER;
2102     }
2103     else
2104     {
2105         MOS_OS_ASSERTMESSAGE("Invalid user feature key %s. Expected %s or %s.", pInputPath, MOS_UFKEY_EXT, MOS_UFKEY_INT);
2106         return MOS_STATUS_INVALID_PARAMETER;
2107     }
2108 
2109     pValue             = pValue + uSepLen;
2110 
2111     *pUserFeatureType  = UserFeatureType;
2112     *ppSubPath         = pValue;
2113 
2114     return MOS_STATUS_SUCCESS;
2115 }
2116 
MosGetLogicalCoreNumber()2117 uint32_t MosUtilities::MosGetLogicalCoreNumber()
2118 {
2119     return sysconf(_SC_NPROCESSORS_CONF);
2120 }
2121 
MosCreateThread(void * ThreadFunction,void * ThreadData)2122 MOS_THREADHANDLE MosUtilities::MosCreateThread(
2123     void                        *ThreadFunction,
2124     void                        *ThreadData)
2125 {
2126     MOS_THREADHANDLE Thread;
2127 
2128     if (0 != pthread_create(&Thread, nullptr, (void *(*)(void *))ThreadFunction, ThreadData))
2129     {
2130         Thread = 0;
2131         MOS_OS_ASSERTMESSAGE("Create thread failed.");
2132     }
2133 
2134     return Thread;
2135 }
2136 
MosGetThreadId(MOS_THREADHANDLE hThread)2137 uint32_t MosUtilities::MosGetThreadId(
2138     MOS_THREADHANDLE            hThread)
2139 {
2140     MOS_UNUSED(hThread);
2141     return 0;
2142 }
2143 
MosGetCurrentThreadId()2144 uint32_t MosUtilities::MosGetCurrentThreadId()
2145 {
2146     return (uint32_t)pthread_self();
2147 }
2148 
MosWaitThread(MOS_THREADHANDLE hThread)2149 MOS_STATUS MosUtilities::MosWaitThread(
2150     MOS_THREADHANDLE            hThread)
2151 {
2152     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
2153 
2154     if (hThread == 0)
2155     {
2156         MOS_OS_ASSERTMESSAGE("MOS wait thread failed, invalid thread handle.");
2157         eStatus = MOS_STATUS_INVALID_PARAMETER;
2158     }
2159     else if (0 != pthread_join(hThread, nullptr))
2160     {
2161         MOS_OS_ASSERTMESSAGE("Failed to join thread.");
2162         eStatus = MOS_STATUS_UNKNOWN;
2163     }
2164 
2165     return eStatus;
2166 }
2167 
MosCreateMutex(uint32_t spinCount)2168 PMOS_MUTEX MosUtilities::MosCreateMutex(uint32_t spinCount)
2169 {
2170     PMOS_MUTEX pMutex;
2171     MOS_UNUSED(spinCount);
2172     pMutex = (PMOS_MUTEX)MOS_AllocMemory(sizeof(*pMutex));
2173     if (pMutex != nullptr)
2174     {
2175         if (pthread_mutex_init(pMutex, nullptr))
2176         {
2177             MOS_FreeMemory(pMutex);
2178             pMutex = nullptr;
2179         }
2180     }
2181 
2182     return pMutex;
2183 }
2184 
MosDestroyMutex(PMOS_MUTEX & pMutex)2185 MOS_STATUS MosUtilities::MosDestroyMutex(PMOS_MUTEX &pMutex)
2186 {
2187     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2188 
2189     if (pMutex)
2190     {
2191         if (pthread_mutex_destroy(pMutex))
2192         {
2193             eStatus = MOS_STATUS_UNKNOWN;
2194         }
2195         MOS_FreeMemAndSetNull(pMutex);
2196     }
2197 
2198     return eStatus;
2199 }
2200 
MosLockMutex(PMOS_MUTEX pMutex)2201 MOS_STATUS MosUtilities::MosLockMutex(PMOS_MUTEX pMutex)
2202 {
2203     MOS_OS_CHK_NULL_RETURN(pMutex);
2204 
2205     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2206 
2207     if (pthread_mutex_lock(pMutex))
2208     {
2209         eStatus = MOS_STATUS_UNKNOWN;
2210     }
2211 
2212     return eStatus;
2213 }
2214 
MosUnlockMutex(PMOS_MUTEX pMutex)2215 MOS_STATUS MosUtilities::MosUnlockMutex(PMOS_MUTEX pMutex)
2216 {
2217     MOS_OS_CHK_NULL_RETURN(pMutex);
2218 
2219     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2220 
2221     if (pthread_mutex_unlock(pMutex))
2222     {
2223         eStatus = MOS_STATUS_UNKNOWN;
2224     }
2225 
2226     return eStatus;
2227 }
2228 
MosCreateSemaphore(uint32_t uiInitialCount,uint32_t uiMaximumCount)2229 PMOS_SEMAPHORE MosUtilities::MosCreateSemaphore(
2230     uint32_t            uiInitialCount,
2231     uint32_t            uiMaximumCount)
2232 {
2233     PMOS_SEMAPHORE pSemaphore = nullptr;
2234     MOS_UNUSED(uiMaximumCount);
2235 
2236     pSemaphore = (PMOS_SEMAPHORE)MOS_AllocMemory(sizeof(*pSemaphore));
2237     if (!pSemaphore)
2238         return nullptr;
2239     if (sem_init(pSemaphore, 0, uiInitialCount))
2240     {
2241         MOS_SafeFreeMemory(pSemaphore);
2242         pSemaphore = nullptr;
2243     }
2244 
2245     return pSemaphore;
2246 }
2247 
MosDestroySemaphore(PMOS_SEMAPHORE & pSemaphore)2248 MOS_STATUS MosUtilities::MosDestroySemaphore(
2249     PMOS_SEMAPHORE              &pSemaphore)
2250 {
2251     MOS_FreeMemAndSetNull(pSemaphore);
2252     return MOS_STATUS_SUCCESS;
2253 }
2254 
MosWaitSemaphore(PMOS_SEMAPHORE pSemaphore,uint32_t uiMilliseconds)2255 MOS_STATUS MosUtilities::MosWaitSemaphore(
2256     PMOS_SEMAPHORE              pSemaphore,
2257     uint32_t                    uiMilliseconds)
2258 {
2259     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
2260 
2261     if (uiMilliseconds == INFINITE)
2262     {
2263         if (sem_wait(pSemaphore))
2264         {
2265             eStatus = MOS_STATUS_UNKNOWN;
2266         }
2267     }
2268     else
2269     {
2270         struct timespec time = {
2271             (int32_t)uiMilliseconds / 1000000,
2272             ((int32_t)uiMilliseconds % 1000000) * 1000};
2273 
2274         if (sem_timedwait(pSemaphore, &time))
2275         {
2276             eStatus = MOS_STATUS_UNKNOWN;
2277         }
2278     }
2279 
2280     return eStatus;
2281 }
2282 
MosPostSemaphore(PMOS_SEMAPHORE pSemaphore,uint32_t uiPostCount)2283 MOS_STATUS MosUtilities::MosPostSemaphore(
2284     PMOS_SEMAPHORE              pSemaphore,
2285     uint32_t                    uiPostCount)
2286 {
2287     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
2288 
2289     if (uiPostCount > 0)
2290     {
2291         while (uiPostCount--)
2292         {
2293             if (sem_post(pSemaphore))
2294             {
2295                 eStatus = MOS_STATUS_UNKNOWN;
2296                 break;
2297             }
2298         }
2299     }
2300     else
2301     {
2302         eStatus = MOS_STATUS_UNKNOWN;
2303     }
2304 
2305     return eStatus;
2306 }
2307 
MosWaitForSingleObject(void * pObject,uint32_t uiMilliseconds)2308 uint32_t MosUtilities::MosWaitForSingleObject(
2309     void                        *pObject,
2310     uint32_t                    uiMilliseconds)
2311 {
2312     uint32_t WaitSignal = 0;
2313     MOS_UNUSED(pObject);
2314     MOS_UNUSED(uiMilliseconds);
2315 
2316     return WaitSignal;
2317 }
2318 
MosWaitForMultipleObjects(uint32_t uiThreadCount,void ** ppObjects,uint32_t bWaitAll,uint32_t uiMilliseconds)2319 uint32_t MosUtilities::MosWaitForMultipleObjects(
2320     uint32_t                    uiThreadCount,
2321     void                        **ppObjects,
2322     uint32_t                    bWaitAll,
2323     uint32_t                    uiMilliseconds)
2324 {
2325     MOS_UNUSED(uiThreadCount);
2326     MOS_UNUSED(ppObjects);
2327     MOS_UNUSED(bWaitAll);
2328     MOS_UNUSED(uiMilliseconds);
2329     return 0;
2330 }
2331 
MosAtomicIncrement(int32_t * pValue)2332 int32_t MosUtilities::MosAtomicIncrement(
2333     int32_t *pValue)
2334 {
2335     if (pValue != nullptr)
2336     {
2337         return __sync_add_and_fetch(pValue, 1);
2338     }
2339     return 0;
2340 }
2341 
MosAtomicDecrement(int32_t * pValue)2342 int32_t MosUtilities::MosAtomicDecrement(
2343     int32_t *pValue)
2344 {
2345     if (pValue != nullptr)
2346     {
2347         return __sync_sub_and_fetch(pValue, 1);
2348     }
2349     return 0;
2350 }
2351 
2352 #ifndef WDDM_LINUX
MosStatusToOsResult(MOS_STATUS eStatus)2353 VAStatus MosUtilities::MosStatusToOsResult(
2354     MOS_STATUS               eStatus)
2355 {
2356     switch (eStatus)
2357     {
2358         case MOS_STATUS_SUCCESS:                        return VA_STATUS_SUCCESS;
2359         case MOS_STATUS_NO_SPACE:                       return VA_STATUS_ERROR_ALLOCATION_FAILED;
2360         case MOS_STATUS_INVALID_PARAMETER:              return VA_STATUS_ERROR_INVALID_PARAMETER;
2361         case MOS_STATUS_INVALID_HANDLE:                 return VA_STATUS_ERROR_INVALID_BUFFER;
2362         case MOS_STATUS_NULL_POINTER:                   return VA_STATUS_ERROR_INVALID_CONTEXT;
2363         default:                                        return VA_STATUS_ERROR_OPERATION_FAILED;
2364     }
2365 
2366     return VA_STATUS_ERROR_OPERATION_FAILED;
2367 }
2368 
OsResultToMOSStatus(VAStatus eResult)2369 MOS_STATUS MosUtilities::OsResultToMOSStatus(
2370     VAStatus                 eResult)
2371 {
2372     switch (eResult)
2373     {
2374         case VA_STATUS_SUCCESS:                     return MOS_STATUS_SUCCESS;
2375         case VA_STATUS_ERROR_ALLOCATION_FAILED:     return MOS_STATUS_NO_SPACE;
2376         case VA_STATUS_ERROR_INVALID_PARAMETER:     return MOS_STATUS_INVALID_PARAMETER;
2377         case VA_STATUS_ERROR_INVALID_BUFFER:        return MOS_STATUS_INVALID_HANDLE;
2378         case VA_STATUS_ERROR_INVALID_CONTEXT:       return MOS_STATUS_NULL_POINTER;
2379         default:                                    return MOS_STATUS_UNKNOWN;
2380     }
2381 
2382     return MOS_STATUS_UNKNOWN;
2383 }
2384 #else
MosStatusToOsResult(MOS_STATUS eStatus)2385 MOS_OSRESULT MosUtilities::MosStatusToOsResult(
2386     MOS_STATUS eStatus)
2387 {
2388     if (eStatus < MOS_STATUS_SUCCESS)
2389     {
2390         // It is in fact an HRESULT already, do nothing
2391         return (MOS_OSRESULT)eStatus;
2392     }
2393 
2394     switch (eStatus)
2395     {
2396     case MOS_STATUS_SUCCESS:
2397         return MOS_OSSOK;
2398     case MOS_STATUS_NO_SPACE:
2399         return MOS_OSEOUTOFMEMORY;
2400     case MOS_STATUS_INVALID_PARAMETER:
2401         return MOS_OSEINVALIDARG;
2402     case MOS_STATUS_INVALID_HANDLE:
2403         return MOS_OSEHANDLE;
2404     case MOS_STATUS_NULL_POINTER:
2405         return MOS_OSEPOINTER;
2406     case MOS_STATUS_UNIMPLEMENTED:
2407         return MOS_OSENOTIMPL;
2408     default:
2409         return MOS_OSEFAIL;
2410     }
2411 
2412     return MOS_OSEFAIL;
2413 }
2414 
OsResultToMOSStatus(MOS_OSRESULT eResult)2415 MOS_STATUS MosUtilities::OsResultToMOSStatus(
2416     MOS_OSRESULT eResult)
2417 {
2418     switch (eResult)
2419     {
2420     case MOS_OSSOK:
2421         return MOS_STATUS_SUCCESS;
2422     case MOS_OSEOUTOFMEMORY:
2423         return MOS_STATUS_NO_SPACE;
2424     case MOS_OSEINVALIDARG:
2425         return MOS_STATUS_INVALID_PARAMETER;
2426     case MOS_OSEHANDLE:
2427         return MOS_STATUS_INVALID_HANDLE;
2428     case MOS_OSEPOINTER:
2429         return MOS_STATUS_NULL_POINTER;
2430     default:
2431         return MOS_STATUS_UNKNOWN;
2432     }
2433 
2434     return MOS_STATUS_UNKNOWN;
2435 }
2436 #endif
MosGetLocalTime(struct tm * Tm)2437 MOS_STATUS MosUtilities::MosGetLocalTime(
2438     struct tm* Tm)
2439 {
2440     MOS_STATUS     eStatus = MOS_STATUS_SUCCESS;
2441     struct tm      *pTm;
2442     time_t         lTime = time(nullptr);
2443     pTm = localtime(&lTime);
2444     if(pTm == nullptr)
2445     {
2446         MOS_OS_ASSERTMESSAGE("Failed to get localtime.");
2447         eStatus = MOS_STATUS_UNKNOWN;
2448         return eStatus;
2449     }
2450 
2451     eStatus = MosSecureMemcpy(Tm, sizeof(struct tm), pTm, sizeof(struct tm));
2452     return eStatus;
2453 }
2454 
MosTraceEventInit()2455 void MosUtilities::MosTraceEventInit()
2456 {
2457     char *val = getenv("GFX_MEDIA_TRACE");
2458     if (val)
2459     {
2460         MosUtilitiesSpecificNext::m_filterEnv = strtoll(val, nullptr, 0);
2461         val = getenv("GFX_MEDIA_TRACE_LEVEL");
2462         if (val)
2463         {
2464             MosUtilitiesSpecificNext::m_levelEnv = static_cast<uint32_t>(strtoll(val, nullptr, 0));
2465         }
2466         m_mosTraceEnable = true;
2467         m_mosTraceFilter = &MosUtilitiesSpecificNext::m_filterEnv;
2468         m_mosTraceLevel  = reinterpret_cast<uint8_t *>(&MosUtilitiesSpecificNext::m_levelEnv);
2469     }
2470     else
2471     {
2472         int fd = open(TRACE_SETTING_PATH, O_RDONLY);
2473         if (fd < 0)
2474         {
2475             return;
2476         }
2477         void *addr = mmap(NULL, TRACE_SETTING_SIZE, PROT_READ, MAP_SHARED, fd, 0);
2478         close(fd); // close first, map addr still valid after close
2479         if (addr == MAP_FAILED)
2480         {
2481             return;
2482         }
2483         m_mosTraceControlData = reinterpret_cast<const MtControlData *>(addr);
2484 
2485         m_mosTraceEnable = &m_mosTraceControlData->enable;
2486         m_mosTraceFilter = {
2487                         m_mosTraceControlData->filter,
2488                         sizeof(m_mosTraceControlData->filter) / sizeof(uint64_t)};
2489         m_mosTraceLevel = &m_mosTraceControlData->level;
2490     }
2491 
2492     // close first, if already opened.
2493     if (MosUtilitiesSpecificNext::m_mosTraceFd >= 0)
2494     {
2495         close(MosUtilitiesSpecificNext::m_mosTraceFd);
2496         MosUtilitiesSpecificNext::m_mosTraceFd = -1;
2497     }
2498     MosUtilitiesSpecificNext::m_mosTraceFd = open(MosUtilitiesSpecificNext::m_mosTracePath, O_WRONLY);
2499     return;
2500 }
2501 
MosTraceEventClose()2502 void MosUtilities::MosTraceEventClose()
2503 {
2504     m_mosTraceEnable.Reset();
2505     m_mosTraceFilter.Reset();
2506     m_mosTraceLevel.Reset();
2507     if (m_mosTraceControlData)
2508     {
2509         munmap((void *)m_mosTraceControlData, TRACE_SETTING_SIZE);
2510         m_mosTraceControlData = nullptr;
2511     }
2512     if (MosUtilitiesSpecificNext::m_mosTraceFd >= 0)
2513     {
2514         close(MosUtilitiesSpecificNext::m_mosTraceFd);
2515         MosUtilitiesSpecificNext::m_mosTraceFd = -1;
2516     }
2517     MosUtilitiesSpecificNext::m_filterEnv = 0;
2518     MosUtilitiesSpecificNext::m_levelEnv  = {};
2519     return;
2520 }
2521 
MosTraceSetupInfo(uint32_t DrvVer,uint32_t PlatFamily,uint32_t RenderFamily,uint32_t DeviceID)2522 void MosUtilities::MosTraceSetupInfo(uint32_t DrvVer, uint32_t PlatFamily, uint32_t RenderFamily, uint32_t DeviceID)
2523 {
2524     // not implemented
2525 }
2526 
MosTraceEvent(uint16_t usId,uint8_t ucType,const void * pArg1,uint32_t dwSize1,const void * pArg2,uint32_t dwSize2)2527 void MosUtilities::MosTraceEvent(
2528     uint16_t         usId,
2529     uint8_t          ucType,
2530     const void       *pArg1,
2531     uint32_t         dwSize1,
2532     const void       *pArg2,
2533     uint32_t         dwSize2)
2534 {
2535     if (!m_mosTraceEnable)
2536     {
2537         return; // skip if trace not enabled from share memory
2538     }
2539 
2540     if (MosUtilitiesSpecificNext::m_mosTraceFd >= 0 &&
2541         TRACE_EVENT_MAX_SIZE > dwSize1 + dwSize2 + TRACE_EVENT_HEADER_SIZE)
2542     {
2543         uint8_t traceBuf[256];
2544         uint8_t *pTraceBuf = traceBuf;
2545 
2546         // special handling for media runtime log, filter by component
2547         if (usId == EVENT_MEDIA_LOG && pArg1 != nullptr && dwSize1 >= 2*sizeof(int32_t))
2548         {
2549             int32_t comp = (*(int32_t*)pArg1) >> 24;
2550             int32_t level = *((int32_t*)pArg1 + 1);
2551 
2552             if (!m_mosTraceFilter(TR_KEY_MOSMSG_ALL) || !m_mosTraceFilter(MEDIA_EVENT_FILTER_KEYID(comp + 16)))
2553             {
2554                 // keyword not set for this component, skip it
2555                 return;
2556             }
2557         }
2558 
2559         if (dwSize1 + dwSize2 + TRACE_EVENT_HEADER_SIZE > sizeof(traceBuf))
2560         {
2561             pTraceBuf = (uint8_t *)MOS_AllocAndZeroMemory(TRACE_EVENT_MAX_SIZE);
2562         }
2563 
2564         if (pTraceBuf)
2565         {
2566             // trace header
2567             uint32_t *header = (uint32_t *)pTraceBuf;
2568             uint32_t    nLen = TRACE_EVENT_HEADER_SIZE;
2569 
2570             header[0] = 0x494D5445; // IMTE (IntelMediaTraceEvent) as ftrace raw marker tag
2571             header[1] = (usId << 16) | (dwSize1 + dwSize2);
2572             header[2] = ucType;
2573 
2574             if (pArg1 && dwSize1 > 0)
2575             {
2576                 MOS_SecureMemcpy(pTraceBuf+nLen, dwSize1, pArg1, dwSize1);
2577                 nLen += dwSize1;
2578             }
2579             if (pArg2 && dwSize2 > 0)
2580             {
2581                 MOS_SecureMemcpy(pTraceBuf+nLen, dwSize2, pArg2, dwSize2);
2582                 nLen += dwSize2;
2583             }
2584             size_t writeSize = write(MosUtilitiesSpecificNext::m_mosTraceFd, pTraceBuf, nLen);
2585             if (traceBuf != pTraceBuf)
2586             {
2587                 MOS_FreeMemory(pTraceBuf);
2588             }
2589         }
2590 #if Backtrace_FOUND
2591         if (m_mosTraceFilter(TR_KEY_CALL_STACK))
2592         {
2593             // reserve space for header and stack size field.
2594             // max 32-2=30 layers call stack in 64bit driver.
2595             uint32_t nLen = 4*sizeof(uint32_t);
2596             void **stack = (void **)(traceBuf + nLen);
2597             int num = backtrace(stack, ((sizeof(traceBuf)-nLen)/sizeof(void *)));
2598             if (num > 0)
2599             {
2600                 uint32_t *header = (uint32_t *)traceBuf;
2601 
2602                 header[0] = 0x494D5445; // IMTE (IntelMediaTraceEvent) as ftrace raw marker tag
2603                 header[1] = (EVENT_CALL_STACK << 16) | (num*sizeof(void *)+sizeof(uint32_t));
2604                 header[2] = 0;
2605                 header[3] = (uint32_t)num;
2606                 nLen += num*sizeof(void *);
2607                 size_t ret = write(MosUtilitiesSpecificNext::m_mosTraceFd, traceBuf, nLen);
2608             }
2609         }
2610 #endif
2611     }
2612     return;
2613 }
2614 
MosShouldTraceEventMsg(uint8_t level,uint8_t compID)2615 bool MosUtilities::MosShouldTraceEventMsg(
2616     uint8_t level,
2617     uint8_t compID)
2618 {
2619     return false;
2620 }
2621 
MosTraceEventMsg(uint8_t level,uint8_t compID,void * message,void * functionName,uint32_t lineNum)2622 void MosUtilities::MosTraceEventMsg(
2623     uint8_t          level,
2624     uint8_t          compID,
2625     void             *message,
2626     void             *functionName,
2627     uint32_t         lineNum)
2628 {
2629 }
2630 
MosTraceDataDump(const char * pcName,uint32_t flags,const void * pBuf,uint32_t dwSize)2631 void MosUtilities::MosTraceDataDump(
2632     const char *pcName,
2633     uint32_t    flags,
2634     const void *pBuf,
2635     uint32_t    dwSize)
2636 {
2637     if (MosUtilitiesSpecificNext::m_mosTraceFd >= 0 && pBuf && pcName)
2638     {
2639         uint8_t *pTraceBuf = (uint8_t *)MOS_AllocAndZeroMemory(TRACE_EVENT_MAX_SIZE);
2640         size_t writeSize = 0;
2641 
2642         if (pTraceBuf)
2643         {
2644             // trace header
2645             uint32_t *header = (uint32_t *)pTraceBuf;
2646             uint32_t    nLen = strlen(pcName) & 0xff;// 255 max pcName length
2647 
2648             header[0] = 0x494D5445; // IMTE (IntelMediaTraceEvent) as ftrace raw marker tag
2649             header[1] = (EVENT_DATA_DUMP << 16) | (8 + nLen + 1);
2650             header[2] = EVENT_TYPE_START;
2651             header[3] = dwSize;
2652             header[4] = flags;
2653             memcpy(&header[5], pcName, nLen);
2654             nLen += TRACE_EVENT_HEADER_SIZE + 8 + 1;
2655             writeSize = write(MosUtilitiesSpecificNext::m_mosTraceFd, pTraceBuf, nLen);
2656             // send dump data
2657             header[2] = EVENT_TYPE_INFO;
2658             const uint8_t *pData = static_cast<const uint8_t *>(pBuf);
2659             while (dwSize > 0)
2660             {
2661                 uint32_t size = dwSize;
2662                 if (size > TRACE_EVENT_MAX_DATA_SIZE)
2663                 {
2664                     size = TRACE_EVENT_MAX_DATA_SIZE;
2665                 }
2666                 uint16_t len = ((size + 3) & ~3) / sizeof(uint32_t);
2667                 uint8_t *pDst = (uint8_t *)&header[3];
2668 
2669                 header[1] = (EVENT_DATA_DUMP << 16) | (size + sizeof(len));
2670                 memcpy(pDst, &len, sizeof(len));
2671                 memcpy(pDst+sizeof(len), pData, size);
2672                 nLen = TRACE_EVENT_HEADER_SIZE + size + sizeof(len);
2673                 writeSize = write(MosUtilitiesSpecificNext::m_mosTraceFd, pTraceBuf, nLen);
2674                 dwSize -= size;
2675                 pData += size;
2676             }
2677             // send dump end
2678             header[1] = EVENT_DATA_DUMP << 16;
2679             header[2] = EVENT_TYPE_END;
2680             writeSize = write(MosUtilitiesSpecificNext::m_mosTraceFd, pTraceBuf, TRACE_EVENT_HEADER_SIZE);
2681 
2682             MOS_FreeMemory(pTraceBuf);
2683         }
2684     }
2685 }
2686 
MosTraceDataDictionary(const char * pcName,const void * pBuf,uint32_t dwSize)2687 void MosUtilities::MosTraceDataDictionary(
2688     const char* pcName,
2689     const void* pBuf,
2690     uint32_t    dwSize)
2691 {
2692     // not implemented
2693 }
2694 
MosGfxInfoInit()2695 MOS_STATUS MosUtilities::MosGfxInfoInit()
2696 {
2697     // not implemented
2698     return MOS_STATUS_SUCCESS;
2699 }
2700 
MosGfxInfoClose()2701 void MosUtilities::MosGfxInfoClose()
2702 {
2703     // not implemented
2704 }
2705 
MosGfxInfoRTErrInternal(uint8_t ver,uint16_t compId,uint16_t FtrId,uint32_t ErrorCode,uint8_t num_of_triples,va_list args)2706 void MosUtilities::MosGfxInfoRTErrInternal(uint8_t ver,
2707     uint16_t    compId,
2708     uint16_t    FtrId,
2709     uint32_t    ErrorCode,
2710     uint8_t     num_of_triples,
2711     va_list     args)
2712 {
2713     // not implemented
2714 }
2715 
MosGfxInfoRTErr(uint8_t ver,uint16_t compId,uint16_t FtrId,uint32_t ErrorCode,uint8_t num_of_triples,...)2716 void MosUtilities::MosGfxInfoRTErr(uint8_t ver,
2717     uint16_t    compId,
2718     uint16_t    FtrId,
2719     uint32_t    ErrorCode,
2720     uint8_t     num_of_triples,
2721     ...)
2722 {
2723     // not implemented
2724 }
2725 
MosGfxInfoInternal(uint8_t ver,uint16_t compId,uint32_t tmtryID,uint8_t num_of_triples,va_list args)2726 void MosUtilities::MosGfxInfoInternal(
2727     uint8_t  ver,
2728     uint16_t compId,
2729     uint32_t tmtryID,
2730     uint8_t  num_of_triples,
2731     va_list  args)
2732 {
2733     // not implemented
2734 }
2735 
MosIsProfilerDumpEnabled()2736 bool MosUtilities::MosIsProfilerDumpEnabled()
2737 {
2738     return true;
2739 }
2740 
MosGfxInfo(uint8_t ver,uint16_t compId,uint32_t tmtryID,uint8_t num_of_triples,...)2741 void MosUtilities::MosGfxInfo(
2742     uint8_t         ver,
2743     uint16_t        compId,
2744     uint32_t        tmtryID,
2745     uint8_t         num_of_triples,
2746     ...)
2747 {
2748     // not implemented
2749 }
2750 
2751 #if (_DEBUG || _RELEASE_INTERNAL)
MosMMPWriteFile(const std::string & name,const void * data,size_t size)2752 void MosUtilities::MosMMPWriteFile(
2753     const std::string &name,
2754     const void        *data,
2755     size_t             size)
2756 {
2757     std::ofstream ofs(name);
2758     ofs.write(static_cast<const char *>(data), size);
2759 }
2760 #endif  //(_DEBUG || _RELEASE_INTERNAL)
startTick(std::string tag)2761 void PerfUtility::startTick(std::string tag)
2762 {
2763     std::lock_guard<std::mutex> lock(perfMutex);
2764     Tick newTick = {};
2765     struct timespec ts = {};
2766 
2767     // get start tick count
2768     clock_gettime(CLOCK_REALTIME, &ts);
2769     newTick.start = int(ts.tv_sec * 1000000) + int(ts.tv_nsec / 1000); // us
2770 
2771     std::vector<Tick> *perf = nullptr;
2772     std::map<std::string, std::vector<Tick>*>::iterator it;
2773     it = records.find(tag);
2774     if (it == records.end())
2775     {
2776         perf = new std::vector<Tick>;
2777         perf->push_back(newTick);
2778         records[tag] = perf;
2779     }
2780     else
2781     {
2782         it->second->push_back(newTick);
2783     }
2784 }
2785 
stopTick(std::string tag)2786 void PerfUtility::stopTick(std::string tag)
2787 {
2788     std::lock_guard<std::mutex> lock(perfMutex);
2789     struct timespec ts = {};
2790     std::map<std::string, std::vector<Tick>*>::iterator it;
2791     it = records.find(tag);
2792     if (it == records.end())
2793     {
2794         // should not happen
2795         return;
2796     }
2797 
2798     // get stop tick count
2799     clock_gettime(CLOCK_REALTIME, &ts);
2800     it->second->back().stop = int(ts.tv_sec * 1000000) + int(ts.tv_nsec / 1000); // us
2801 
2802     // calculate time interval
2803     it->second->back().time = double(it->second->back().stop - it->second->back().start) / 1000.0; // ms
2804 }
2805 
2806 /*----------------------------------------------------------------------------
2807 | Name      : GMMDebugBreak
2808 | Purpose   : Fix compiling issue for Gmmlib on debug mode
2809 | Arguments : N/A
2810 | Returns   : void
2811 | Calls     : N/A
2812 | Callers   : Several
2813 \---------------------------------------------------------------------------*/
GMMDebugBreak(const char * file,const char * function,const int32_t line)2814 void GMMDebugBreak(const char  *file, const char  *function,const int32_t line)
2815 {
2816     // Not required for media driver
2817     return;
2818 }
2819 
2820 /*----------------------------------------------------------------------------
2821 | Name      : GMMPrintMessage
2822 | Purpose   : Fix compiling issue for Gmmlib on debug mode
2823 | Arguments : N/A
2824 | Returns   : void
2825 | Calls     : N/A
2826 | Callers   : Several
2827 \---------------------------------------------------------------------------*/
GMMPrintMessage(int32_t debuglevel,const char * function,...)2828 void GMMPrintMessage(int32_t debuglevel, const char  *function, ...)
2829 {
2830     // Not Required for media driver
2831     return;
2832 }
2833