[IE][VPU]: Update call signature with the fw from R14 develop branch (#3241)
[platform/upstream/dldt.git] / inference-engine / thirdparty / movidius / mvnc / src / mvnc_data.c
1 /*
2 * Copyright 2017-2019 Intel Corporation.
3 * The source code, information and material ("Material") contained herein is
4 * owned by Intel Corporation or its suppliers or licensors, and title to such
5 * Material remains with Intel Corporation or its suppliers or licensors.
6 * The Material contains proprietary information of Intel or its suppliers and
7 * licensors. The Material is protected by worldwide copyright laws and treaty
8 * provisions.
9 * No part of the Material may be used, copied, reproduced, modified, published,
10 * uploaded, posted, transmitted, distributed or disclosed in any way without
11 * Intel's prior express written permission. No license under any patent,
12 * copyright or other intellectual property rights in the Material is granted to
13 * or conferred upon you, either expressly, by implication, inducement, estoppel
14 * or otherwise.
15 * Any license under such intellectual property rights must be express and
16 * approved by Intel in writing.
17 */
18
19 #include "mvnc_data.h"
20 #include "mvnc_tool.h"
21
22 #define MVLOG_UNIT_NAME ncTool
23 #include "XLinkLog.h"
24 #include "XLinkStringUtils.h"
25 #include "XLink.h"
26
27 #include <string.h>
28 #include <stdio.h>
29
30 XLinkProtocol_t convertProtocolToXlink(
31     const ncDeviceProtocol_t ncProtocol) {
32     switch (ncProtocol) {
33         case NC_ANY_PROTOCOL: return X_LINK_ANY_PROTOCOL;
34         case NC_USB:          return X_LINK_USB_VSC;
35         case NC_PCIE:         return X_LINK_PCIE;
36         default:              return X_LINK_ANY_PROTOCOL;
37     }
38 }
39
40 ncDeviceProtocol_t convertProtocolToNC(
41     const XLinkProtocol_t xLinkProtocol) {
42     switch (xLinkProtocol) {
43         case X_LINK_ANY_PROTOCOL:   return NC_ANY_PROTOCOL;
44         case X_LINK_USB_VSC:        return NC_USB;
45         case X_LINK_PCIE:           return NC_PCIE;
46         default:
47             mvLog(MVLOG_WARN, "This convertation not supported, set to ANY_PROTOCOL");
48             return NC_ANY_PROTOCOL;
49     }
50 }
51
52 XLinkPlatform_t convertPlatformToXlink(
53     const ncDevicePlatform_t ncProtocol) {
54     switch (ncProtocol) {
55         case NC_ANY_PLATFORM: return X_LINK_ANY_PLATFORM;
56         case NC_MYRIAD_2:     return X_LINK_MYRIAD_2;
57         case NC_MYRIAD_X:     return X_LINK_MYRIAD_X;
58         default:           return X_LINK_ANY_PLATFORM;
59     }
60 }
61
62 ncDevicePlatform_t convertPlatformToNC(
63     const XLinkPlatform_t xLinkProtocol) {
64     switch (xLinkProtocol) {
65         case X_LINK_ANY_PLATFORM:   return NC_ANY_PLATFORM;
66         case X_LINK_MYRIAD_2:       return NC_MYRIAD_2;
67         case X_LINK_MYRIAD_X:       return NC_MYRIAD_X;
68         default:
69             mvLog(MVLOG_WARN, "This convertation not supported, set to NC_ANY_PLATFORM");
70             return NC_ANY_PLATFORM;
71     }
72 }
73
74 int copyNcDeviceDescrToXLink(const struct ncDeviceDescr_t *in_ncDeviceDesc,
75                                     deviceDesc_t *out_deviceDesc) {
76     CHECK_HANDLE_CORRECT(in_ncDeviceDesc);
77     CHECK_HANDLE_CORRECT(out_deviceDesc);
78
79     out_deviceDesc->protocol = convertProtocolToXlink(in_ncDeviceDesc->protocol);
80     out_deviceDesc->platform = convertPlatformToXlink(in_ncDeviceDesc->platform);
81     mv_strncpy(out_deviceDesc->name, XLINK_MAX_NAME_SIZE, in_ncDeviceDesc->name, XLINK_MAX_NAME_SIZE - 1);
82
83     return NC_OK;
84 }
85
86 int copyXLinkDeviceDescrToNc(const deviceDesc_t *in_DeviceDesc,
87                                     struct ncDeviceDescr_t *out_ncDeviceDesc) {
88     CHECK_HANDLE_CORRECT(in_DeviceDesc);
89     CHECK_HANDLE_CORRECT(out_ncDeviceDesc);
90
91     out_ncDeviceDesc->protocol = convertProtocolToNC(in_DeviceDesc->protocol);
92     out_ncDeviceDesc->platform = convertPlatformToNC(in_DeviceDesc->platform);
93     mv_strncpy(out_ncDeviceDesc->name, XLINK_MAX_NAME_SIZE, in_DeviceDesc->name, XLINK_MAX_NAME_SIZE - 1);
94
95     return NC_OK;
96 }
97
98 static ncStatus_t readFirmware(const char* binaryPath, char** out_firmware, size_t* out_length) {
99     CHECK_HANDLE_CORRECT(binaryPath);
100     CHECK_HANDLE_CORRECT(out_firmware);
101     CHECK_HANDLE_CORRECT(out_length);
102
103     *out_firmware = NULL;
104     *out_length = 0;
105     FILE* firmwareFile = fopen(binaryPath, "rb");
106
107     if(firmwareFile == NULL) {
108         mvLog(MVLOG_ERROR, "Fail to open file by path %s", binaryPath);
109         return NC_ERROR;
110     }
111
112     fseek(firmwareFile, 0, SEEK_END);
113     long fileSize = ftell(firmwareFile);
114     if(fileSize <= 0) {
115         mvLog(MVLOG_ERROR, "Fail to get file size or firmware is empty. fileSize = %ld", fileSize);
116         fclose(firmwareFile);
117         return NC_ERROR;
118     }
119     rewind(firmwareFile);
120
121     char* firmware = malloc(fileSize * sizeof(char));
122     if(firmware == NULL) {
123         mvLog(MVLOG_ERROR, "Fail to allocate memory for firmware");
124         fclose(firmwareFile);
125         return NC_ERROR;
126     }
127
128     size_t readCount = fread(firmware, sizeof(char), fileSize, firmwareFile);
129     if(readCount != fileSize)
130     {
131         mvLog(MVLOG_ERROR, "Fail to read firmware by path %s. readCount = %zu", binaryPath, readCount);
132         fclose(firmwareFile);
133         free(firmware);
134         return NC_ERROR;
135     }
136
137     fclose(firmwareFile);
138
139     *out_firmware = firmware;
140     *out_length = (size_t )fileSize;
141
142     return NC_OK;
143 }
144
145 static ncStatus_t patchFirmware(char **firmware, size_t *length, size_t commandLocationId,
146                                 const char command[], const size_t commandSize, const char value) {
147     CHECK_HANDLE_CORRECT(firmware);
148     CHECK_HANDLE_CORRECT(length);
149     CHECK_HANDLE_CORRECT(command);
150
151     char* currFirmware = *firmware;
152     size_t currLength = *length;
153
154     size_t patchedFirmwareLen = currLength + commandSize + 1;
155     char* patchedFirmware = malloc(patchedFirmwareLen);
156     if(patchedFirmware == NULL) {
157         mvLog(MVLOG_ERROR, "Fail to allocate memory for patched firmware");
158         return NC_ERROR;
159     }
160
161     memcpy(patchedFirmware, currFirmware, commandLocationId);
162
163     memcpy(patchedFirmware + commandLocationId,
164            command, commandSize);
165     memcpy(patchedFirmware + commandLocationId + commandSize,
166            &value, 1);
167
168     size_t currentPos = commandLocationId + commandSize + 1;
169     size_t tailSize = currLength - commandLocationId;
170     memcpy(patchedFirmware + currentPos,
171            currFirmware + commandLocationId, tailSize);
172
173     free(currFirmware);
174     *firmware = patchedFirmware;
175     *length = patchedFirmwareLen;
176
177     return NC_OK;
178 }
179
180 // 0x98 the write command for 8bit
181 // {0x00, 0x00, 0x20, 0x80} == 0x80200000 the address of watchdog flag
182 // 0x01 flag value
183 const char g_setWdSwitchCommandMX[] = {0x98, 0x00, 0x00, 0x20, 0x80};
184 const char g_executeCommand = 0xa4;
185
186 static ncStatus_t patchSetWdSwitchCommand(char **firmware, size_t *length, const char wdEnable) {
187     CHECK_HANDLE_CORRECT(firmware);
188     CHECK_HANDLE_CORRECT(length);
189
190     char* currFirmware = *firmware;
191     size_t currLength = *length;
192     size_t executeCommandIdx = 0;
193     char executeCommandFound = 0;
194     size_t i = 0;
195
196     for (i = currLength - 1; i >= 0; i--) {
197         if(currFirmware[i] == g_executeCommand) {
198             executeCommandIdx = i;
199             executeCommandFound = 1;
200             break;
201         }
202     }
203
204     if(!executeCommandFound) {
205         mvLog(MVLOG_WARN, "Fail to find execute command");
206         return NC_ERROR;
207     }
208     return patchFirmware(firmware, length, executeCommandIdx,
209                          g_setWdSwitchCommandMX, sizeof(g_setWdSwitchCommandMX), wdEnable);
210 }
211
212 // 0x98 the write command for 8bit
213 // {0x00, 0x0c, 0x20, 0x70} == 0x70200c00 the address of memory type for ddrInit application
214 const char g_setMemTypeCommandMX[] = {0x98, 0x00, 0x0c, 0x20, 0x70};
215 const char g_callCommand[] = {0xba, 0x78, 0xe9, 0x00, 0x70};
216
217 static ncStatus_t patchSetMemTypeCommand(char **firmware, size_t *length, const char memType) {
218     CHECK_HANDLE_CORRECT(firmware);
219     CHECK_HANDLE_CORRECT(length);
220
221     char* currFirmware = *firmware;
222     size_t currLength = *length;
223     size_t callCommandIdx = 0;
224     char callCommandFound = 0;
225     size_t i = 0;
226     size_t callCommandLen = sizeof(g_callCommand);
227
228     for (i = 0; i < currLength; i++) {
229         size_t j = 0;
230         for (j = 0; j < callCommandLen; j++) {
231             if(currFirmware[i + j] != g_callCommand[j]) {
232                 break;
233             }
234         }
235
236         if(j == callCommandLen) {
237             callCommandIdx = i;
238             callCommandFound = 1;
239         }
240     }
241
242     if(!callCommandFound) {
243         mvLog(MVLOG_WARN, "Fail to find call command");
244         return NC_ERROR;
245     }
246     return patchFirmware(firmware, length, callCommandIdx,
247                          g_setMemTypeCommandMX, sizeof(g_setMemTypeCommandMX), memType);
248 }
249
250 ncStatus_t bootDevice(deviceDesc_t* deviceDescToBoot,
251                       const char* mv_cmd_file_path, const bootOptions_t bootOptions) {
252
253     CHECK_HANDLE_CORRECT(deviceDescToBoot);
254
255     char* firmware = NULL;
256     size_t length = 0;
257     ncStatus_t sc = readFirmware(mv_cmd_file_path, &firmware, &length);
258     if(sc) {
259         mvLog(MVLOG_ERROR, "Fail to read firmware by path %s. sc = %d", mv_cmd_file_path, sc);
260         return sc;
261     }
262
263     if(deviceDescToBoot->platform == X_LINK_MYRIAD_X) {
264         if(deviceDescToBoot->protocol != X_LINK_PCIE) {
265             sc = patchSetWdSwitchCommand(&firmware, &length, bootOptions.wdEnable);
266             if(sc) {
267                 mvLog(MVLOG_WARN, "Fail to patch \"Set wd switch value\" command for firmware sc = %d", sc);
268             }
269             
270             sc = patchSetMemTypeCommand(&firmware, &length, bootOptions.memType);
271             if(sc) {
272                 mvLog(MVLOG_WARN, "Fail to patch \"Set memory type\" command for firmware sc = %d", sc);
273             }
274         }       
275     }
276
277     XLinkError_t rc = XLinkBootFirmware(deviceDescToBoot, firmware, (unsigned long)length);
278     free(firmware);
279
280     if(rc) {
281         return NC_ERROR;
282     }
283
284     return NC_OK;
285 }