/** @file DHL_DBG_Shell.c @brief DHL mini debug shell implementation Copyright 2006~2010 Digital STREAM Technology, Inc. All Rights Reserved */ #include "DHL_OSAL.h" #include "DHL_DBG.h" #include "DHL_OSAL_Priv.h" // get line API #include "DHL_DBG_Priv.h" // symtab API #include "DHL_OSAL_Config.h" //#include #include /* ¸ðµç Çì´õ ÆÄÀÏÀ» Æ÷ÇÔÇÏÁö´Â ¾ÊÀ¸¸ç, compile timeÀ» ÁÙÀ̱â À§ÇØ °¢ ¸ðµâÀº ÇÊ¿äÇÑ ¸¸Å­ÀÇ Çì´õ¸¦ ¼±¾ðÇϵµ·Ï ÇÔ. */ /* DHL µð¹ö±× ¸ðµâ À̸§ Á¤ÀÇ ·ê Âü°í: DHL ¸ðµâµéÀº ¸ðµÎ * ·Î ½ÃÀÛ. API´Â ´ë¹®ÀÚ, Platform ¹× ±âŸ´Â ¼Ò¹®ÀÚ »ç¿ë. µðÆúÆ® ·¹º§Àº 0À¸·Î ¼³Á¤ÇÑ´Ù. (0: ¿¡·¯ ¸Þ½ÃÁö¸¸ Ãâ·Â) */ DHL_MODULE("*shl", 0); #if COMMENT ____Config____(){} #endif /* ÀÌ ¸ðµâ ³»ºÎ¿¡¼­ »ç¿ëµÇ´Â °¢Á¾ configuration Á¤ÀÇ. */ #define SUPPORT_DBG_SHELL 1 // image size¸¦ ÁÙÀ̱â À§ÇØ shell Äڵ带 ¿ÏÀüÈ÷ Á¦°ÅÇÏ°í ½Í´Ù¸é // ÀÌ flag °ªÀ» 0À¸·Î ¼³Á¤ÇÏ¸é µÈ´Ù. #if SUPPORT_DBG_SHELL // ÀÌ if Á¶°ÇÀº "±²ÀåÈ÷" ³ÐÀº Á¶°ÇÀ¸·Î, ÀÌ ÆÄÀÏ ¼Ò½º ÄÚµåÀÇ ´ëºÎºÐÀ» Æ÷ÇÔÇÑ´Ù. #define SHELL_DEBUG 1 #define MAX_SHELL_HISTORY 30 /* naming rule: SHELL_XXXXX values: 0 or 1 */ #define SHELL_USE_SHELL_TASK 0 // 1À̸é shell Àü¿ë task¸¦ »ç¿ëÇÑ´Ù. // // Á¦°øµÇ´Â platform¿¡¼­ shellÀÌ ÀÌ¹Ì Á¦°øµÇ´Â °æ¿ì // µÎ°³ÀÇ shell µ¿ÀÛÀÌ ºÒ°¡ÇÔÀ¸·Î // minishellÀº dispatch extensionÀ¸·Î µ¿ÀÛÇØ¾ß ÇÑ´Ù. // ±×·² °æ¿ì 0 À¸·Î Çϰí, command dispatch ¸¦ »ç¿ëÇÏ¿© µ¿ÀÛÇϵµ·Ï ÇÑ´Ù. #define SHELL_INTERNAL_ECHO 1 // 1À̸é shell ³»ºÎ¿¡¼­ local echo (ÀÔ·Â ¹ÞÀº ¹®ÀÚ¸¦ ´Ù½Ã È­¸é¿¡ Ãâ·Â) ÇÑ´Ù. // // stdio api¿Í ¼­·Î ¸ÂÃç¾ß ÇÑ´Ù. // °¡´ÉÇϸé stdio ¿¡¼­´Â echo¸¦ ÇÏÁö ¸»°í // ¿©±â shell¿¡¼­ local echo¸¦ ÇÏ´Â °Ô ±ÇÀåµÊ. #define SHELL_AUTHORIZED_ACCESS 0 // 1À̸é ÀÓÀÇÀÇ »ç¿ëÀÚ°¡ shell Á¢±ÙÀ» ÇÏÁö ¸øÇϵµ·Ï // passwd¸¦ ÅëÇÑ authorized »ç¿ëÀÚ¸¸À» Á¢±Ù Çã¿ëÇÑ´Ù. // // º¸¾ÈÀÌ ÇÊ¿äÇÑ °æ¿ì ¾ç»ê SW build ½Ã¿¡ »ç¿ë °¡´É. // ¹Ýµå½Ã ÇÊ¿äÇÏÁö´Â ¾ÊÀ½. #define SHELL_SUPPORT_BG_EXE 1 // 1À̸é shell ¸í·ÉÀ» ½ÇÇàÇÒ ¶§ background ½ÇÇà flag°¡ ÀÖ´Â °æ¿ì // º°µµÀÇ task¸¦ »ý¼ºÇÏ´Â °ÍÀ» Çã¿ëÇÑ´Ù. // // ¸Þ¸ð¸®°¡ ºÎÁ·ÇÏÁö ¾Ê°í, task »ý¼º¿¡ Á¦¾àÀÌ ¾ø´Â °æ¿ì »ç¿ë ±ÇÀå. #define SHELL_ALLOW_EXIT 1 // 1À̸é 'exit' ¸í·ÉÀ» ÀÔ·ÂÇÏ¿© shell exitÀ» Çã¿ëÇÑ´Ù. // // linux ó·³ multi processingÀÌ °¡´ÉÇÑ os¿¡¼­ À¯¿ë. // ±âŸ os¿¡¼­´Â Çã¿ëÇÏÁö ¾Êµµ·Ï ÇØ¾ß ÇÑ´Ù. #define SHELL_SUPPORT_EXT_KEY 1 // 1À̸é LG box/LG term ¿¡¼­ »ç¿ë °¡´ÉÇÑ È®Àå ۸¦ Áö¿øÇÑ´Ù. // // platform¿¡ ¸ÂÃç¼­ ¼³Á¤. #define SHELL_ECHO_TEST 1 // 1À̸é echo ¸í·É¿¡ ÀÇÇÑ echo test ÄÚµå Æ÷ÇÔÇÑ´Ù. // // È®ÀåŰ µîÀÇ Å×½ºÆ®¿¡ À¯¿ëÇÏ°Ô »ç¿ëµÈ´Ù. // serial emulatorµîÀÇ Å͹̳ΠŸÀÔÀÌ Æ¯¼öÇÑ °æ¿ì // echo test·Î ÀûÀýÇÑ key code¸¦ ã¾Æ³¾ ¼ö ÀÖ´Ù. #define SHELL_USE_OS_SYMBOL 0 // 1À̸é os symbol (build °úÁ¤¿¡¼­ linker°¡ ¸¸µé¾îÁÖ´Â symbol) À» »ç¿ëÇÑ´Ù. // // º¸Åë symtable on/off flag´Â makefile µî¿¡¼­ ¼³Á¤Çϱ⠶§¹®¿¡ // ¿©±â¼­´Â Ç×»ó 1·Î ÇÏ´Â °ÍÀÌ ±ÇÀåµÈ´Ù. #define SHELL_SUPPORT_INPUT_EMULATION 0 // ÀÓ½Ã.. // @todo .. #define SHELL_SUPPORT_HISTORY 1 // 1ÀÌ¸é °ú°Å ÀÔ·Â ¸í·ÉµéÀÇ ÀçȰ¿ë ±â´É Ãß°¡. #if COMMENT ____Types____(){} #endif /* ÀÌ ¸ðµâ ³»ºÎ¿¡¼­ »ç¿ëµÇ´Â structure ¹× enumerations. */ typedef UINT32 (*SHELL_CMD_HANDLER_TYPE)(int,...); #if SHELL_SUPPORT_BG_EXE #define DHL_SHELL_BG_TASK_PRIORITY TASK_PRI_DHL_SHELLX #define DHL_SHELL_BG_TASK_STACKSIZE 16384 #endif #define DHL_SHELL_TASK_PRIORITY TASK_PRI_DHL_SHELL #define DHL_SHELL_TASK_STACKSIZE 16384 #if SHELL_AUTHORIZED_ACCESS static BOOL s_buser_authorized; // ÀÏ´Ü 1·Î ÇØµÎÀÚ. // ³ªÁß¿¡ ¾ç»ê½Ã¿¡´Â µðÆúÆ®·Î 0ÀÌ µÇ°í // authorize µÈ »ç¿ëÀÚ¿¡°Ô¸¸ shell »ç¿ëÀÌ Çã°¡µÈ´Ù #endif // SHELL_AUTHORIZED_ACCESS #if SHELL_ALLOW_EXIT // shell exit ¿äû flag static BOOL s_request_exit; #endif // SHELL_ALLOW_EXIT static DHL_OS_TASK_ID s_shell_tid; // cafrii 070302, argument 8°³ Á¦ÇÑ »çÇ×À» ¾ø¾Ú. typedef struct { void *fn; // function pointer int n_arg; int args[1]; // »ç½ÇÀº 1°³°¡ ¾Æ´Ï¶ó ÇÊ¿äÇÑ ¸¸Å­ °¡º¯ÀûÀ¸·Î ÇÒ´çÇÑ´Ù. } DebugShellParam; #define SIZE_OF_DEBUG_SHELL_PARAM(n_arg) \ (sizeof(DebugShellParam) + sizeof(int)*(n_arg)) #define MAX_CALL_ARG 8 // for newcon3, <- 32 #define DHL_SHELL_MAX_CMDLINE 255 // cafrii 061226 new shell token management design // #define DHL_SHELL_MAX_TOKEN_LEN 80 #define DHL_SHELL_MAX_TOKEN (MAX_CALL_ARG + 4) //10 typedef enum { ShellToken_Unknown = 0, ShellToken_Digit, ShellToken_HexDigit, ShellToken_String, ShellToken_Symbol, } DebugShellTokenType; typedef struct { char text[DHL_SHELL_MAX_TOKEN_LEN+1]; // max 80 characters DebugShellTokenType type; union { UINT32 value; // if text is digit.. void *addr; // if text is symbol.. char *string; // if text is string.. } u; } DebugShellToken; //DebugShellToken *g_dbg_tokens; typedef struct { char cmdline[DHL_SHELL_MAX_CMDLINE]; DebugShellToken *tokens; BOOL bCmdMatched; } DebugShellContext; // À¯È¿ÇÑ call ÁÖ¼Ò ¿µ¿ªÀÎÁö üũÇÏ´Â macro. // #define DHL_VALID_ADDR(ad) 0 // ÀÓ½Ã.. dhl_dbg_is_text_symbol((UINT32)ad) // call °¡´ÉÇÑ text symbol ÀÎÁö üũ.. // dhl_dbg api °¡ Á¦°øµÇ´Ï ±×°ÍÀ» »ç¿ëÇÒ °Í.. // cafrii 061212 add // ZMon¿¡¼­ ÀԷµǴ ¸ðµç address´Â ´ÙÀ½°ú °°Àº formÀ» ÃëÇØ¾ß ÇÑ´Ù. // 0x12345678 ¶Ç´Â 0X12345678 // #define DHL_VALID_HEX_ADDR(s) ( \ ((s)[0] == '0') && ((s)[1] == 'x' || (s)[1] == 'X') && (strlen(s) == 8) ) #if COMMENT ____Variables____(){} #endif /* global·Î Àû¿ëµÇ´Â variable Á¤ÀÇ. °¢ function º°·Î Ư¼öÇÑ ¿ëµµÀÇ variableÀº °¢ functionX block ¿¡¼­ Á¤ÀÇ °¡´É. */ #if COMMENT ____History____(){} #endif static char *g_dhl_pShellHistory[MAX_SHELL_HISTORY]; static void shell_add_to_history(char *buf) { // history bufferÀÇ ¸Ç ¾ÕÀ¸·Î push µÈ´Ù. // ¸¸¾à ¿ÏÀüÈ÷ µ¿ÀÏÇÑ command°¡ history buf¿¡ ÀÌ¹Ì ÀÖÀ¸¸é ±× buf´Â »èÁ¦µÈ´Ù. int i, k; char *p = NULL; if (buf == NULL || buf[0] == 0) return; // µ¿ÀÏÇÑ ³»¿ë °Ë»ö.. for (i=0; i0; k--) g_dhl_pShellHistory[k] = g_dhl_pShellHistory[k-1]; g_dhl_pShellHistory[0] = p; return; } p = DHL_OS_Malloc(strlen(buf)+1); strcpy(p, buf); if (g_dhl_pShellHistory[MAX_SHELL_HISTORY-1]) DHL_OS_Free((void **)&g_dhl_pShellHistory[MAX_SHELL_HISTORY-1]); for (i=MAX_SHELL_HISTORY-1; i>0; i--) g_dhl_pShellHistory[i] = g_dhl_pShellHistory[i-1]; g_dhl_pShellHistory[0] = p; } static void shell_cmd_history(DebugShellToken *tokens, int nToken) { int i; DHL_UNUSED(tokens); DHL_UNUSED(nToken); for (i=MAX_SHELL_HISTORY-1; i>=0; i--) { if (g_dhl_pShellHistory[i] == 0) continue; DHL_OS_Printf(" (%2d) '%s'\n", i, g_dhl_pShellHistory[i]); } } #if COMMENT ____Symbol____(){} #endif /* symbolÀ» ºÐ¼®ÇÑ´Ù. ¸ÕÀú os symtabÀ» º¸°í, ±× ´ÙÀ½¿¡ DHL symtabÀ» ã´Â´Ù. */ #define SYM_TYPE_UNKNOWN 0 #define SYM_TYPE_TEXT 1 #define SYM_TYPE_DATA 2 static void *shell_lookup_symbol(char *str, int *pType) { UINT32 calladdr; int type; /* alias symbol¿¡ ¿ì¼± ¼øÀ§¸¦ µÎµµ·Ï ÇÑ´Ù. */ if (DHL_DBG_QuerySymbol(str, (void **)&calladdr, &type) == DHL_OK && type == DHL_SYM_FN) { if (pType) *pType = type; return (void *)calladdr; } #if SHELL_USE_OS_SYMBOL calladdr = dhl_dbg_find_sym_by_name(str); if (calladdr) { if (pType) { if (dhl_dbg_is_text_symbol(calladdr)) *pType = DHL_SYM_FN; else if (dhl_dbg_is_data_symbol(calladdr)) *pType = DHL_SYM_V4; else *pType = DHL_SYM_NONE; } return (void *)calladdr; } #endif // SHELL_USE_OS_SYMBOL return NULL; } #if COMMENT ____Parser____(){} #endif /* shell command line ÆÄ¼­ µðÀÚÀÎ. 1. string ÀÔ·ÂÀ» Áö¿øÇÑ´Ù. ex) print "this is test" -> arg[0] "print", arg[1] "this is test" 2. string ³»ÀÇ escape sequence¸¦ Áö¿øÇÑ´Ù. 3. comma in string is treated as it is.. return ¸Ç ¾Õ command ºÎºÐÀ» Æ÷ÇÔÇÏ¿©, ºÐ¸®µÈ Àüü token °¹¼ö¸¦ ¸®ÅÏ. */ static int shell_parse_line_to_tokens(char *buf, DebugShellToken *tokens, int maxtoken) { //int i, n; char *p = buf; BOOL inside_quote = FALSE; DebugShellToken *t = tokens; // ÅäÅ« ÀÎÅØ½º (¸î ¹ø ° ÅäÅ«ÀÎÁö?) int num_tokens = 0; // ÇöÀç ÅäÅ« ¾È¿¡¼­ÀÇ writer pointer index (ÇöÀç Æ®Å«ÀÇ ±æÀÌ) int len = 0; DHL_ASSERT(tokens!=NULL, "token should be non-null"); #define NEW_TOKEN() \ num_tokens=0; len=0; memset(t, 0, sizeof(*t)); #define NEXT_TOKEN() \ t->text[len] = 0; t++; num_tokens++; len=0; \ if (num_tokens>=DHL_SHELL_MAX_TOKEN) goto label_end; \ memset(t, 0, sizeof(*t)); #define END_TOKEN() \ t->text[len] = 0; t++; num_tokens++; len=0; #define INPUT_CH(c) \ if (lentext[len]=(c); len++;} NEW_TOKEN(); while (*p) { if (*p == '"') { if (inside_quote) // string ó¸® ÁßÀ̸é string Á¾·á. { INPUT_CH(*p); inside_quote = FALSE; NEXT_TOKEN(); } else { // »õ·Ó°Ô stringÀ» ½ÃÀÛÇÑ´Ù. // ¸¸¾à ±× ÀÌÀü tokenÀÌ Á¾·á°¡ ¾ÈµÈ °Å¶ó¸é // ¿©±â¼­ ¸ÕÀú Á¾·áÇÏ°í »õ token ÁøÇà. // ¿¹: test"code" -> arg1 'test' arg2 'code' if (len) { NEXT_TOKEN(); } inside_quote = TRUE; INPUT_CH(*p); } p++; continue; } if (inside_quote) { if (*p == '\\' && *(p+1) == '"') { // escape sequence ³»ÀÇ quote ±âÈ£´Â ±×´ë·Î Åë°ú½ÃŲ´Ù. INPUT_CH('\\'); INPUT_CH('"'); } else { INPUT_CH(*p); } } else { if (*p == ' ' || *p == '\r' || *p == '\n' || *p == ',') { if (len) { NEXT_TOKEN(); } } else if (*p == ';') { // cafrii 070124 add // it is comment from this.. break; } else { INPUT_CH(*p); } } p++; } label_end: if (len) { END_TOKEN(); } return num_tokens; } // // ´Ü¾î ÇØ¼®ÇÏ´Â ÇÔ¼ö. // // ÇöÀç ÀÎ½Ä °¡´ÉÇÑ ´Ü¾î´Â string, 10Áø¼ö, 16Áø¼ö, symbol ÀÌ´Ù. // // 10Áø¼ö, 16Áø¼öÀÇ °æ¿ì - ±âÈ£¸¦ Áö¿øÇϰí overflow check´Â ÇÏÁö ¾Ê´Â´Ù. // static void shell_translate_one_token(int idx, DebugShellToken *token) { char *text; int value; if (token == NULL) return; text = token->text; if (text[0] == 0) { token->type = ShellToken_Unknown; token->u.value = 0; return; } if (text[0] == '"') { // this token is probably string. token->type = ShellToken_String; token->u.string = &text[1]; // skip quote sign.. // trim last trailing quote sign if (token->u.string[strlen(token->u.string)-1] == '"') { token->u.string[strlen(token->u.string)-1] = 0; } else DHL_OS_Printf("!! token[%d] (%s) trailing quote sign not found\n", idx, text); return; } if (1) // check if digit.. { // ÇöÀç overflow üũ´Â ÇÏÁö ¾Ê´Â´Ù. // int i, len, negative = 0; value = 0; if (text[0] == '-') { negative = 1; text++; } if (text[0] == '0' && (text[1] == 'x' || text[1] == 'X')) { token->type = ShellToken_HexDigit; text += 2; } else token->type = ShellToken_Digit; len = strlen(text); for (i=0; itype == ShellToken_HexDigit) { if ( !((text[i] >= '0' && text[i] <= '9') || (text[i] >= 'A' && text[i] <= 'F') || (text[i] >= 'a' && text[i] <= 'f'))) { //DHL_OS_Printf("!! token[%d] '%s' not hex digit\n", idx, text); token->type = ShellToken_Unknown; break; } value = (value << 4UL) + ( (text[i] >= '0' && text[i] <= '9') ? (text[i] - '0') : (text[i] >= 'A' && text[i] <= 'F') ? (text[i] - 'A' + 10) : (text[i] >= 'a' && text[i] <= 'f') ? (text[i] - 'a' + 10) : 0); } else { if (!(text[i] >= '0' && text[i] <= '9')) { //DHL_OS_Printf("!! token[%d] '%s' not decimal digit\n", idx, text); token->type = ShellToken_Unknown; break; } value = value * 10 + (text[i] - '0'); } } if (token->type != ShellToken_Unknown) { token->u.value = negative ? -1*value : value; return; } } // symbol °¡´É¼º üũ.. // if (1) { void *addr = shell_lookup_symbol(token->text, 0); //printf("lookup symtab (%s) return %d\n", token->text, addr); if (addr == NULL) { DHL_OS_Printf("!! token[%d] '%s' not symbol\n", idx, text); // ÀÌ·± °æ°í¸¦ º¸±â ½ÈÀ¸¸é Ç×»ó stringÀº quote ¸¶Å·À» ÇÏ¸é µÈ´Ù. // ex: // Shell> symlkup dbg --> error message and symbol lookup. // Shell> symlkup "dbg" --> symbol lookup without error message } else { token->u.addr = addr; token->type = ShellToken_Symbol; return; } } // ¸¶Áö¸· ³²Àº °ÍÀº string »ÓÀÌ´Ù. token->u.string = token->text; token->type = ShellToken_String; return; } static void shell_translate_tokens(DebugShellToken *token, int nToken) { int i; // ¸Ç óÀ½ tokenÀº command ¶ó¼­ for (i=0; i 5) break; } else { repeat = 0; prev_key = key; } } DHL_OS_Printf("EchoTest end\n"); } #endif // SHELL_ECHO_TEST static void shell_cmd_set(DebugShellToken *tokens, int nToken) { char *string; UINT32 value; UINT32 ptr; int type; // sanity check. // if (strcmp(tokens[0].text, "set") != 0) return; #if SHELL_DEBUG dprint(1, "set command, %d tokens\n", nToken); #endif if (nToken-1 < 2) { DHL_OS_Printf("!! too few arguments\n"); return; } // ¸Ç óÀ½ tokenÀº "set" ÀÌ¶ó¼­ skip. [1], [2] ¸¸ º¯È¯... shell_translate_tokens(&tokens[1], 2); string = tokens[1].text; value = tokens[2].u.value; //bCmdMatched = TRUE; if (string[0] == 0) return; // ¸ÕÀú symbol tableÀ» µÚÁ®¼­ ±×°÷¿¡ µî·ÏÀÌ µÇ¾î ÀÖÀ¸¸é ±× Á¤º¸¸¦ »ç¿ëÇϵµ·Ï ÇÏÀÚ. // if (DHL_DBG_QuerySymbol(string, (void **)&ptr, &type) == DHL_OK) { // type º°·Î Àß °ü¸®ÇØ¾ß ÇÑ´Ù. ¾È±×·¯¸é access violation ³¯ ¼öµµ ÀÖÀ½.. // if (type == DHL_SYM_V1 && (ptr)) { // no alignment required for byte addressing *(UINT8 *)ptr = (UINT8) value; DHL_OS_Printf("set '%s' value = 0x%02x (%d, %uU)\n", string, (int)*(UINT8 *)ptr, (int)*(UINT8 *)ptr, (UINT32)*(UINT8 *)ptr); } else if (type == DHL_SYM_V2 && (ptr & 1) == 0) { *(UINT16 *)ptr = (UINT16) value; DHL_OS_Printf("set '%s' value = 0x%04x (%d, %uU)\n", string, (int)*(UINT16 *)ptr, (int)*(UINT16 *)ptr, (UINT32)*(UINT16 *)ptr); } else if (type == DHL_SYM_V4 && (ptr & 3) == 0) { *(UINT32 *)ptr = (UINT32) value; DHL_OS_Printf("set '%s' value = 0x%08x (%d, %uU)\n", string, *(int *)ptr, *(int *)ptr, *(UINT32 *)ptr); } else DHL_OS_Printf("!! alignment err: 0x%x, type %d\n", ptr, type); return; } DHL_OS_Printf("set: var symbol '%s' not found\n", string); } /* alias variable symbol */ static void shell_cmd_show(DebugShellToken *tokens, int nToken) { char *string; int value; UINT32 ptr; int type; if (nToken <= 1) string = NULL; // show all else { shell_translate_tokens(&tokens[1], 1); string = tokens[1].text; } if (string && string[0]) { if (DHL_DBG_QuerySymbol(string, (void **)&ptr, &type) == DHL_OK) { value = type==DHL_SYM_V1 ? *(INT8*)ptr : type==DHL_SYM_V2 ? *(INT16*)ptr : *(INT32*)ptr; DHL_OS_Printf("'%s' size %d, value = 0x%x (%d, %uU)\n", string, type, value, value, value); return; } DHL_OS_Printf("show: symbol '%s' not found\n\n", string); DHL_DBG_PrintSymbolTable(DHL_SYM_FN | DHL_SYM_V1 | DHL_SYM_V2 | DHL_SYM_V4, string); DHL_OS_Printf("\n"); return; } DHL_DBG_PrintSymbolTable(DHL_SYM_FN | DHL_SYM_V1 | DHL_SYM_V2 | DHL_SYM_V4, NULL); DHL_OS_Printf("\n"); } /* usage: assign my_symbol_name 0x123456 my_symbol_name À̶ó´Â symbolÀ» ÁÖ¼Ò 0x123456 À¸·Î µî·ÏÇÑ´Ù. 0x123456 ÁÖ¼Ò´Â valid ÇÑ ÁÖ¼ÒÀ̾î¾ß ÇÑ´Ù. param: max token: 3 fixed. */ static void shell_cmd_assign(DebugShellToken *tokens, int nToken) { if (nToken < 3) return; shell_translate_tokens(&tokens[1], 2); // »õ·Î¿î symbolÀ» µî·ÏÇÑ´Ù. // symbol ºÎºÐ üũ.. if (tokens[1].text == NULL || strlen(tokens[1].text) < 1) { DHL_OS_Printf("!! invalid symbol '%s'\n", tokens[1].text); return; } // address ºÎºÐ üũ.. if (!DHL_VALID_ADDR(tokens[2].u.value) || !DHL_VALID_HEX_ADDR(tokens[2].text)) { DHL_OS_Printf("!! addr 0x%x '%s' invalid\n", tokens[2].u.value, tokens[2].text); return; } DHL_OS_Printf("assign symbol '%s' to 0x%x\n", tokens[1].text, tokens[2].u.value); DHL_DBG_RegisterFunctionSymbol(tokens[1].text, (void *)tokens[2].u.value); } #if SHELL_AUTHORIZED_ACCESS static BOOL shell_check_authorized(char *passwd) { return s_buser_authorized; } static void shell_cmd_passwd(DebugShellToken *tokens, int nToken) { int n; char buf[32]; DHL_UNUSED(tokens); DHL_UNUSED(nToken); if (shell_check_authorized(NULL)) { DHL_OS_Printf("already authorized. no passwd required\n"); return; } n = dhl_os_get_line(buf, sizeof(buf), eDHL_OS_GLF_PASSWD); if (n > 0 && shell_check_authorized(buf)) { DHL_OS_Printf("ok\n"); } else { DHL_OS_Printf("not authorized user!!\n"); } } #endif /* SHELL_AUTHORIZED_ACCESS */ void shell_cmd_which(DebugShellToken *tokens, int nToken) { if (nToken < 2) { DHL_OS_Printf(" usage: which substring // search cmds\n"); DHL_OS_Printf(" usage: which * // all cmds\n"); } else dhl_dbg_print_symtab(tokens[1].text); } #if COMMENT ____Call____(){} #endif #if SHELL_SUPPORT_BG_EXE // // User°¡ Shell ¿¡¼­ ¸í·ÉÀ» ÀÔ·ÂÇϸé Shell task¿¡¼­ ¹Ù·Î ÇÔ¼ö¸¦ ½ÇÇàÇÏ´Â °ÍÀÌ ¾Æ´Ï°í // º°µµÀÇ executer task¸¦ ¸¸µé¾î¼­ ½ÇÇàÇϵµ·Ï ÇÑ´Ù. // // ±×·¯¸é ½Ã°£ÀÌ ¿À·¡ °É¸®´Â ¸í·É (ex: autoscan) À» ½ÇÇà½ÃŲ ÈÄ¿¡µµ // Prompt°¡ ´Ù½Ã ¶ß±â ¶§¹®¿¡ ´Ù½Ã ´Ù¸¥ ¸í·ÉÀ» ½ÇÇà ½Ãų ¼ö ÀÖ´Ù. // // static void shell_bgtask(DebugShellParam *param) { int i; SHELL_CMD_HANDLER_TYPE fn; int n_arg, arg[MAX_CALL_ARG]; UINT32 result; memset(arg, 0, sizeof(arg)); // copy all params to local variables.. fn = (SHELL_CMD_HANDLER_TYPE)(int)param->fn; n_arg = param->n_arg; for (i=0; in_arg; i++) arg[i] = param->args[i]; for (; i MAX_CALL_ARG) { DHL_OS_Printf("!! call arg number %d exceed limit %d..\n", n_arg, MAX_CALL_ARG); //n_arg = MAX_CALL_ARG; return; } // cafrii 070306 bugfix. move position memset(arg, 0, sizeof(arg)); for (i=0; ifn = fn; //param->n_arg = n_arg - 1; // ¸Ç ¸¶Áö¸· arg´Â '&' À̹ǷΠÁ¦¿Ü. param->n_arg = n_arg; // ÀÌ¹Ì ¾Õ¿¡¼­ Á¦¿Ü ÇßÀ¸¹Ç·Î ±×´ë·Î »ç¿ë. for (i=0; iargs[i] = arg[i]; sprintf(pTaskNameBuf, "Shl%02x", nShellExeCount++); tid = DHL_OS_CreateTask((DHL_OS_TASKFUNCTION) shell_bgtask, pTaskNameBuf, DHL_SHELL_BG_TASK_PRIORITY, DHL_SHELL_BG_TASK_STACKSIZE, (int)param); if (tid == 0) DHL_OS_Free((void **)¶m); return; } #endif // SHELL_SUPPORT_BG_EXE if (n_arg <= 8) result = (*(SHELL_CMD_HANDLER_TYPE)(int)fn)( arg[ 0], arg[ 1], arg[ 2], arg[ 3], arg[ 4], arg[ 5], arg[ 6], arg[ 7]); else result = (*(SHELL_CMD_HANDLER_TYPE)(int)fn)( arg[ 0], arg[ 1], arg[ 2], arg[ 3], arg[ 4], arg[ 5], arg[ 6], arg[ 7], arg[ 8], arg[ 9], arg[10], arg[11], arg[12], arg[13], arg[14], arg[15], arg[16], arg[17], arg[18], arg[19], arg[20], arg[21], arg[22], arg[23], arg[24], arg[25], arg[26], arg[27], arg[28], arg[29], arg[30], arg[31]); DHL_OS_Printf("call 0x%x result = 0x%x (%u)\n", (UINT32)fn, result, result); } /* symbolÀº ¾ø°í Á÷Á¢ symbol address¸¦ ÀÔ·ÂÇØ¼­ ½ÇÇàÇÏ´Â °æ¿ì¿¡ À¯¿ë.. usage: call symbol_name arg1, arg2, .. call 0x80203040 arg1, arg2, .. ÃÖ¼ÒÇÑ ÅäÅ« 2°³ ÇÊ¿ä. */ void shell_cmd_call(DebugShellToken *tokens, int nToken) { BOOL bShellSpawn = FALSE; if (nToken < 2) { DHL_OS_Printf("!! too few arguments for cmd '%s'\n", tokens[0].text); return; } // ¸Ç ¸¶Áö¸· word°¡ '&' À̸é background run flagÀÓ. if (nToken > 1 && tokens[nToken-1].text[0] == '&' && tokens[nToken-1].text[1] == 0) { // this is background spawn flag //DHL_OS_Printf("&& shell spawn specified\n"); bShellSpawn = TRUE; nToken--; } // ¸Ç óÀ½ tokenÀº "call" ÀÌ¶ó¼­ skip shell_translate_tokens(&tokens[1], nToken-1); if (tokens[1].type != ShellToken_HexDigit && tokens[1].type != ShellToken_Symbol) { DHL_OS_Printf("!! invalid call address 0x%x\n", tokens[1].u.value); return; } DHL_OS_Printf("call function of '0x%08x' %s\n", tokens[1].u.value, bShellSpawn ? "in separate task.." : ""); #if 0 // Á÷Á¢ ÀÔ·ÂÇÑ function addressÀ̹ǷΠÀ߸øµÈ °ªÀÌ ÀÔ·ÂµÈ °ÍÀÎÁö üũ¸¦ ÇØ º¼ Çʿ䰡 ÀÖ´Ù. // if (tokens[1].type == ShellToken_Symbol && dhl_dbg_in_text_range(tokens[1].u.value)) { // text ¿µ¿ª¿¡ ÇØ´çÇÏ´Â ÁÖ¼ÒÀÌ´Ù. Á¤È®È÷ ÇÔ¼ö start ÁÖ¼ÒÀÎÁö´Â ¾Ë¼ö ¾øÀ¸³ª, // static function °ú °°Àº °ÍµéÀ» ½ÇÇà½Ãų ¼ö ÀÖµµ·Ï symtab ¿¡ ¾ø´Â ÁÖ¼Òµµ Çã¿ëÇÑ´Ù. // shell_exec_cmd((void *)tokens[1].u.value, nToken-2, &tokens[2], bShellSpawn); } else if (tokens[1].type == ShellToken_HexDigit && dhl_dbg_in_text_range(tokens[1].u.value)) { // digitÀ¸·Î ÀԷ¹ÞÀº call address´Â ¹Ýµå½Ã 0x·Î ½ÃÀÛÇϵµ·Ï ÇÏÀÚ. // Áï hex digit¸¸ Çã¿ëÇÑ´Ù. shell_exec_cmd((void *)tokens[1].u.value, nToken-2, &tokens[2], bShellSpawn); } else { DHL_OS_Printf("!! err: call address/symbol '%s' invalid\n", tokens[1].text); } #else // 090909 cafrii bugfix // shared lib ÀÎ °æ¿ì symbol table¿¡µµ µî·ÏÀÌ ¾ÈµÉ ¼ö ÀÖ´Ù. // ¶ÇÇÑ address rangeµµ ±â´ëÇÏ´Â ¿µ¿ªÀÌ ¾Æ´Ò ¼ö ÀÖ´Ù. // Á÷Á¢ "call" ¸í·ÉÀ» »ç¿ëÇÏ´Â °æ¿ì¿¡´Â ¹«Á¶°Ç ½ÇÇàÇϵµ·Ï ÇÏÀÚ. shell_exec_cmd((void *)tokens[1].u.value, nToken-2, &tokens[2], bShellSpawn); #endif } BOOL shell_default(DebugShellToken *tokens, int nToken) { BOOL bCmdMatched = FALSE; BOOL bShellSpawn = FALSE; // DHL command table¿¡¼­ ã¾Æ¼­ ÇØ´ç functionÀ» ½ÇÇà½ÃŲ´Ù. // int type; void *addr; // ¸Ç ¸¶Áö¸· word°¡ '&' À̸é background run flagÀÓ. if (nToken > 1 && tokens[nToken-1].text[0] == '&' && tokens[nToken-1].text[1] == 0) { // this is background spawn flag //DHL_OS_Printf("&& shell spawn specified\n"); bShellSpawn = TRUE; nToken--; } if (DHL_DBG_QuerySymbol(tokens[0].text, (void **)&addr, &type) == DHL_OK && type == DHL_SYM_FN) { bCmdMatched = TRUE; DHL_OS_Printf("call function of '0x%08x' (aliased)\n", addr); // dhl_dbg_in_text_range() ÇÔ¼ö´Â ¼ýÀÚ ¹üÀ§¸¸ üũÇÏ´Â ÇÔ¼ö. // ¿©±â¼­´Â Á¤È®ÇÏ°Ô symbol °ú ÀÏÄ¡ÇÏ´ÂÁö ¿©ºÎ°¡ Áß¿äÇÔ. if (!dhl_dbg_is_text_symbol((UINT32)addr)) DHL_OS_Printf("!! err: call address invalid\n"); // µî·ÏµÈ symbol ÀÓ¿¡µµ ÀÌ·± ¹®Á¦°¡ »ý±â´Â °æ¿ì´Â ¾î¶² °æ¿ì?? else { // ¸Ç óÀ½ tokenÀº command ¶ó¼­ skip shell_translate_tokens(&tokens[1], nToken-1); shell_exec_cmd((void *)addr, nToken-1, &tokens[1], bShellSpawn); } goto end; } #if 1 // call ¾øÀ̵µ ½ÇÇàÀÌ °¡´ÉÇϵµ·Ï º¯°æ.. // Á¶±Ý À§ÇèÇÒ ¼öµµ ÀÖÀ¸³ª °³¹ß Áß¿¡´Â ÀÌ°Ô ÆíÇÔ.. addr = shell_lookup_symbol(tokens[0].text, &type); if (addr && type == DHL_SYM_FN) { bCmdMatched = TRUE; DHL_OS_Printf("build symbol found: '%s' = 0x%08x. executing..\n", tokens[0].text, (UINT32)addr); // ¸Ç óÀ½ tokenÀº command ¶ó¼­ skip shell_translate_tokens(&tokens[1], nToken-1); shell_exec_cmd((void *)addr, nToken-1, &tokens[1], bShellSpawn); goto end; } #endif if (addr) { DHL_OS_Printf("entry found: %s (type %d) = 0x%08x, but invalid\n", tokens[0].text, tokens[0].type, (UINT32)addr); } else DHL_OS_Printf("unknown command '%s'\n", tokens[0].text); end: return bCmdMatched; } #if COMMENT ____Dispatcher____(){} #endif static struct dispatch_tbl_t s_dispatch_table[] = { { "help", shell_cmd_help, "show this help", }, { "?", shell_cmd_help, "show this help", }, #if SHELL_ECHO_TEST { "echo", shell_cmd_echo, "key input echo test", }, #endif { "set", shell_cmd_set, "change alias variable with new value", }, { "show", shell_cmd_show, "show alias symbol (var. with value. or func.)", }, { "assign", shell_cmd_assign, "assign new alias symbol", }, #if SHELL_AUTHORIZED_ACCESS { "passwd", shell_cmd_passwd, "authorize shell use", }, #endif { "which", shell_cmd_which, "search build symbols", }, { "h", shell_cmd_history, "show command history", }, { "call", shell_cmd_call, "call function with symbol", }, { NULL, NULL, }, }; static struct dispatch_tbl_t *shell_get_dispatch_table(void) { return s_dispatch_table; } static BOOL shell_process_cmdline(char *buf) { int i, nToken; BOOL bCmdMatched; DebugShellToken tokens[DHL_SHELL_MAX_TOKEN]; struct dispatch_tbl_t *dpt = s_dispatch_table; //int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; // °¢ token º°·Î ºÐ¼®.. tokens ¿¡´Ù ÀúÀå // nToken = shell_parse_line_to_tokens(buf, tokens, DHL_SHELL_MAX_TOKEN); if (nToken <= 0) return FALSE; #if SHELL_DEBUG dprint(2, "== %d tokens\n", nToken); for (i=0; i UINT32 int idx_history = -1; int i; label_start: idx_history = -1; pos = 0; memset(buf, 0, size); shell_print("Shell> "); #if SHELL_SUPPORT_INPUT_EMULATION if (g_shell_vibuf[0]) { UINT32 flag = DHL_OS_DisableInterrupts(); strncpy(buf, g_shell_vibuf, size-1); buf[size-1] = 0; g_shell_vibuf[0] = 0; DHL_OS_RestoreInterrupts(flag); // cafrii 090119, move printf to outside of Lock/Unlock task region. shell_print(g_shell_vibuf); shell_print("\n"); goto input_end; } #endif while (1) { // ZMon ÀÌ enable µÇ¾î ÀÖÁö ¾ÊÀ» ¶§¿¡, ZTCP°¡ ¾øÀ» ¶§ µîµîÀÇ °æ¿ì¿¡ ´ëÇØ // UART¿¡¼­ µ¥ÀÌÅ͸¦ ÀÔ·Â ¹Þ´Â ¹æ¹ýÀÌ °¢±â ´Ù¸¦ ¼ö ÀÖÀ½.. key = DHL_OS_GetChar(); // DbgGetChar´Â Ű ÀԷ¿¡ ½ÇÆÐÇϸé 0xFFFF ¸®ÅÏÇÑ´Ù. if (key == (UINT32)0) continue; if (key == DHL_EXTKEY_CR) { #if SHELL_INTERNAL_ECHO shell_print("\n"); #endif break; } else if (key == DHL_EXTKEY_ESC) { // ESC key shell_print("\n"); goto label_start; } #if SHELL_SUPPORT_EXT_KEY else if (key == DHL_EXTKEY_UP || key == DHL_EXTKEY_DN) { char **his = g_dhl_pShellHistory; if (0); else if (key == DHL_EXTKEY_UP) { if (idx_history+1 >= MAX_SHELL_HISTORY || his[idx_history+1] == NULL || his[idx_history+1][0] == 0) { continue; // ignore this key input. } idx_history++; } else if (key == DHL_EXTKEY_DN) { if (idx_history-1 < 0 || his[idx_history-1] == NULL || his[idx_history-1][0] == 0) continue; // ignore this key input. idx_history--; } for (i=0; i 0) { #if SHELL_INTERNAL_ECHO shell_print("\b"); #endif pos--; } } else if (key == DHL_EXTKEY_RG) { if (pos < strlen(buf)) { #if SHELL_INTERNAL_ECHO shell_putc(buf[pos]); #endif pos++; } } else if (key == DHL_EXTKEY_HOME) { if (pos > 0) { #if SHELL_INTERNAL_ECHO for (i=0; i 0) { // go back ÇÒ ±ÛÀÚ°¡ ÀÖ´Â °æ¿ì¿¡¸¸.. memmove(&buf[pos-1], &buf[pos], strlen(&buf[pos])+1); pos--; #if SHELL_INTERNAL_ECHO shell_putc('\b'); shell_print(&buf[pos]); shell_putc(' '); for (i=0; i= 0x20 && key < 0x7F) { if (strlen(buf) < size-1) { memmove(&buf[pos+1], &buf[pos], strlen(&buf[pos])+1); buf[pos++] = key; #if SHELL_INTERNAL_ECHO shell_putc(key); // at [pos-1] shell_print(&buf[pos]); for (i=0; i= buf && (*p == ' ' || *p == '\t')) { *p-- = 0; //n_trim++; } // skip head spaces p = buf; while (*p == ' ' || *p == '\t') p++; if (p != buf) memmove(buf, p, strlen(p)+1); } #if COMMENT ____Group2____(){} #endif static void shell_task_main(UINT32 arg) { DebugShellContext context; char buf[256]; BOOL bExecuted, bExit=FALSE; DHL_UNUSED(arg); DHL_OS_Printf("Mini Shell Task Spawned..\n"); #if SHELL_ALLOW_EXIT s_request_exit = 0; #endif #if 0 if (g_dbg_tokens == NULL) { // ÀÌ ¸Þ¸ð¸®´Â ¸Ç óÀ½ Çѹø¸¸ »ý¼ºµÈ´Ù. g_dbg_tokens = DHL_OS_Malloc(DHL_SHELL_MAX_TOKEN * sizeof(DebugShellToken)); } #endif memset(&context, 0, sizeof(context)); while (!bExit) { //DHL_OS_Delay(1); memset(buf, 0, sizeof(buf)); shell_input_command(context.cmdline, sizeof(context.cmdline)); if (context.cmdline[0] == 0) // just blank.. continue; #if SHELL_DEBUG dprint(2, "cmd input [%s]\n", context.cmdline); #endif bExecuted = shell_process_cmdline(context.cmdline); /* ¹æ±Ý Àü ÀÔ·ÂÇÑ ¸í·ÉÀ» history¿¡ Ãß°¡.. */ if (!(buf[0] == 'h' && buf[1] == 0)) shell_add_to_history(context.cmdline); if (bExecuted == FALSE) { //DHL_OS_Printf("\nInvalid command\n"); } DHL_OS_Printf("\n"); #if SHELL_ALLOW_EXIT if (s_request_exit) bExit = TRUE; #endif } DHL_OS_Printf("shell exit\n"); #if SHELL_ALLOW_EXIT s_shell_tid = 0; #endif } #if COMMENT ____Debug____(){} #endif #if COMMENT ____Symbol____(){} #endif #if DHL_REGISTER_DEUBG_SYMBOLS static DHL_SymbolTable _symbols[] = { /* however, if you want typing short-cut, it is good usage. DHL_FNC_SYM_ENTRY2("epg_start", App_EpgUpdateStart), DHL_FNC_SYM_ENTRY2("epg_stop", App_EpgUpdateCancel), DHL_FNC_SYM_ENTRY2("epg_list", Dmc_EpgPrintAllTables), DHL_FNC_SYM_ENTRY2("epg_delete", App_EpgDeleteAll), DHL_VAR_SYM_ENTRY(g_XX_TestMode), */ 0, }; #endif /* DHL_REGISTER_DEUBG_SYMBOLS */ // shell ±â´ÉÀÇ ´ëºÎºÐÀ» disable ½ÃŰ·Á¸é ¾Æ·¡ Ç÷¡±×¸¦ 1·Î ¼³Á¤Ç϶ó. #endif /* SUPPORT_DBG_SHELL */ #if COMMENT ____Init____(){} #endif void DHL_DBG_StartDbgShell(void) { #if SUPPORT_DBG_SHELL /* °¢Á¾ init code.. */ #if SHELL_USE_SHELL_TASK if (1) { DHL_OS_TASK_ID tid; DHL_OS_Printf("Starting MiniShell, priority %d ...\n", DHL_SHELL_TASK_PRIORITY); tid = s_shell_tid = DHL_OS_CreateTask((DHL_OS_TASKFUNCTION)shell_task_main, "Shell", DHL_SHELL_TASK_PRIORITY, DHL_SHELL_TASK_STACKSIZE, 0); if (tid == DHL_INVALID_TASK_ID) DHL_OS_Printf("!! Shell task spawn error!\n"); else DHL_OS_Printf("Minishell TID 0x%x running\n", tid); } #elif SHELL_ALLOW_EXIT DHL_OS_Printf("enter debug shell. this will block calling thread.\n"); DHL_OS_Printf("type 'exit' to return.\n"); shell_task_main(0); #endif #if DHL_REGISTER_DEUBG_SYMBOLS DHL_DBG_RegisterSymbols(_symbols, DHL_NUMSYMBOLS(_symbols)); #endif #endif /* SUPPORT_DBG_SHELL */ } /* debug minishellÀÇ °¢Á¾ Á¤º¸ query. */ void DHL_DBG_GetDbgShellInfo(DHL_DBG_SHELL_INFO *pInfo) { #if SUPPORT_DBG_SHELL if (s_shell_tid) { pInfo->started = TRUE; pInfo->tid = s_shell_tid; } else { pInfo->started = FALSE; } #else DHL_UNUSED(pInfo); #endif } /* return TRUE if current task is debug shell task */ BOOL DHL_DBG_IsDbgShell(void) { #if SUPPORT_DBG_SHELL DHL_DBG_SHELL_INFO si; DHL_DBG_GetDbgShellInfo(&si); return si.tid == DHL_OS_GetTaskID() ? TRUE : FALSE; #else return FALSE; #endif } /* debug command emulation ÇÔ¼ö. debug shell¿¡ ÀÔ·ÂµÈ °Íó·³ ó¸®ÇÑ´Ù. */ void DHL_DBG_EmulateCommand(const char *cmd) { #if SUPPORT_DBG_SHELL && SHELL_SUPPORT_INPUT_EMULATION if (cmd && *cmd) { UINT32 flag; flag = DHL_OS_DisableInterrupts(); strncpy(g_shell_vibuf, cmd, sizeof(g_shell_vibuf)); g_shell_vibuf[sizeof(g_shell_vibuf)-1] = 0; DHL_OS_RestoreInterrupts(flag); } #else DHL_UNUSED(cmd); #endif } /* end of file */