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>;
64 int CmdBase::parser(char *p
)
70 string param
= get_next_param(m_cmd
, pos
);
72 if (param
.find(':') != string::npos
)
73 param
= get_next_param(m_cmd
, pos
);
75 while (pos
< m_cmd
.size())
77 param
= get_next_param(m_cmd
, pos
);
79 struct Param
*pp
= NULL
;
80 for (size_t i
= 0; i
< m_param
.size(); i
++)
82 string key
= string(m_param
[i
].key
);
83 if (compare_str(param
, key
, m_param
[i
].ignore_case
))
93 err
= "unknown Option";
95 set_last_err_string(err
);
99 if (pp
->type
== Param::e_uint32
)
101 param
= get_next_param(m_cmd
, pos
);
102 *(uint32_t*)pp
->pData
= str_to_uint(param
);
105 if (pp
->type
== Param::e_string_filename
)
107 param
= get_next_param(m_cmd
, pos
);
108 *(string
*)pp
->pData
= param
;
110 if (!check_file_exist(param
))
114 if (pp
->type
== Param::e_string
)
116 param
= get_next_param(m_cmd
, pos
);
117 *(string
*)pp
->pData
= param
;
120 if (pp
->type
== Param::e_bool
)
122 *(bool*)pp
->pData
= true;
125 if (pp
->type
== Param::e_null
)
135 nt
.type
= uuu_notify::NOTIFY_CMD_INFO
;
139 nt
.str
= (char*)str
.c_str();
145 int CmdList::run_all(CmdCtx
*p
, bool dry
)
147 CmdList::iterator it
;
151 nt
.type
= uuu_notify::NOTIFY_CMD_TOTAL
;
157 for (it
= begin(); it
!= end(); it
++, i
++)
161 nt
.type
= uuu_notify::NOTIFY_CMD_INDEX
;
165 nt
.type
= uuu_notify::NOTIFY_CMD_START
;
166 nt
.str
= (char *)(*it
)->m_cmd
.c_str();
174 nt
.type
= uuu_notify::NOTIFY_CMD_END
;
180 if ((*it
)->m_lastcmd
)
186 string
get_next_param(string
&cmd
, size_t &pos
, char sperate
)
189 if (pos
== string::npos
)
191 if (pos
>= cmd
.size())
195 while (cmd
[pos
] == sperate
&& pos
< cmd
.size())
199 size_t end
= string::npos
;
201 for (size_t s
= pos
; s
< cmd
.size(); s
++)
206 if (!quate
&& cmd
[s
] == sperate
)
216 str
= cmd
.substr(pos
, end
- pos
);
222 string
remove_square_brackets(string
&cmd
)
224 size_t sz
=cmd
.find('[');
225 return cmd
.substr(0, sz
);
228 int get_string_in_square_brackets(string
&cmd
, string
&context
)
230 size_t start
= cmd
.find('[');
231 if (start
== string::npos
)
237 size_t end
= cmd
.find(']', start
);
238 if (end
== string::npos
)
240 set_last_err_string("missed ]");
244 context
= cmd
.substr(start
+ 1, end
- start
- 1);
248 uint32_t str_to_uint(string
&str
)
252 if (str
.substr(0, 2).compare("0x") == 0)
253 return strtoul(str
.substr(2).c_str(), NULL
, 16);
255 return strtoul(str
.c_str(), NULL
, 10);
258 template <class T
> shared_ptr
<CmdBase
> new_cmd_obj(char *p
)
260 return shared_ptr
<CmdBase
>(new T(p
));
263 CmdObjCreateMap::CmdObjCreateMap()
265 (*this)["CFG:"] = new_cmd_obj
<CfgCmd
>;
267 (*this)["SDPS:BOOT"] = new_cmd_obj
<SDPSCmd
>;
269 (*this)["SDP:DCD"] = new_cmd_obj
<SDPDcdCmd
>;
270 (*this)["SDP:JUMP"] = new_cmd_obj
<SDPJumpCmd
>;
271 (*this)["SDP:RDMEM"] = new_cmd_obj
<SDPReadMemCmd
>;
272 (*this)["SDP:WRMEM"] = new_cmd_obj
<SDPWriteMemCmd
>;
273 (*this)["SDP:WRITE"] = new_cmd_obj
<SDPWriteCmd
>;
274 (*this)["SDP:STATUS"] = new_cmd_obj
<SDPStatusCmd
>;
275 (*this)["SDP:BOOT"] = new_cmd_obj
<SDPBootCmd
>;
276 (*this)["SDP:BLOG"] = new_cmd_obj
<SDPBootlogCmd
>;
278 (*this)["SDPU:JUMP"] = new_cmd_obj
<SDPJumpCmd
>;
279 (*this)["SDPU:WRITE"] = new_cmd_obj
<SDPWriteCmd
>;
280 (*this)["SDPU:BLOG"] = new_cmd_obj
<SDPBootlogCmd
>;
282 (*this)["SDPV:JUMP"] = new_cmd_obj
<SDPJumpCmd
>;
283 (*this)["SDPV:WRITE"] = new_cmd_obj
<SDPWriteCmd
>;
284 (*this)["SDPV:BLOG"] = new_cmd_obj
<SDPBootlogCmd
>;
286 (*this)["FB:GETVAR"] = new_cmd_obj
<FBGetVar
>;
287 (*this)["FASTBOOT:GETVAR"] = new_cmd_obj
<FBGetVar
>;
288 (*this)["FB:UCMD"] = new_cmd_obj
<FBUCmd
>;
289 (*this)["FASTBOOT:UCMD"] = new_cmd_obj
<FBUCmd
>;
290 (*this)["FB:ACMD"] = new_cmd_obj
<FBACmd
>;
291 (*this)["FASTBOOT:ACMD"] = new_cmd_obj
<FBACmd
>;
292 (*this)["FB:DOWNLOAD"] = new_cmd_obj
<FBDownload
>;
293 (*this)["FASTBOOT:DOWNLOAD"] = new_cmd_obj
<FBDownload
>;
294 (*this)["FB:FLASH"] = new_cmd_obj
<FBFlashCmd
>;
295 (*this)["FASTBOOT:FLASH"] = new_cmd_obj
<FBFlashCmd
>;
296 (*this)["FB:ERASE"] = new_cmd_obj
<FBEraseCmd
>;
297 (*this)["FASTBOOT:ERASE"] = new_cmd_obj
<FBEraseCmd
>;
298 (*this)["FB:OEM"] = new_cmd_obj
<FBOemCmd
>;
299 (*this)["FASTBOOT:OEM"] = new_cmd_obj
<FBOemCmd
>;
300 (*this)["FB:FLASHING"] = new_cmd_obj
<FBFlashingCmd
>;
301 (*this)["FASTBOOT:FLASHING"] = new_cmd_obj
<FBFlashingCmd
>;
302 (*this)["FB:SET_ACTIVE"] = new_cmd_obj
<FBSetActiveCmd
>;
303 (*this)["FASTBOOT:SET_ACTIVE"] = new_cmd_obj
<FBSetActiveCmd
>;
305 (*this)["FBK:UCMD"] = new_cmd_obj
<FBUCmd
>;
306 (*this)["FBK:ACMD"] = new_cmd_obj
<FBACmd
>;
307 (*this)["FBK:SYNC"] = new_cmd_obj
<FBSyncCmd
>;
308 (*this)["FBK:UCP"] = new_cmd_obj
<FBCopy
>;
310 (*this)["_ALL:DONE"] = new_cmd_obj
<CmdDone
>;
311 (*this)["_ALL:DELAY"] = new_cmd_obj
<CmdDelay
>;
312 (*this)["_ALL:SH"] = new_cmd_obj
<CmdShell
>;
313 (*this)["_ALL:SHELL"] = new_cmd_obj
<CmdShell
>;
314 (*this)["_ALL:<"] = new_cmd_obj
<CmdShell
>;
318 shared_ptr
<CmdBase
> create_cmd_obj(string cmd
)
322 param
= get_next_param(cmd
, pos
, ':');
323 param
= remove_square_brackets(param
);
325 param
= str_to_upper(param
);
327 if (g_cmd_create_map
.find(param
) == g_cmd_create_map
.end())
330 param
= get_next_param(cmd
, pos
);
331 s
+= str_to_upper(param
);
332 if (g_cmd_create_map
.find(s
) != g_cmd_create_map
.end())
333 return g_cmd_create_map
[s
]((char*)cmd
.c_str());
335 string commoncmd
= "_ALL:";
336 commoncmd
+= str_to_upper(param
);
337 if (g_cmd_create_map
.find(commoncmd
) != g_cmd_create_map
.end())
338 return g_cmd_create_map
[commoncmd
]((char*)cmd
.c_str());
342 return g_cmd_create_map
[param
]((char*)cmd
.c_str());
346 err
= "Unknown Command:";
348 set_last_err_string(err
);
352 int uuu_run_cmd(const char * cmd
, int dry
)
354 shared_ptr
<CmdBase
> p
;
355 p
= create_cmd_obj(cmd
);
362 nt
.type
= uuu_notify::NOTIFY_CMD_TOTAL
;
366 nt
.type
= uuu_notify::NOTIFY_CMD_START
;
367 nt
.str
= (char *)p
->m_cmd
.c_str();
370 if (typeid(*p
) != typeid(CfgCmd
))
375 string pro
= get_next_param(c
, pos
, ':');
376 pro
= remove_square_brackets(pro
);
389 ret
= ctx
.look_for_match_device(pro
.c_str());
399 return ret
= dry
? p
->dump() : p
->run(NULL
);
402 nt
.type
= uuu_notify::NOTIFY_CMD_END
;
409 int CmdDone::run(CmdCtx
*)
412 nt
.type
= uuu_notify::NOTIFY_DONE
;
417 int CmdDelay::parser(char * /*p*/)
420 string param
= get_next_param(m_cmd
, pos
);
422 if (param
.find(':') != string::npos
)
423 param
= get_next_param(m_cmd
, pos
);
425 if (str_to_upper(param
) != "DELAY")
427 string err
= "Unknown Commnd:";
429 set_last_err_string(err
);
433 string ms
= get_next_param(m_cmd
, pos
);
434 m_ms
= str_to_uint(ms
);
438 int CmdDelay::run(CmdCtx
*)
440 std::this_thread::sleep_for(std::chrono::milliseconds(m_ms
));
444 int CmdShell::parser(char * p
)
452 if (parser_protocal(p
, pos
))
455 m_protocal
= m_cmd
.substr(0, pos
);
457 s
= get_next_param(m_cmd
, pos
);
461 if (pos
!= string::npos
&& pos
< m_cmd
.size())
462 m_shellcmd
= m_cmd
.substr(pos
);
467 int CmdShell::run(CmdCtx
*)
471 #define _pclose pclose
473 FILE *pipe
= _popen(m_shellcmd
.c_str(), "r");
477 string err
= "failure popen: ";
478 err
+= m_shellcmd
.c_str();
479 set_last_err_string(err
);
485 while (fgets((char*)str
.c_str(), str
.size(), pipe
))
491 str
.resize(strlen(str
.c_str()));
495 size_t pos
= cmd
.find_first_of("\r\n");
496 if (pos
!= string::npos
)
497 cmd
= cmd
.substr(0, pos
);
499 return uuu_run_cmd(cmd
.c_str(), 0);
502 nt
.type
= uuu_notify::NOTIFY_CMD_INFO
;
503 nt
.str
= (char*)str
.c_str();
507 /* Close pipe and print return value of pPipe. */
510 int ret
= _pclose(pipe
);
512 str
.format("\nProcess returned %d\n", ret
);;
515 set_last_err_string(str
.c_str());
521 set_last_err_string("Error: Failed to read the pipe to the end.\n");
528 int run_cmds(const char *procotal
, CmdCtx
*p
)
530 CmdMap cmdmap
, *pCmdMap
;
532 if (!g_cmd_list_file
.empty())
534 shared_ptr
<FileBuffer
> pbuff
= get_file_buffer(g_cmd_list_file
);
537 if(parser_cmd_list_file(pbuff
, &cmdmap
))
543 pCmdMap
= &g_cmd_map
;
546 if (pCmdMap
->find(procotal
) == pCmdMap
->end())
551 return (*pCmdMap
)[procotal
]->run_all(p
);
554 static int insert_one_cmd(const char * cmd
, CmdMap
*pCmdMap
)
559 string pro
= get_next_param(s
, pos
, ':');
560 pro
= remove_square_brackets(pro
);
563 pro
= str_to_upper(pro
);
565 shared_ptr
<CmdBase
> p
= create_cmd_obj(s
);
572 if (pCmdMap
->find(pro
) == pCmdMap
->end())
574 shared_ptr
<CmdList
> list(new CmdList
);
575 (*pCmdMap
)[pro
] = list
;
578 (*pCmdMap
)[pro
]->push_back(p
);
584 static int added_default_boot_cmd(const char *filename
)
588 str
= "SDPS: boot -f ";
593 int ret
= insert_one_cmd(str
.c_str(), &g_cmd_map
);
596 insert_one_cmd("SDPS: done", &g_cmd_map
);
598 str
= "SDP: boot -f ";
603 ret
= insert_one_cmd(str
.c_str(), &g_cmd_map
);
606 insert_one_cmd("SDP: done", &g_cmd_map
);
608 str
= "SDPU: write -f ";
612 str
+= " -offset 0x57c00";
613 insert_one_cmd(str
.c_str(), &g_cmd_map
);
614 insert_one_cmd("SDPU: jump", &g_cmd_map
);
615 insert_one_cmd("SDPU: done", &g_cmd_map
);
617 str
= "SDPV: write -f ";
622 insert_one_cmd(str
.c_str(), &g_cmd_map
);
623 insert_one_cmd("SDPV: jump", &g_cmd_map
);
624 insert_one_cmd("SDPV: done", &g_cmd_map
);
629 int check_version(string str
)
633 for (size_t i
= 0; i
< str
.size(); i
++)
636 if (c
>= '0' && c
<= '9')
641 if (c
== '.' || i
== str
.size()-1 || c
== '\n')
649 int cur
= uuu_get_version();
654 str
= "Current uuu version is too low, please download latest one";
655 set_last_err_string(str
);
661 int uuu_run_cmd_script(const char * buff
, int dry
)
663 shared_ptr
<FileBuffer
> p(new FileBuffer
);
664 p
->m_data
.resize(strlen(buff
));
665 memcpy(p
->m_data
.data(), buff
, strlen(buff
));
666 return parser_cmd_list_file(p
);
669 int parser_cmd_list_file(shared_ptr
<FileBuffer
> pbuff
, CmdMap
*pCmdMap
)
671 char uuu_version
[] = "uuu_version";
675 pCmdMap
= &g_cmd_map
;
679 for (size_t i
= 0; i
< pbuff
->size(); i
++)
681 uint8_t c
= pbuff
->at(i
);
688 if (c
== '\n' || c
== 0 || i
== pbuff
->size() - 1)
690 if (str
.substr(0, strlen(uuu_version
)) == uuu_version
)
692 if (check_version(str
.substr(strlen(uuu_version
), 10)))
696 }else if (str
.size() > 1)
699 if (insert_one_cmd(str
.c_str(), pCmdMap
))
708 int uuu_auto_detect_file(const char *filename
)
711 fn
+= remove_quota(filename
);
712 fn
.replace('\\', '/');
720 shared_ptr
<FileBuffer
> buffer
= get_file_buffer(fn
);
725 size_t pos
= str_to_upper(fn
).find("ZIP");
726 if(pos
== string::npos
|| pos
!= fn
.size() - 3)
728 pos
= str_to_upper(fn
).find("SDCARD");
729 if (pos
== string::npos
|| pos
!= fn
.size() - 6)
730 buffer
= get_file_buffer(fn
); //we don't try open a zip file here
737 string str
= "uuu_version";
738 void *p1
= buffer
->data();
739 void *p2
= (void*)str
.data();
740 if (memcmp(p1
, p2
, str
.size()) == 0)
742 size_t pos
= fn
.rfind('/');
743 if (pos
!= string::npos
)
744 set_current_dir(fn
.substr(0, pos
+ 1));
746 g_cmd_list_file
= fn
.substr(pos
+1);
748 return parser_cmd_list_file(buffer
);
751 //flash.bin or uboot.bin
752 return added_default_boot_cmd(fn
.c_str());
755 int notify_done(uuu_notify nt
, void *p
)
757 if(nt
.type
== uuu_notify::NOTIFY_DONE
)
758 *(std::atomic
<int> *) p
= 1;
759 if (nt
.type
== uuu_notify::NOTIFY_CMD_END
&& nt
.status
)
760 *(std::atomic
<int> *) p
= 1;
764 int uuu_wait_uuu_finish(int deamon
, int dry
)
766 std::atomic
<int> exit
;
770 for(auto it
=g_cmd_map
.begin(); it
!= g_cmd_map
.end(); it
++)
772 for(auto cmd
= it
->second
->begin(); cmd
!= it
->second
->end(); cmd
++)
781 uuu_register_notify_callback(notify_done
, &exit
);