1 /* 2 * Copyright (C) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #include "translate.h" 16 #include "host_updater.h" 17 18 namespace Hdc { 19 namespace TranslateCommand { Usage()20 string Usage() 21 { 22 string ret = ""; 23 ret = "\n OpenHarmony device connector(HDC) ...\n\n" 24 "---------------------------------global commands:----------------------------------\n" 25 " -h/help [verbose] - Print hdc help, 'verbose' for more other cmds\n" 26 " -v/version - Print hdc version\n" 27 " -t connectkey - Use device with given connect key\n" 28 "\n" 29 "---------------------------------component commands:-------------------------------\n" 30 "session commands(on server):\n" 31 " list targets [-v] - List all devices status, -v for detail\n" 32 " start [-r] - Start server. If with '-r', will be restart server\n" 33 " kill [-r] - Kill server. If with '-r', will be restart server\n" 34 "\n" 35 "service commands(on daemon):\n" 36 " target mount - Set /system /vendor partition read-write\n" 37 " wait - Wait for the device to become available\n" 38 " target boot [-bootloader|-recovery] - Reboot the device or boot into bootloader\\recovery.\n" 39 " target boot [MODE] - Reboot the into MODE.\n" 40 " smode [-r] - Restart daemon with root permissions, '-r' to cancel root\n" 41 " permissions\n" 42 " tmode usb - Reboot the device, listening on USB\n" 43 " tmode port [port] - Reboot the device, listening on TCP port\n" 44 "\n" 45 "---------------------------------task commands:-------------------------------------\n" 46 "file commands:\n" 47 " file send [option] local remote - Send file to device\n" 48 " file recv [option] remote local - Recv file from device\n" 49 " option is -a|-s|-z\n" 50 " -a: hold target file timestamp\n" 51 " -sync: just update newer file\n" 52 " -z: compress transfer\n" 53 " -m: mode sync\n" 54 " -b: send/receive file to debug application directory\n" 55 "\n" 56 "forward commands:\n" 57 " fport localnode remotenode - Forward local traffic to remote device\n" 58 " rport remotenode localnode - Reserve remote traffic to local host\n" 59 " node config name format 'schema:content'\n" 60 " examples are below:\n" 61 " tcp:<port>\n" 62 " localfilesystem:<unix domain socket name>\n" 63 " localreserved:<unix domain socket name>\n" 64 " localabstract:<unix domain socket name>\n" 65 " dev:<device name>\n" 66 " jdwp:<pid> (remote only)\n" 67 " fport ls - Display forward/reverse tasks\n" 68 " fport rm taskstr - Remove forward/reverse task by taskstring\n" 69 "\n" 70 "app commands:\n" 71 " install [-r|-s] src - Send package(s) to device and install them\n" 72 " src examples: single or multiple packages and directories\n" 73 " (.hap .hsp)\n" 74 " -r: replace existing application\n" 75 " -s: install shared bundle for multi-apps\n" 76 " uninstall [-k] [-s] package - Remove application package from device\n" 77 " -k: keep the data and cache directories\n" 78 " -s: remove shared bundle\n" 79 "\n" 80 "debug commands:\n" 81 " hilog [-h] - Show device log, -h for detail\n" 82 " shell [-b bundlename] [COMMAND...] - Run shell command (interactive shell if no command given)\n" 83 " -b: run command in specified debug application bundle path\n" 84 " bundle parameter only support non-interactive shell\n" 85 " bugreport [FILE] - Return all information from the device, stored in file if " 86 "FILE is specified\n" 87 " jpid - List PIDs of processes hosting a JDWP transport\n" 88 " track-jpid [-a|-p] - Track PIDs of debug processes hosting a JDWP transport\n" 89 " -a: include debug and release processes\n" 90 " -p: don't display debug and release tags\n" 91 "\n" 92 "security commands:\n" 93 " keygen FILE - Generate public/private key; key stored in FILE and FILE.pub\n" 94 "\n"; 95 return ret; 96 } 97 Verbose()98 string Verbose() 99 { 100 string ret = "\n OpenHarmony device connector(HDC) ...\n\n" 101 "---------------------------------global commands:----------------------------------\n" 102 " -h/help [verbose] - Print hdc help, 'verbose' for more other cmds\n" 103 " -v/version - Print hdc version\n" 104 " -l[0-5] - Set runtime loglevel\n" 105 " -t connectkey - Use device with given connect key\n" 106 " checkserver - check client-server version\n" 107 " checkdevice - check server-daemon version(only uart)\n" 108 "\n" 109 "---------------------------------component commands:-------------------------------\n" 110 "session commands(on server):\n" 111 " discover - Discover devices listening on TCP via LAN broadcast\n" 112 " list targets [-v] - List all devices status, -v for detail\n" 113 " tconn key - Connect device via key, TCP use ip:port\n" 114 " example:192.168.0.100:10178/192.168.0.100\n" 115 " USB connect automatic, TCP need to connect manually\n" 116 #ifdef HDC_SUPPORT_UART 117 "\n" 118 " UART connect need connect manually.\n" 119 " Baud Rate can be specified with commas.\n" 120 " key format: <Port Name>[,Baud Rate]\n" 121 " example: tconn COM5,921600\n" 122 " Default Baud Rate is 921600.\n" 123 "\n" 124 #endif 125 " start [-r] - Start server. If with '-r', will be restart server\n" 126 " kill [-r] - Kill server. If with '-r', will be restart server\n" 127 " -s [ip:]port - Set hdc server listen config\n" 128 "\n" 129 "service commands(on daemon):\n" 130 " target mount - Set /system /vendor partition read-write\n" 131 " target boot [-bootloader|-recovery] - Reboot the device or boot into bootloader\\recovery.\n" 132 " target boot [MODE] - Reboot the into MODE.\n" 133 " smode [-r] - Restart daemon with root permissions, '-r' to cancel root\n" 134 " permissions\n" 135 " tmode usb - Reboot the device, listening on USB\n" 136 " tmode port [port] - Reboot the device, listening on TCP port\n" 137 "\n" 138 "---------------------------------task commands:-------------------------------------\n" 139 "file commands:\n" 140 " file send [option] local remote - Send file to device\n" 141 " file recv [option] remote local - Recv file from device\n" 142 " option is -a|-s|-z\n" 143 " -a: hold target file timestamp\n" 144 " -sync: just update newer file\n" 145 " -z: compress transfer\n" 146 " -m: mode sync\n" 147 " -b: send/receive file to debug application directory\n" 148 "\n" 149 "forward commands:\n" 150 " fport localnode remotenode - Forward local traffic to remote device\n" 151 " rport remotenode localnode - Reserve remote traffic to local host\n" 152 " node config name format 'schema:content'\n" 153 " examples are below:\n" 154 " tcp:<port>\n" 155 " localfilesystem:<unix domain socket name>\n" 156 " localreserved:<unix domain socket name>\n" 157 " localabstract:<unix domain socket name>\n" 158 " dev:<device name>\n" 159 " jdwp:<pid> (remote only)\n" 160 " fport ls - Display forward/reverse tasks\n" 161 " fport rm taskstr - Remove forward/reverse task by taskstring\n" 162 "\n" 163 "app commands:\n" 164 " install [-r|-s] src - Send package(s) to device and install them\n" 165 " src examples: single or multiple packages and directories\n" 166 " (.hap .hsp)\n" 167 " -r: replace existing application\n" 168 " -s: install shared bundle for multi-apps\n" 169 " uninstall [-k] [-s] package - Remove application package from device\n" 170 " -k: keep the data and cache directories\n" 171 " -s: remove shared bundle\n" 172 "\n" 173 "debug commands:\n" 174 " hilog [-h] - Show device log, -h for detail\n" 175 " shell [-b bundlename] [COMMAND...] - Run shell command (interactive shell if no command given)\n" 176 " -b: run command in specified debug application bundle path\n" 177 " bundle parameter only support non-interactive shell\n" 178 " bugreport [FILE] - Return all information from the device, stored in file if FILE " 179 "is specified\n" 180 " jpid - List PIDs of processes hosting a JDWP transport\n" 181 " sideload [PATH] - Sideload the given full OTA package\n" 182 "\n" 183 "security commands:\n" 184 " keygen FILE - Generate public/private key; key stored in FILE and FILE.pub\n" 185 "\n" 186 "---------------------------------flash commands:------------------------------------\n" 187 "flash commands:\n" 188 " update packagename - Update system by package\n" 189 " flash [-f] partition imagename - Flash partition by image\n" 190 " erase [-f] partition - Erase partition\n" 191 " format [-f] partition - Format partition\n" 192 "---------------------------------external commands:------------------------------------\n" 193 "extconn key - Connect external device via key, TCP use ip:port(remian)\n" 194 "-S [ip:]port - Set hdc external server listen config\n" 195 "\n"; 196 return ret; 197 } 198 TargetConnect(FormatCommand * outCmd)199 string TargetConnect(FormatCommand *outCmd) 200 { 201 string stringError; 202 if (Base::StringEndsWith(outCmd->parameters, " -remove")) { 203 outCmd->parameters = outCmd->parameters.substr(0, outCmd->parameters.size() - CMD_REMOTE_SIZE); 204 outCmd->cmdFlag = CMD_KERNEL_TARGET_DISCONNECT; 205 } else { 206 outCmd->cmdFlag = CMD_KERNEL_TARGET_CONNECT; 207 constexpr int maxKeyLength = 50; // 50: tcp max=21,USB max=8bytes, serial device name maybe long 208 if (outCmd->parameters.size() > maxKeyLength) { 209 stringError = "Error connect key's size"; 210 outCmd->bJumpDo = true; 211 } 212 } 213 size_t pos = outCmd->parameters.find(":"); 214 if (pos != std::string::npos) { 215 // tcp mode 216 string ip = outCmd->parameters.substr(0, pos); 217 string sport = outCmd->parameters.substr(pos + 1); 218 if (sport.empty()) { 219 stringError = "Port incorrect"; 220 outCmd->bJumpDo = true; 221 return stringError; 222 } 223 if (ip == "localhost") { 224 ip = "127.0.0.1"; 225 outCmd->parameters.replace(0, pos, ip); 226 } 227 int port = std::stoi(sport); 228 sockaddr_in addr; 229 if ((port <= 0 || port > MAX_IP_PORT) || uv_ip4_addr(ip.c_str(), port, &addr) < 0) { 230 stringError = "IP:Port incorrect"; 231 outCmd->bJumpDo = true; 232 } 233 } 234 return stringError; 235 } 236 ForwardPort(const char * input,FormatCommand * outCmd)237 string ForwardPort(const char *input, FormatCommand *outCmd) 238 { 239 string stringError; 240 const char *pExtra = input + 6; // CMDSTR_FORWARD_FPORT CMDSTR_FORWARD_RPORT + " " size 241 if (!strncmp(input, CMDSTR_FORWARD_FPORT.c_str(), CMDSTR_FORWARD_FPORT.size()) && !strcmp(pExtra, "ls")) { 242 outCmd->cmdFlag = CMD_FORWARD_LIST; 243 } else if (!strncmp(input, CMDSTR_FORWARD_FPORT.c_str(), CMDSTR_FORWARD_FPORT.size()) && 244 !strncmp(pExtra, "rm", 2)) { // 2: "rm" size 245 outCmd->cmdFlag = CMD_FORWARD_REMOVE; 246 if (strcmp(pExtra, "rm")) { 247 outCmd->parameters = input + FORWORD_PORT_RM_BUF_SIZE; 248 } 249 } else { 250 const char *p = input + FORWORD_PORT_OTHER_BUF_SIZE; 251 // clang-format off 252 if (strncmp(p, "tcp:", 4) && // 4: "tcp:" size 253 strncmp(p, "localabstract:", 14) && // 14: "localabstract:" size 254 strncmp(p, "localreserved:", 14) && // 14: "localreserved:" size 255 strncmp(p, "localfilesystem:", 16) && // 16: "localfilesystem:" size 256 strncmp(p, "dev:", 4) && // 4: "dev:" size 257 strncmp(p, "jdwp:", 5) && // 5: "jdwp:" size 258 strncmp(p, "ark:", 4)) { // 4: "ark:" size 259 stringError = "Incorrect forward command"; 260 outCmd->bJumpDo = true; 261 } 262 // clang-format on 263 outCmd->cmdFlag = CMD_FORWARD_INIT; 264 outCmd->parameters = input; 265 } 266 return stringError; 267 } 268 RunMode(const char * input,FormatCommand * outCmd)269 string RunMode(const char *input, FormatCommand *outCmd) 270 { 271 string stringError; 272 outCmd->cmdFlag = CMD_UNITY_RUNMODE; 273 outCmd->parameters = input + CMDSTR_TARGET_MODE.size() + 1; // with ' ' 274 int portLength = 4; 275 int portSpaceLength = 5; 276 if (!strncmp(outCmd->parameters.c_str(), "port", portLength) && 277 !strcmp(outCmd->parameters.c_str(), CMDSTR_TMODE_USB.c_str())) { 278 stringError = "Error tmode command"; 279 outCmd->bJumpDo = true; 280 } else if (!strncmp(outCmd->parameters.c_str(), "port ", portSpaceLength)) { 281 const char *tmp = input + strlen("tmode port "); 282 // command is tmode port close 283 if (strcmp(tmp, "close") == 0) { 284 return stringError; 285 } 286 int port = atoi(tmp); 287 if (port > MAX_IP_PORT || port <= 0) { 288 stringError = "Incorrect port range"; 289 outCmd->bJumpDo = true; 290 } 291 } 292 return stringError; 293 } 294 TargetReboot(const char * input,FormatCommand * outCmd)295 void TargetReboot(const char *input, FormatCommand *outCmd) 296 { 297 outCmd->cmdFlag = CMD_UNITY_REBOOT; 298 if (strcmp(input, CMDSTR_TARGET_REBOOT.c_str())) { 299 outCmd->parameters = input + CMDSTR_TARGET_REBOOT.size() + 1; // with ' ' 300 if (outCmd->parameters == "-bootloader" || outCmd->parameters == "-recovery" || 301 outCmd->parameters == "-flashd") { 302 outCmd->parameters.erase(outCmd->parameters.begin()); 303 } 304 } 305 } 306 307 // command input 308 // client side:Enter string data formatting conversion to module see internal processing command String2FormatCommand(const char * inputRaw,int sizeInputRaw,FormatCommand * outCmd)309 string String2FormatCommand(const char *inputRaw, int sizeInputRaw, FormatCommand *outCmd) 310 { 311 string stringError; 312 string input = string(inputRaw, sizeInputRaw); 313 if (!strncmp(input.c_str(), CMDSTR_SOFTWARE_HELP.c_str(), CMDSTR_SOFTWARE_HELP.size())) { 314 outCmd->cmdFlag = CMD_KERNEL_HELP; 315 outCmd->bJumpDo = true; 316 if (strstr(input.c_str(), " verbose")) { 317 stringError = Verbose(); 318 } else { 319 stringError = Usage(); 320 } 321 } else if (!strcmp(input.c_str(), CMDSTR_SOFTWARE_VERSION.c_str())) { 322 outCmd->cmdFlag = CMD_KERNEL_HELP; 323 stringError = Base::GetVersion(); 324 outCmd->bJumpDo = true; 325 } else if (!strcmp(input.c_str(), CMDSTR_TARGET_DISCOVER.c_str())) { 326 outCmd->cmdFlag = CMD_KERNEL_TARGET_DISCOVER; 327 } else if (!strncmp(input.c_str(), CMDSTR_LIST_TARGETS.c_str(), CMDSTR_LIST_TARGETS.size())) { 328 outCmd->cmdFlag = CMD_KERNEL_TARGET_LIST; 329 if (strstr(input.c_str(), " -v")) { 330 outCmd->parameters = "v"; 331 } 332 } else if (!strncmp(input.c_str(), CMDSTR_CHECK_SERVER.c_str(), CMDSTR_CHECK_SERVER.size())) { 333 outCmd->cmdFlag = CMD_CHECK_SERVER; 334 } else if (!strncmp(input.c_str(), CMDSTR_CHECK_DEVICE.c_str(), CMDSTR_CHECK_DEVICE.size())) { 335 outCmd->parameters = input.c_str() + CMDSTR_CHECK_DEVICE.size() + 1; // with ' ' 336 outCmd->cmdFlag = CMD_CHECK_DEVICE; 337 } else if (!strncmp(input.c_str(), CMDSTR_WAIT_FOR.c_str(), CMDSTR_WAIT_FOR.size())) { 338 outCmd->cmdFlag = CMD_WAIT_FOR; 339 } else if (!strcmp(input.c_str(), CMDSTR_CONNECT_ANY.c_str())) { 340 outCmd->cmdFlag = CMD_KERNEL_TARGET_ANY; 341 } else if (!strncmp(input.c_str(), CMDSTR_CONNECT_TARGET.c_str(), CMDSTR_CONNECT_TARGET.size())) { 342 outCmd->parameters = input.c_str() + CMDSTR_CONNECT_TARGET.size() + 1; // with ' ' 343 stringError = TargetConnect(outCmd); 344 } else if (!strncmp(input.c_str(), (CMDSTR_SHELL_EX).c_str(), (CMDSTR_SHELL_EX).size())) { 345 if (!HostShellOption::FormatParametersToTlv( 346 input, CMDSTR_SHELL_EX.size() - 1, outCmd->parameters, stringError)) { 347 outCmd->bJumpDo = true; 348 } 349 outCmd->cmdFlag = CMD_UNITY_EXECUTE_EX; 350 } else if (!strncmp(input.c_str(), (CMDSTR_SHELL + " ").c_str(), CMDSTR_SHELL.size() + 1)) { 351 outCmd->cmdFlag = CMD_UNITY_EXECUTE; 352 outCmd->parameters = input.c_str() + CMDSTR_SHELL.size() + 1; 353 } else if (!strcmp(input.c_str(), CMDSTR_SHELL.c_str())) { 354 outCmd->cmdFlag = CMD_SHELL_INIT; 355 } else if (!strncmp(input.c_str(), CMDSTR_FILE_SEND.c_str(), CMDSTR_FILE_SEND.size()) || 356 !strncmp(input.c_str(), CMDSTR_FILE_RECV.c_str(), CMDSTR_FILE_RECV.size())) { 357 outCmd->cmdFlag = CMD_FILE_INIT; 358 outCmd->parameters = input.c_str() + strlen("file "); 359 } else if (!strncmp(input.c_str(), string(CMDSTR_FORWARD_FPORT + " ").c_str(), CMDSTR_FORWARD_FPORT.size() + 1) 360 || !strncmp(input.c_str(), string(CMDSTR_FORWARD_RPORT + " ").c_str(), 361 CMDSTR_FORWARD_RPORT.size() + 1)) { 362 stringError = ForwardPort(input.c_str(), outCmd); 363 } else if (!strncmp(input.c_str(), CMDSTR_APP_INSTALL.c_str(), CMDSTR_APP_INSTALL.size())) { 364 outCmd->cmdFlag = CMD_APP_INIT; 365 outCmd->parameters = input; 366 } else if (!strncmp(input.c_str(), CMDSTR_APP_UNINSTALL.c_str(), CMDSTR_APP_UNINSTALL.size())) { 367 outCmd->cmdFlag = CMD_APP_UNINSTALL; 368 outCmd->parameters = input; 369 if (outCmd->parameters.size() > MAX_APP_PARAM_SIZE || outCmd->parameters.size() < MIN_APP_PARAM_SIZE) { 370 stringError = "Package's path incorrect"; 371 outCmd->bJumpDo = true; 372 } 373 } else if (!strcmp(input.c_str(), CMDSTR_TARGET_MOUNT.c_str())) { 374 outCmd->cmdFlag = CMD_UNITY_REMOUNT; 375 } else if (!strcmp(input.c_str(), CMDSTR_LIST_JDWP.c_str())) { 376 outCmd->cmdFlag = CMD_JDWP_LIST; 377 } else if (!strncmp(input.c_str(), CMDSTR_TRACK_JDWP.c_str(), CMDSTR_TRACK_JDWP.size())) { 378 outCmd->cmdFlag = CMD_JDWP_TRACK; 379 if (strstr(input.c_str(), " -p")) { 380 outCmd->parameters = "p"; 381 } else if (strstr(input.c_str(), " -a")) { 382 outCmd->parameters = "a"; 383 } 384 } else if (!strncmp(input.c_str(), CMDSTR_TARGET_REBOOT.c_str(), CMDSTR_TARGET_REBOOT.size())) { 385 TargetReboot(input.c_str(), outCmd); 386 } else if (!strncmp(input.c_str(), CMDSTR_TARGET_MODE.c_str(), CMDSTR_TARGET_MODE.size())) { 387 stringError = RunMode(input.c_str(), outCmd); 388 } else if (!strncmp(input.c_str(), CMDSTR_HILOG.c_str(), CMDSTR_HILOG.size())) { 389 outCmd->cmdFlag = CMD_UNITY_HILOG; 390 if (strstr(input.c_str(), " -h")) { 391 outCmd->parameters = "h"; 392 } 393 } else if (!strncmp(input.c_str(), CMDSTR_STARTUP_MODE.c_str(), CMDSTR_STARTUP_MODE.size())) { 394 outCmd->cmdFlag = CMD_UNITY_ROOTRUN; 395 if (strstr(input.c_str(), " -r")) { 396 outCmd->parameters = "r"; 397 } 398 } else if (!strncmp(input.c_str(), CMDSTR_APP_SIDELOAD.c_str(), CMDSTR_APP_SIDELOAD.size())) { 399 if (strlen(input.c_str()) == CMDSTR_APP_SIDELOAD.size()) { 400 stringError = "Incorrect command, please with local path"; 401 outCmd->bJumpDo = true; 402 } 403 outCmd->cmdFlag = CMD_APP_SIDELOAD; 404 outCmd->parameters = input; 405 } else if (!strncmp(input.c_str(), CMDSTR_BUGREPORT.c_str(), CMDSTR_BUGREPORT.size())) { 406 outCmd->cmdFlag = CMD_UNITY_BUGREPORT_INIT; 407 outCmd->parameters = input; 408 if (outCmd->parameters.size() == CMDSTR_BUGREPORT.size() + 1) { // 1 is sizeInputRaw = input.size() + 1 409 outCmd->parameters = CMDSTR_BUGREPORT + " "; 410 } 411 } 412 // Inner command, protocol uses only 413 else if (!strncmp(input.c_str(), CMDSTR_INNER_ENABLE_KEEPALIVE.c_str(), CMDSTR_INNER_ENABLE_KEEPALIVE.size())) { 414 outCmd->cmdFlag = CMD_KERNEL_ENABLE_KEEPALIVE; 415 } else if (HostUpdater::CheckMatchUpdate(input, *outCmd)) { 416 outCmd->parameters = input; 417 } else { 418 stringError = "Unknown command..."; 419 outCmd->bJumpDo = true; 420 } 421 #ifdef HDC_DEBUG 422 WRITE_LOG(LOG_DEBUG, "String2FormatCommand cmdFlag:%d", outCmd->cmdFlag); 423 #endif 424 // nl 425 if (stringError.size()) { 426 stringError += "\n"; 427 } 428 return stringError; 429 }; 430 } 431 } // namespace Hdc 432