1 /*
2 * Copyright (c) 2018-2021, 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 #include <dlfcn.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include "driver_loader.h"
28 #include "mos_util_debug.h"
29 #include "memory_leak_detector.h"
30 
31 using namespace std;
32 
33 #if MOS_MESSAGES_ENABLED
MOS_Message(MOS_MESSAGE_LEVEL level,const PCCHAR logtag,MOS_COMPONENT_ID compID,uint8_t subCompID,const PCCHAR functionName,int32_t lineNum,const PCCHAR message,...)34 extern "C" void MOS_Message(
35     MOS_MESSAGE_LEVEL level,
36     const PCCHAR      logtag,
37     MOS_COMPONENT_ID  compID,
38     uint8_t           subCompID,
39     const PCCHAR      functionName,
40     int32_t           lineNum,
41     const PCCHAR      message,
42     ...)
43 {
44 }
45 #endif
46 
47 void UltGetCmdBuf(PMOS_COMMAND_BUFFER pCmdBuffer);
48 
49 extern char               *g_driverPath;
50 extern vector<Platform_t> g_platform;
51 
52 const char *g_platformName[] = {
53     "SKL",
54     "BXT",
55     "BDW",
56 };
57 
DriverDllLoader()58 DriverDllLoader::DriverDllLoader()
59 {
60     if (g_driverPath)
61     {
62         m_driver_path = g_driverPath;
63     }
64     else
65     {
66         m_driver_path = "/opt/intel/mediasdk/lib64/iHD_drv_video.so";
67     }
68 
69     m_platformArray = {
70 #ifdef IGFX_GEN9_SKL_SUPPORTED
71         igfxSKLAKE,
72 #endif
73 #ifdef IGFX_GEN9_BXT_SUPPORTED
74         igfxBROXTON,
75 #endif
76 #ifdef IGFX_GEN8_BDW_SUPPORTED
77         igfxBROADWELL,
78 #endif
79     };
80 
81     if (g_platform.size() > 0)
82     {
83         m_platformArray = g_platform;
84     }
85 }
86 
DriverDllLoader(char * path)87 DriverDllLoader::DriverDllLoader(char *path)
88 {
89     DriverDllLoader();
90     m_driver_path = path;
91 }
92 
CloseDriver(bool detectMemLeak)93 VAStatus DriverDllLoader::CloseDriver(bool detectMemLeak)
94 {
95     VAStatus vaStatus = m_ctx.vtable->vaTerminate(&m_ctx);
96 
97     if (detectMemLeak)
98     {
99         MemoryLeakDetector::Detect(m_drvSyms.MOS_GetMemNinjaCounter(),
100                                 m_drvSyms.MOS_GetMemNinjaCounterGfx(),
101                                 m_currentPlatform);
102     }
103 
104     m_drvSyms = {};
105 
106     if(m_umdhandle)
107     {
108         dlclose(m_umdhandle);
109         m_umdhandle = nullptr;
110     }
111 
112     return vaStatus;
113 }
114 
InitDriver(Platform_t platform_id)115 VAStatus DriverDllLoader::InitDriver(Platform_t platform_id)
116 {
117     int drm_fd           = platform_id + 1 < 0 ? 1 : platform_id + 1;
118     m_drmstate.fd        = drm_fd;
119     m_drmstate.auth_type = 3;
120     m_ctx.vtable         = &m_vtable;
121     m_ctx.vtable_vpp     = &m_vtable_vpp;
122 #if VA_CHECK_VERSION(1,11,0)
123     m_ctx.vtable_prot    = &m_vtable_prot;
124 #endif
125     m_ctx.drm_state      = &m_drmstate;
126     m_currentPlatform    = platform_id;
127     m_ctx.vtable_tpi     = nullptr;
128 
129     if (LoadDriverSymbols() != VA_STATUS_SUCCESS)
130     {
131         return VA_STATUS_ERROR_UNKNOWN;
132     }
133     m_drvSyms.MOS_SetUltFlag(1);
134     *m_drvSyms.ppfnUltGetCmdBuf = UltGetCmdBuf;
135     return m_drvSyms.__vaDriverInit_(&m_ctx);
136 }
137 
LoadDriverSymbols()138 VAStatus DriverDllLoader::LoadDriverSymbols()
139 {
140     const int buf_len         = 256;
141     char init_func_s[buf_len] = {};
142 
143     m_umdhandle = dlopen(m_driver_path, RTLD_NOW | RTLD_GLOBAL);
144     if (!m_umdhandle)
145     {
146         printf("ERROR: dlopen of %s failed.\n", m_driver_path);
147         char* pErrorStr = dlerror();
148         if(nullptr != pErrorStr)
149         {
150             printf("ERROR: %s\n", pErrorStr);
151         }
152         return VA_STATUS_ERROR_UNKNOWN;
153     }
154 
155     for (int i = 0; i <= VA_MINOR_VERSION; i++)
156     {
157         sprintf_s(init_func_s, buf_len, "__vaDriverInit_%d_%d", VA_MAJOR_VERSION, i);
158         m_drvSyms.__vaDriverInit_ = (VADriverInit)dlsym(m_umdhandle, init_func_s);
159         if (m_drvSyms.__vaDriverInit_)
160         {
161             m_drvSyms.vaCmExtSendReqMsg         = (CmExtSendReqMsgFunc)dlsym(m_umdhandle, "vaCmExtSendReqMsg");
162             m_drvSyms.MOS_SetUltFlag            = (MOS_SetUltFlagFunc)dlsym(m_umdhandle, "MOS_SetUltFlag");
163             m_drvSyms.MOS_GetMemNinjaCounter    = (MOS_GetMemNinjaCounterFunc)dlsym(m_umdhandle, "MOS_GetMemNinjaCounter");
164             m_drvSyms.MOS_GetMemNinjaCounterGfx = (MOS_GetMemNinjaCounterFunc)dlsym(m_umdhandle, "MOS_GetMemNinjaCounterGfx");
165             m_drvSyms.ppfnUltGetCmdBuf          = (UltGetCmdBufFunc *)dlsym(m_umdhandle, "pfnUltGetCmdBuf");
166             break;
167         }
168     }
169 
170     if (!m_drvSyms.Initialized())
171     {
172         printf("ERROR: not all driver symbols are successfully loaded.\n");
173         return VA_STATUS_ERROR_UNKNOWN;
174     }
175 
176     return VA_STATUS_SUCCESS;
177 }
178