[U-Boot] [PATCH v3 2/3] cmd: Add 'bcb' command to read/modify/write BCB fields
Eugeniu Rosca
roscaeugeniu at gmail.com
Sat Jul 6 16:18:46 UTC 2019
Hi Simon,
On Sat, Jun 22, 2019 at 08:09:48PM +0100, Simon Glass wrote:
> On Thu, 23 May 2019 at 16:33, Eugeniu Rosca <erosca at de.adit-jv.com> wrote:
[..]
> I'm going to make some general comments as I still feel that this code
> is really odd.
Thanks. My replies below.
> > +enum bcb_cmd {
>
> > + BCB_CMD_LOAD,
> > + BCB_CMD_FIELD_SET,
> > + BCB_CMD_FIELD_CLEAR,
> > + BCB_CMD_FIELD_TEST,
> > + BCB_CMD_FIELD_DUMP,
> > + BCB_CMD_STORE,
> > +};
>
> It looks like this ^^ can be removed, see below.
My reply below.
> > +static int bcb_cmd_get(char *cmd)
> > +{
> > + if (!strncmp(cmd, "load", sizeof("load")))
>
> Is this strncmp() for a security reason? I don't think that is
> necessary. We typically would avoid using the command line in secure
> situations.
strncmp() is chosen for the sake of paranoid/defensive programming.
Indeed, strncmp() is not really needed when comparing a variable
with a string literal. We expect strcmp() to behave safely even if the
string variable is not NUL-terminated.
In the same scenario, Linux v5.2-rc7 uses both strcmp() and strncmp(),
but the frequency of strcmp() is higher:
$ git --version
git version 2.22.0
$ (Linux 5.2-rc7) git grep -En 'strncmp\([^"]*"[[:alnum:]]+"' | wc -l
1066
$ (Linux 5.2-rc7) git grep -En 'strcmp\([^"]*"[[:alnum:]]+"' | wc -l
1968
A quick "strcmp vs strncmp" object size test shows that strcmp()
generates smaller memory footprint (gcc-8, x86_64):
$ (U-Boot) size cmd/bcb-strncmp.o cmd/bcb-strcmp.o
text data bss dec hex filename
3373 400 2048 5821 16bd cmd/bcb-strncmp.o
3314 400 2048 5762 1682 cmd/bcb-strcmp.o
So, overall, I agree to use strcmp() whenever variables are compared
with string literals.
>
> Better I think to check just the first 1-2 chars which is enough to
> distinguish the command.
I personally think this will make the code less readable and will
increase maintenance effort. This will especially be annoying when
differentiating sub-commands like set/see, start/status, etc, which
have a long common prefix.
>
> > + return BCB_CMD_LOAD;
> > + if (!strncmp(cmd, "set", sizeof("set")))
> > + return BCB_CMD_FIELD_SET;
> > + if (!strncmp(cmd, "clear", sizeof("clear")))
> > + return BCB_CMD_FIELD_CLEAR;
> > + if (!strncmp(cmd, "test", sizeof("test")))
> > + return BCB_CMD_FIELD_TEST;
> > + if (!strncmp(cmd, "store", sizeof("store")))
> > + return BCB_CMD_STORE;
> > + if (!strncmp(cmd, "dump", sizeof("dump")))
> > + return BCB_CMD_FIELD_DUMP;
> > + else
> > + return -1;
> > +}
>
> and this function ^^
Do you propose zapping both bcb_cmd_get() and bcb_is_misused()?
I stress again that bcb_is_misused() aims to centralize error reporting.
Without bcb_is_misused(), I would need to create multiple instances of
below error messages (since they would need to be reported by several
sub-commands), increasing the code size:
- printf("Error: Please, load BCB first!\n");
- printf("Error: Bad usage of 'bcb %s'\n", subcommand);
>
> > +
> > +static int bcb_is_misused(int argc, char *const argv[])
> > +{
> > + int cmd = bcb_cmd_get(argv[0]);
> > +
> > + switch (cmd) {
> > + case BCB_CMD_LOAD:
> > + if (argc != 3)
> > + goto err;
> > + break;
>
> To me it does not make sense to hold the validation code for 'load'
> here. It just makes it harder to maintain if we update it, since we
> need to change the code and and below.
Please, make me understand. Are you unhappy about 'bcb load' only or
are you unhappy about the bcb_is_misused()? I provided some arguments
above to still keep this function in place.
If this function is preserved, I see no reason to treat 'bcb load'
differently from other sub-commands.
> > +static int bcb_field_get(char *name, char **field, int *size)
>
> How about fieldp and sizep to indicate that these values are returned?
Makes sense. Will be updated.
> > +
> > +static int
>
> Would prefer not to split the line here so we can search for 'int
> do_', for example.
Will update that, although I see 355 occurrences of this pattern in
U-Boot and 23980 occurrences in Linux v5.2-rc7:
$ (U-Boot/master) git grep -E "^static\s+[[:alnum:]]+$" -- "*.c" "*.h" | wc -l
355
$ (Linux v5.2-rc7) git grep -E "^static\s+[[:alnum:]]+$" -- "*.c" "*.h" | wc -l
23980
This makes me wonder where the border between subjective preferences
of the maintainer and objective coding style requirements really is?
> > + if (blk_dread(desc, info.start, cnt, &bcb) != cnt) {
> > + ret = -EIO;
>
> Actually the error code is the return value of blk_dread(). Although
> perhaps it is badly documented.
Based on my reading, blk_dread() returns ulong, not a negative error
code. I could find no blk_dread() caller which reuses the return value
as error code. I will make no change here.
> > +err_1:
>
> How about err_read_fail
>
> > +err_2:
>
> err_too_small
Agreed. Will be updated.
>
> > + printf("Error: mmc %s:%s too small!", argv[1], argv[2]);
> > + goto err;
> > +err:
> > + bcb_dev = -1;
> > + bcb_part = -1;
>
> Why these two lines?
They act as an indicator for wrongly loaded or unloaded BCB.
> > + if (blk_dwrite(desc, info.start, cnt, &bcb) != cnt) {
>
> as above
My feedback on blk_dread() applies here too.
> > + if (bcb_is_misused(argc, argv)) {
> > + /* We try to improve the user experience by reporting the
>
> /*
> * We try ...
> * ...
> */
Will be updated.
>
> > + * root-cause of misusage, so don't return CMD_RET_USAGE,
> > + * since the latter prints out the full-blown help text
>
> Right, but that's the idea...this is how people get the syntax.
I prefer to tell the users what's the reason of their command being
rejected rather than throwing a full-blown help message which they
didn't ask for.
--
Best Regards,
Eugeniu.
More information about the U-Boot
mailing list