4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or
12 * other materials provided with the distribution.
14 * Neither the name of the NXP Semiconductor nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
50 static CmdMap g_cmd_map
;
51 static CmdObjCreateMap g_cmd_create_map
;
52 static string g_cmd_list_file
;
54 int parser_cmd_list_file(shared_ptr
<FileBuffer
> pbuff
, CmdMap
*pCmdMap
= NULL
);
57 void * create_object() { return new T
; }
59 typedef void * (*FN
)();
61 FN g_fn
= create_object
<int>;
71 int CmdBase::parser(char *p
)
77 string param
= get_next_param(m_cmd
, pos
);
79 if (param
.find(':') != string::npos
)
80 param
= get_next_param(m_cmd
, pos
);
84 while (pos
< m_cmd
.size())
86 param
= get_next_param(m_cmd
, pos
);
88 struct Param
*pp
= NULL
;
92 if (index
> m_param
.size())
94 set_last_err_string("More parameter then expected");
97 pp
= &(m_param
[index
]);
102 for (size_t i
= 0; i
< m_param
.size(); i
++)
104 string key
= string(m_param
[i
].key
);
105 if (compare_str(param
, key
, m_param
[i
].ignore_case
))
116 err
= "unknown Option";
118 set_last_err_string(err
);
122 if (pp
->type
== Param::Type::e_uint32
)
125 param
= get_next_param(m_cmd
, pos
);
126 *(uint32_t*)pp
->pData
= str_to_uint32(param
);
129 if (pp
->type
== Param::Type::e_string_filename
)
132 param
= get_next_param(m_cmd
, pos
);
133 *(string
*)pp
->pData
= param
;
135 if (!check_file_exist(param
))
139 if (pp
->type
== Param::Type::e_string
)
142 param
= get_next_param(m_cmd
, pos
);
143 *(string
*)pp
->pData
= param
;
146 if (pp
->type
== Param::Type::e_bool
)
148 *(bool*)pp
->pData
= true;
151 if (pp
->type
== Param::Type::e_null
)
156 if (m_bCheckTotalParam
)
158 if (index
< m_param
.size())
162 str
+= m_param
[index
].Error
;
163 set_last_err_string(str
);
170 int CmdBase::parser_protocal(char *p
, size_t &pos
)
175 string prot
= get_next_param(m_cmd
, pos
, ':');
177 if (get_string_in_square_brackets(prot
, param
))
182 size_t param_pos
= 0;
183 string s
= get_next_param(param
, param_pos
);
188 timeout
= get_next_param(param
, param_pos
);
189 m_timeout
= str_to_uint32(timeout
);
194 err
= "Unknown option: ";
196 err
+= " for protocol: ";
197 err
+= remove_square_brackets(prot
);
198 set_last_err_string(err
);
208 nt
.type
= uuu_notify::NOTIFY_CMD_INFO
;
212 nt
.str
= (char*)str
.c_str();
218 int CmdList::run_all(CmdCtx
*p
, bool dry
)
220 CmdList::iterator it
;
224 nt
.type
= uuu_notify::NOTIFY_CMD_TOTAL
;
230 for (it
= begin(); it
!= end(); it
++, i
++)
234 nt
.type
= uuu_notify::NOTIFY_CMD_INDEX
;
238 nt
.type
= uuu_notify::NOTIFY_CMD_START
;
239 nt
.str
= (char *)(*it
)->m_cmd
.c_str();
247 nt
.type
= uuu_notify::NOTIFY_CMD_END
;
253 if ((*it
)->m_lastcmd
)
259 int CmdMap::run_all(const std::string
&protocol
, CmdCtx
*p
, bool dry_run
)
261 if (find(protocol
) == end())
265 err
.append("Unknown Protocal:");
266 err
.append(protocol
);
267 set_last_err_string(err
);
270 return at(protocol
)->run_all(p
, dry_run
);
273 string
get_next_param(const string
&cmd
, size_t &pos
, char sperate
)
276 if (pos
== string::npos
)
278 if (pos
>= cmd
.size())
282 while (cmd
[pos
] == sperate
&& pos
< cmd
.size())
286 size_t end
= string::npos
;
288 for (size_t s
= pos
; s
< cmd
.size(); s
++)
293 if (!quate
&& cmd
[s
] == sperate
)
303 str
= cmd
.substr(pos
, end
- pos
);
309 string
remove_square_brackets(const string
&cmd
)
311 size_t sz
=cmd
.find('[');
312 return cmd
.substr(0, sz
);
315 int get_string_in_square_brackets(const string
&cmd
, string
&context
)
317 size_t start
= cmd
.find('[');
318 if (start
== string::npos
)
324 size_t end
= cmd
.find(']', start
);
325 if (end
== string::npos
)
327 set_last_err_string("missed ]");
331 context
= cmd
.substr(start
+ 1, end
- start
- 1);
335 template<typename T
, uint64_t MAX_VAL
>
336 T
str_to_uint(const std::string
&str
, bool * conversion_succeeded
)
338 if (conversion_succeeded
) *conversion_succeeded
= false;
343 if (str
.substr(0, 2).compare("0x") == 0)
350 const auto tmp_val
= std::stoull(str
, nullptr, base
);
351 if (tmp_val
<= MAX_VAL
)
353 if (conversion_succeeded
) *conversion_succeeded
= true;
354 return static_cast<T
>(tmp_val
);
356 } catch (const std::invalid_argument
&) {
357 } catch (const std::out_of_range
&) {
360 set_last_err_string("Conversion of string to unsigned failed");
365 uint16_t str_to_uint16(const string
&str
, bool * conversion_suceeded
)
367 return str_to_uint
<uint16_t, UINT16_MAX
>(str
, conversion_suceeded
);
370 uint32_t str_to_uint32(const string
&str
, bool * conversion_suceeded
)
372 return str_to_uint
<uint32_t, UINT32_MAX
>(str
, conversion_suceeded
);
375 uint64_t str_to_uint64(const string
&str
, bool * conversion_suceeded
)
377 return str_to_uint
<uint64_t, UINT64_MAX
>(str
, conversion_suceeded
);
380 template <class T
> shared_ptr
<CmdBase
> new_cmd_obj(char *p
)
382 return shared_ptr
<CmdBase
>(new T(p
));
385 CmdObjCreateMap::CmdObjCreateMap()
387 (*this)["CFG:"] = new_cmd_obj
<CfgCmd
>;
389 (*this)["SDPS:BOOT"] = new_cmd_obj
<SDPSCmd
>;
391 (*this)["SDP:DCD"] = new_cmd_obj
<SDPDcdCmd
>;
392 (*this)["SDP:JUMP"] = new_cmd_obj
<SDPJumpCmd
>;
393 (*this)["SDP:RDMEM"] = new_cmd_obj
<SDPReadMemCmd
>;
394 (*this)["SDP:WRMEM"] = new_cmd_obj
<SDPWriteMemCmd
>;
395 (*this)["SDP:WRITE"] = new_cmd_obj
<SDPWriteCmd
>;
396 (*this)["SDP:STATUS"] = new_cmd_obj
<SDPStatusCmd
>;
397 (*this)["SDP:BOOT"] = new_cmd_obj
<SDPBootCmd
>;
398 (*this)["SDP:BLOG"] = new_cmd_obj
<SDPBootlogCmd
>;
400 (*this)["SDPU:JUMP"] = new_cmd_obj
<SDPJumpCmd
>;
401 (*this)["SDPU:WRITE"] = new_cmd_obj
<SDPWriteCmd
>;
402 (*this)["SDPU:BLOG"] = new_cmd_obj
<SDPBootlogCmd
>;
404 (*this)["SDPV:JUMP"] = new_cmd_obj
<SDPJumpCmd
>;
405 (*this)["SDPV:WRITE"] = new_cmd_obj
<SDPWriteCmd
>;
406 (*this)["SDPV:BLOG"] = new_cmd_obj
<SDPBootlogCmd
>;
408 (*this)["FB:GETVAR"] = new_cmd_obj
<FBGetVar
>;
409 (*this)["FASTBOOT:GETVAR"] = new_cmd_obj
<FBGetVar
>;
410 (*this)["FB:UCMD"] = new_cmd_obj
<FBUCmd
>;
411 (*this)["FASTBOOT:UCMD"] = new_cmd_obj
<FBUCmd
>;
412 (*this)["FB:ACMD"] = new_cmd_obj
<FBACmd
>;
413 (*this)["FASTBOOT:ACMD"] = new_cmd_obj
<FBACmd
>;
414 (*this)["FB:DOWNLOAD"] = new_cmd_obj
<FBDownload
>;
415 (*this)["FASTBOOT:DOWNLOAD"] = new_cmd_obj
<FBDownload
>;
416 (*this)["FB:FLASH"] = new_cmd_obj
<FBFlashCmd
>;
417 (*this)["FASTBOOT:FLASH"] = new_cmd_obj
<FBFlashCmd
>;
418 (*this)["FB:ERASE"] = new_cmd_obj
<FBEraseCmd
>;
419 (*this)["FASTBOOT:ERASE"] = new_cmd_obj
<FBEraseCmd
>;
420 (*this)["FB:OEM"] = new_cmd_obj
<FBOemCmd
>;
421 (*this)["FASTBOOT:OEM"] = new_cmd_obj
<FBOemCmd
>;
422 (*this)["FB:FLASHING"] = new_cmd_obj
<FBFlashingCmd
>;
423 (*this)["FASTBOOT:FLASHING"] = new_cmd_obj
<FBFlashingCmd
>;
424 (*this)["FB:SET_ACTIVE"] = new_cmd_obj
<FBSetActiveCmd
>;
425 (*this)["FASTBOOT:SET_ACTIVE"] = new_cmd_obj
<FBSetActiveCmd
>;
426 (*this)["FB:CONTINUE"] = new_cmd_obj
<FBContinueCmd
>;
427 (*this)["FASTBOOT:CONTINUE"] = new_cmd_obj
<FBContinueCmd
>;
429 (*this)["FB:UPDATE-SUPER"] = new_cmd_obj
<FBUpdateSuper
>;
430 (*this)["FASTBOOT:UPDATE-SUPER"] = new_cmd_obj
<FBUpdateSuper
>;
431 (*this)["FB:CREATE-LOGICAL-PARTITION"] = new_cmd_obj
<FBCreatePartition
>;
432 (*this)["FASTBOOT:CREATE-LOGICAL-PARTITION"] = new_cmd_obj
<FBCreatePartition
>;
433 (*this)["FB:DELETE-LOGICAL-PARTITION"] = new_cmd_obj
<FBDelPartition
>;
434 (*this)["FASTBOOT:DELETE-LOGICAL-PARTITION"] = new_cmd_obj
<FBDelPartition
>;
435 (*this)["FB:RESIZE-LOGICAL-PARTITION"] = new_cmd_obj
<FBResizePartition
>;
436 (*this)["FASTBOOT:RESIZE-LOGICAL-PARTITION"] = new_cmd_obj
<FBResizePartition
>;
438 (*this)["FBK:UCMD"] = new_cmd_obj
<FBUCmd
>;
439 (*this)["FBK:ACMD"] = new_cmd_obj
<FBACmd
>;
440 (*this)["FBK:SYNC"] = new_cmd_obj
<FBSyncCmd
>;
441 (*this)["FBK:UCP"] = new_cmd_obj
<FBCopy
>;
443 (*this)["_ALL:DONE"] = new_cmd_obj
<CmdDone
>;
444 (*this)["_ALL:DELAY"] = new_cmd_obj
<CmdDelay
>;
445 (*this)["_ALL:SH"] = new_cmd_obj
<CmdShell
>;
446 (*this)["_ALL:SHELL"] = new_cmd_obj
<CmdShell
>;
447 (*this)["_ALL:<"] = new_cmd_obj
<CmdShell
>;
451 shared_ptr
<CmdBase
> create_cmd_obj(string cmd
)
455 param
= get_next_param(cmd
, pos
, ':');
456 param
= remove_square_brackets(param
);
458 param
= str_to_upper(param
);
460 if (g_cmd_create_map
.find(param
) == g_cmd_create_map
.end())
463 param
= get_next_param(cmd
, pos
);
464 s
+= str_to_upper(param
);
465 if (g_cmd_create_map
.find(s
) != g_cmd_create_map
.end())
466 return g_cmd_create_map
[s
]((char*)cmd
.c_str());
468 string commoncmd
= "_ALL:";
469 commoncmd
+= str_to_upper(param
);
470 if (g_cmd_create_map
.find(commoncmd
) != g_cmd_create_map
.end())
471 return g_cmd_create_map
[commoncmd
]((char*)cmd
.c_str());
475 return g_cmd_create_map
[param
]((char*)cmd
.c_str());
479 err
= "Unknown Command:";
481 set_last_err_string(err
);
485 int uuu_run_cmd(const char * cmd
, int dry
)
487 shared_ptr
<CmdBase
> p
;
488 p
= create_cmd_obj(cmd
);
495 nt
.type
= uuu_notify::NOTIFY_CMD_TOTAL
;
499 nt
.type
= uuu_notify::NOTIFY_CMD_START
;
500 nt
.str
= (char *)p
->m_cmd
.c_str();
503 if (typeid(*p
) != typeid(CfgCmd
))
508 string pro
= get_next_param(c
, pos
, ':');
509 pro
= remove_square_brackets(pro
);
522 ret
= ctx
.look_for_match_device(pro
.c_str());
532 return ret
= dry
? p
->dump() : p
->run(NULL
);
535 nt
.type
= uuu_notify::NOTIFY_CMD_END
;
542 int CmdDone::run(CmdCtx
*)
545 nt
.type
= uuu_notify::NOTIFY_DONE
;
550 int CmdDelay::parser(char * /*p*/)
553 string param
= get_next_param(m_cmd
, pos
);
555 if (param
.find(':') != string::npos
)
556 param
= get_next_param(m_cmd
, pos
);
558 if (str_to_upper(param
) != "DELAY")
560 string err
= "Unknown Commnd:";
562 set_last_err_string(err
);
566 string ms
= get_next_param(m_cmd
, pos
);
567 m_ms
= str_to_uint32(ms
);
571 int CmdDelay::run(CmdCtx
*)
573 std::this_thread::sleep_for(std::chrono::milliseconds(m_ms
));
577 int CmdShell::parser(char * p
)
585 if (parser_protocal(p
, pos
))
588 m_protocal
= m_cmd
.substr(0, pos
);
590 s
= get_next_param(m_cmd
, pos
);
594 if (pos
!= string::npos
&& pos
< m_cmd
.size())
595 m_shellcmd
= m_cmd
.substr(pos
);
600 int CmdShell::run(CmdCtx
*)
604 #define _pclose pclose
606 FILE *pipe
= _popen(m_shellcmd
.c_str(), "r");
610 string err
= "failure popen: ";
611 err
+= m_shellcmd
.c_str();
612 set_last_err_string(err
);
618 while (fgets((char*)str
.c_str(), str
.size(), pipe
))
624 str
.resize(strlen(str
.c_str()));
628 size_t pos
= cmd
.find_first_of("\r\n");
629 if (pos
!= string::npos
)
630 cmd
= cmd
.substr(0, pos
);
632 return uuu_run_cmd(cmd
.c_str(), 0);
635 nt
.type
= uuu_notify::NOTIFY_CMD_INFO
;
636 nt
.str
= (char*)str
.c_str();
640 /* Close pipe and print return value of pPipe. */
643 int ret
= _pclose(pipe
);
645 str
.format("\nProcess returned %d\n", ret
);;
648 set_last_err_string(str
.c_str());
654 set_last_err_string("Error: Failed to read the pipe to the end.\n");
661 int run_cmds(const char *procotal
, CmdCtx
*p
)
663 CmdMap cmdmap
, *pCmdMap
;
665 if (!g_cmd_list_file
.empty())
667 shared_ptr
<FileBuffer
> pbuff
= get_file_buffer(g_cmd_list_file
);
670 if(parser_cmd_list_file(pbuff
, &cmdmap
))
676 pCmdMap
= &g_cmd_map
;
679 if (pCmdMap
->find(procotal
) == pCmdMap
->end())
684 return (*pCmdMap
)[procotal
]->run_all(p
);
687 static int insert_one_cmd(const char * cmd
, CmdMap
*pCmdMap
)
692 string pro
= get_next_param(s
, pos
, ':');
693 pro
= remove_square_brackets(pro
);
696 pro
= str_to_upper(pro
);
698 shared_ptr
<CmdBase
> p
= create_cmd_obj(s
);
705 if (pCmdMap
->find(pro
) == pCmdMap
->end())
707 shared_ptr
<CmdList
> list(new CmdList
);
708 (*pCmdMap
)[pro
] = list
;
711 (*pCmdMap
)[pro
]->push_back(p
);
717 static int added_default_boot_cmd(const char *filename
)
721 str
= "SDPS: boot -f ";
726 int ret
= insert_one_cmd(str
.c_str(), &g_cmd_map
);
729 insert_one_cmd("SDPS: done", &g_cmd_map
);
731 str
= "SDP: boot -f ";
736 ret
= insert_one_cmd(str
.c_str(), &g_cmd_map
);
739 insert_one_cmd("SDP: done", &g_cmd_map
);
741 str
= "SDPU: write -f ";
745 str
+= " -offset 0x57c00";
746 insert_one_cmd(str
.c_str(), &g_cmd_map
);
747 insert_one_cmd("SDPU: jump", &g_cmd_map
);
748 insert_one_cmd("SDPU: done", &g_cmd_map
);
750 str
= "SDPV: write -f ";
755 insert_one_cmd(str
.c_str(), &g_cmd_map
);
756 insert_one_cmd("SDPV: jump", &g_cmd_map
);
757 insert_one_cmd("SDPV: done", &g_cmd_map
);
762 int check_version(string str
)
766 for (size_t i
= 0; i
< str
.size(); i
++)
769 if (c
>= '0' && c
<= '9')
774 if (c
== '.' || i
== str
.size()-1 || c
== '\n')
782 int cur
= uuu_get_version();
787 str
= "Current uuu version is too low, please download latest one";
788 set_last_err_string(str
);
794 int uuu_run_cmd_script(const char * buff
, int dry
)
796 shared_ptr
<FileBuffer
> p(new FileBuffer((void*)buff
, strlen(buff
)));
798 return parser_cmd_list_file(p
);
801 int parser_cmd_list_file(shared_ptr
<FileBuffer
> pbuff
, CmdMap
*pCmdMap
)
803 char uuu_version
[] = "uuu_version";
807 pCmdMap
= &g_cmd_map
;
811 for (size_t i
= 0; i
< pbuff
->size(); i
++)
813 uint8_t c
= pbuff
->at(i
);
820 if (c
== '\n' || c
== 0 || i
== pbuff
->size() - 1)
822 if (str
.substr(0, strlen(uuu_version
)) == uuu_version
)
824 if (check_version(str
.substr(strlen(uuu_version
), 10)))
828 }else if (str
.size() > 1)
831 if (insert_one_cmd(str
.c_str(), pCmdMap
))
840 int uuu_auto_detect_file(const char *filename
)
843 fn
+= remove_quota(filename
);
844 fn
.replace('\\', '/');
852 shared_ptr
<FileBuffer
> buffer
= get_file_buffer(fn
);
857 size_t pos
= str_to_upper(fn
).find("ZIP");
858 if(pos
== string::npos
|| pos
!= fn
.size() - 3)
860 pos
= str_to_upper(fn
).find("SDCARD");
861 if (pos
== string::npos
|| pos
!= fn
.size() - 6)
862 buffer
= get_file_buffer(fn
); //we don't try open a zip file here
869 string str
= "uuu_version";
870 void *p1
= buffer
->data();
871 void *p2
= (void*)str
.data();
872 if (memcmp(p1
, p2
, str
.size()) == 0)
874 size_t pos
= fn
.rfind('/');
875 if (pos
!= string::npos
)
876 set_current_dir(fn
.substr(0, pos
+ 1));
878 g_cmd_list_file
= fn
.substr(pos
+1);
880 return parser_cmd_list_file(buffer
);
883 //flash.bin or uboot.bin
884 return added_default_boot_cmd(fn
.c_str());
887 int notify_done(uuu_notify nt
, void *p
)
889 if(nt
.type
== uuu_notify::NOTIFY_DONE
)
890 *(std::atomic
<int> *) p
= 1;
891 if (nt
.type
== uuu_notify::NOTIFY_CMD_END
&& nt
.status
)
892 *(std::atomic
<int> *) p
= 1;
896 int uuu_wait_uuu_finish(int deamon
, int dry
)
898 std::atomic
<int> exit
;
902 for(auto it
=g_cmd_map
.begin(); it
!= g_cmd_map
.end(); it
++)
904 for(auto cmd
= it
->second
->begin(); cmd
!= it
->second
->end(); cmd
++)
913 uuu_register_notify_callback(notify_done
, &exit
);
915 if(polling_usb(exit
))