명령어 테이블 구조체
U-Boot에서 각 명령어는 cmd_tbl_s 구조체로 표현되며, 명령어 이름, 인자 개수, 실행 함수, 도움말 등을 포함한다.
struct cmd_tbl_s {
char *cmd_name; /* 명령어 이름 */
int arg_max; /* 최대 인자 수 */
int auto_repeat; /* 자동 반복 가능 여부 */
int (*exec)(struct cmd_tbl_s *, int, int, char *[]);
char *brief; /* 간단한 사용법 */
#ifdef CFG_LONGHELP
char *detail; /* 상세 도움 */
#endif
#ifdef CONFIG_AUTO_COMPLETE
int (*complete)(int, char *[], char, int, char *[]);
#endif
};
typedef struct cmd_tbl_s cmd_tbl_t;
전용 섹션을 통한 명령어 배치
컴파일러 속성을 활용해 명령어 정보를 .u_boot_cmd 섹션에 배치한다. 이를 통해 타임에 연속된 메모리 영역에서 명령어를 순회할 수 있다.
#define SECTION_ATTR __attribute__((unused, section(".u_boot_cmd")))
#define SHELL_CMD(n, args, repeat, fn, usage_str, help_str) \
cmd_tbl_t __cmd_info_##n SECTION_ATTR = { \
#n, args, repeat, fn, usage_str, help_str \
}
매크로 전개 결과는 다음과 같다. __cmd_info_hello 변수가 지정된 섹션에 배치되며, 초기값으로 명령어 정보가 설정된다.
/* SHELL_CMD(hello, 3, 1, run_hello, "help", "detail") 전개 후 */
cmd_tbl_t __cmd_info_hello
__attribute__((unused, section(".u_boot_cmd"))) = {
"hello", 3, 1, run_hello, "help", "detail"
};
find_cmd 함수 분석
입력된 문자열과 일치하는 명령어를 검색하며, 전체 일치뿐 아니라 고유한 축약형도 허용한다. 점(.) 이전까지만 비교하여 cp.b 같은 형태도 처리한다.
cmd_tbl_t *find_cmd(const char *input)
{
cmd_tbl_t *entry;
cmd_tbl_t *candidate = &__cmd_table_begin;
const char *dot_pos;
int match_len;
int partial_cnt = 0;
/* 점(.) 이전 길이 계산: "cp.b" -> "cp" 길이 */
dot_pos = strchr(input, '.');
match_len = dot_pos ? (dot_pos - input) : strlen(input);
for (entry = &__cmd_table_begin;
entry != &__cmd_table_end;
entry++) {
if (strncmp(input, entry->cmd_name, match_len) != 0)
continue;
if (match_len == strlen(entry->cmd_name))
return entry; /* 완전 일치 */
candidate = entry; /* 축약 가능 후보 */
partial_cnt++;
}
/* 후보가 유일하면 축약 명령어로 인정 */
if (partial_cnt == 1)
return candidate;
return NULL; /* 미발견 또는 모호한 축약 */
}
검색 알고리즘 핵심
링커 스크립트에서 __cmd_table_begin과 __cmd_table_end 볼로 섹션 경계를 정의한다. 이를 통해 for 루프가 연속된 명령어 테이블을 순회하며, O(n) 선형 검색으로 입력 명령어와 매칭시킨다.
축약 처리 로직의 핵심은 partial_cnt 카운트다. st가 start와 stop 두 명령어에 모두 매칭되면 모호성으로 판단해 NULL을 반환한다. 반면 he가 hello만 매칭되면 유일 후보로 인정되어 실행 가능하다.