summaryrefslogtreecommitdiff
path: root/doc/README.commands
blob: 229f86d8fb25074076b22e3aa4d5edcc70f7f502 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
Command definition
------------------

Commands are added to U-Boot by creating a new command structure.
This is done by first including command.h, then using the U_BOOT_CMD() or the
U_BOOT_CMD_COMPLETE macro to fill in a struct cmd_tbl struct.

U_BOOT_CMD(name, maxargs, repeatable, command, "usage", "help")
U_BOOT_CMD_COMPLETE(name, maxargs, repeatable, command, "usage, "help", comp)

name:		The name of the command. THIS IS NOT a string.

maxargs:	The maximum number of arguments this function takes including
		the command itself.

repeatable:	Either 0 or 1 to indicate if autorepeat is allowed.

command:	Pointer to the command function. This is the function that is
		called when the command is issued.

usage:		Short description. This is a string.

help:		Long description. This is a string. The long description is
		only available if CONFIG_SYS_LONGHELP is defined.

comp:		Pointer to the completion function. May be NULL.
		This function is called if the user hits the TAB key while
		entering the command arguments to complete the entry. Command
		completion is only available if CONFIG_AUTO_COMPLETE is defined.

Sub-command definition
----------------------

Likewise an array of struct cmd_tbl holding sub-commands can be created using either
of the following macros:

* U_BOOT_CMD_MKENT(name, maxargs, repeatable, command, "usage", "help")
* U_BOOT_CMD_MKENTCOMPLETE(name, maxargs, repeatable, command, "usage, "help",
  comp)

This table has to be evaluated in the command function of the main command, e.g.

    static struct cmd_tbl cmd_sub[] = {
        U_BOOT_CMD_MKENT(foo, CONFIG_SYS_MAXARGS, 1, do_foo, "", ""),
        U_BOOT_CMD_MKENT(bar, CONFIG_SYS_MAXARGS, 1, do_bar, "", ""),
    };

    static int do_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
    {
        struct cmd_tbl *cp;

        if (argc < 2)
                return CMD_RET_USAGE;

        /* drop sub-command argument */
        argc--;
        argv++;

        cp = find_cmd_tbl(argv[0], cmd_ut_sub, ARRAY_SIZE(cmd_sub));

        if (cp)
            return cp->cmd(cmdtp, flag, argc, argv);

        return CMD_RET_USAGE;
    }

Command function
----------------

The command function pointer has to be of type
int (*cmd)(struct cmd_tbl *cmdtp, int flag, int argc, const char *argv[]);

cmdtp:		Table entry describing the command (see above).

flag:		A bitmap which may contain the following bit:
		CMD_FLAG_REPEAT - The last command is repeated.
		CMD_FLAG_BOOTD  - The command is called by the bootd command.
		CMD_FLAG_ENV    - The command is called by the run command.

argc:		Number of arguments including the command.

argv:		Arguments.

Allowable return value are:

CMD_RET_SUCCESS	The command was successfully executed.

CMD_RET_FAILURE	The command failed.

CMD_RET_USAGE	The command was called with invalid parameters. This value
		leads to the display of the usage string.

Completion function
-------------------

The completion function pointer has to be of type
int (*complete)(int argc, char *const argv[], char last_char,
		int maxv, char *cmdv[]);

argc:		Number of arguments including the command.

argv:		Arguments.

last_char:	The last character in the command line buffer.

maxv:		Maximum number of possible completions that may be returned by
		the function.

cmdv:		Used to return possible values for the last argument. The last
		possible completion must be followed by NULL.

The function returns the number of possible completions (without the terminating
NULL value).

Behind the scene
----------------

The structure created is named with a special prefix and placed by
the linker in a special section using the linker lists mechanism
(see include/linker_lists.h)

This makes it possible for the final link to extract all commands
compiled into any object code and construct a static array so the
command array can be iterated over using the linker lists macros.

The linker lists feature ensures that the linker does not discard
these symbols when linking full U-Boot even though they are not
referenced in the source code as such.

If a new board is defined do not forget to define the command section
by writing in u-boot.lds ($(srctree)/board/boardname/u-boot.lds) these
3 lines:

	.u_boot_list : {
		KEEP(*(SORT(.u_boot_list*)));
	}

Writing tests
-------------

All new commands should have tests. Tests for existing commands are very
welcome.

It is fairly easy to write a test for a command. Enable it in sandbox, and
then add code that runs the command and checks the output.

Here is an example:

/* Test 'acpi items' command */
static int dm_test_acpi_cmd_items(struct unit_test_state *uts)
{
	struct acpi_ctx ctx;
	void *buf;

	buf = malloc(BUF_SIZE);
	ut_assertnonnull(buf);

	ctx.current = buf;
	ut_assertok(acpi_fill_ssdt(&ctx));
	console_record_reset();
	run_command("acpi items", 0);
	ut_assert_nextline("dev 'acpi-test', type 1, size 2");
	ut_assert_nextline("dev 'acpi-test2', type 1, size 2");
	ut_assert_console_end();

	ctx.current = buf;
	ut_assertok(acpi_inject_dsdt(&ctx));
	console_record_reset();
	run_command("acpi items", 0);
	ut_assert_nextline("dev 'acpi-test', type 2, size 2");
	ut_assert_nextline("dev 'acpi-test2', type 2, size 2");
	ut_assert_console_end();

	console_record_reset();
	run_command("acpi items -d", 0);
	ut_assert_nextline("dev 'acpi-test', type 2, size 2");
	ut_assert_nextlines_are_dump(2);
	ut_assert_nextline("%s", "");
	ut_assert_nextline("dev 'acpi-test2', type 2, size 2");
	ut_assert_nextlines_are_dump(2);
	ut_assert_nextline("%s", "");
	ut_assert_console_end();

	return 0;
}
DM_TEST(dm_test_acpi_cmd_items, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);