Hi Daniel,

Nice command. Several comments inline, there is still some way to go to
get this into shape.

On Mon, Aug 24, 2015 at 01:32:13PM +0200, Daniel Schultz wrote:
> +
> +static int print_field(u8 *reg, int index)
> +{
> +     int rev;
> +     u32 val;
> +     u32 tmp;
> +     u64 tmp64;
> +
> +     rev = reg[EXT_CSD_REV];
> +
> +     if (rev >= 7)

Additional print_field_v7/v6/v5() functions will reduce the indentation
level by one and help violating the 80 character limit less often.

> +             switch (index) {
> +             case EXT_CSD_CMDQ_MODE_EN:
> +                     print_field_caption(CMDQ_MODE_EN, RWE_P);
> +                     val = get_field_val(CMDQ_MODE_EN, 0, 0x1);
> +                     if (val)
> +                             printf("\tCommand queuing is enabled\n");
> +                     else
> +                             printf("\tCommand queuing is disabled\n");

Your printfs are very inefficient. You should use something like:

        if (val)
                str = "en";
        else
                str = "dis";
        printf("Command queuing is %sabled\n", str);

Same goes for many other printfs. This will result in much less similar
strings in the binary.

> +                     return 1;
> +
> +             case EXT_CSD_SECURE_REMOVAL_TYPE:
> +                     print_field_caption(SECURE_REMOVAL_TYPE, RWaR);
> +                     val = get_field_val(SECURE_REMOVAL_TYPE, 0, 0xF);
> +                     switch (val) {
> +                     case 0x0:
> +                             printf("\t[3-0] Supported Secure Removal Type: 
> information removed by an erase of the physical memory\n");
> +                             break;
> +                     case 0x1:
> +                             printf("\t[3-0] Supported Secure Removal Type: 
> information removed by an overwriting the addressed locations with a 
> character followed by an erase\n");
> +                             break;
> +                     case 0x2:
> +                             printf("\t[3-0] Supported Secure Removal Type: 
> information removed by an overwriting the addressed locations with a 
> character, its complement, then a random character\n");
> +                             break;
> +                     case 0x3:
> +                             printf("\t[3-0] Supported Secure Removal Type: 
> information removed using a vendor defined\n");
> +                             break;

This is *very* verbose. Could you write this a bit more compact, maybe

        case 0x0:
                str = "erase";
                break;
        case 0x1:
                str = "overwrite, then erase";
                break;
        case 0x2:
                str = "overwrite, complement, then random";
                break;
        case 0x3:
                str = "vendor defined";
                break;

        printf("[3-0] Supported Secure Removal Type: %s\n", str);

Background is that this information only makes sense when being somewhat
familiar with the spec. Without knowing the spec at all even the more
verbose printfs do not help, but when knowing the spec a more compact
writing is enough to remember what is meant.

> +
> +static void print_register_raw(u8 *reg, int index)
> +{
> +     int i;
> +
> +     if (index == 0)
> +             for (i = 0; i < EXT_CSD_BLOCKSIZE; i++) {
> +                     if (i % 8 == 0)
> +                             printf("%u:", i);
> +                     printf(" %#02x", reg[i]);
> +                     if (i % 8 == 7)
> +                             printf("\n");
> +             }

        memory_display(reg, 0, EXT_CSD_BLOCKSIZE, 1, 0);

Should do it here.

> +static int do_extcsd(int argc, char *argv[])
> +{
> +     struct device_d         *dev;
> +     struct mci              *mci;
> +     struct mci_host         *host;
> +     u8                      *dst;
> +     int                     retval = 0;
> +     int                     opt;
> +     char                    *devname;
> +     int                     index = 0;
> +     int                     value = 0;
> +     int                     write_operation = 0;
> +     int                     always_write = 0;
> +     int                     print_as_raw = 0;
> +
> +     if (argv[1] == NULL)
> +             return COMMAND_ERROR_USAGE;

argc contains the number of arguments. When argc is 1 then argv[1] is
undefined. It may or may not be NULL in this case. You want to use if
(argc < 2) here.

> +
> +     devname = argv[1];

You should use argv[optind] after parsing the arguments for the devname.
With this not only "extcsd <devname> [OPTIONS]" works but also "extcsd
[OPTIONS] <devname>". Don't forget to check if there actually is
argv[optind] by

        if (optind == argc)
                return COMMAND_ERROR_USAGE;

> +     if (!strncmp(devname, "/dev/", 5))
> +             devname += 5;
> +
> +     while ((opt = getopt(argc, argv, "i:v:yr")) > 0)
> +             switch (opt) {
> +             case 'i':
> +                     index = simple_strtoul(optarg, NULL, 0);
> +                     break;
> +             case 'v':
> +                     value = simple_strtoul(optarg, NULL, 0);
> +                     write_operation = 1;
> +                     break;
> +             case 'y':
> +                     always_write = 1;
> +                     break;
> +             case 'r':
> +                     print_as_raw = 1;
> +                     break;
> +             }
> +
> +     dev = get_device_by_name(devname);
> +     if (dev == NULL) {
> +             retval = -ENODEV;
> +             goto error;
> +     }
> +     mci = container_of(dev, struct mci, dev);
> +     if (mci == NULL) {
> +             retval = -ENOENT;
> +             goto error;
> +     }

Unfortunately this doesn't work properly. It works when the argument
really is a mmc devices, but it doesn't detect when the argument is some
other type of device. This code will happily use container_of on
something that is not a MMC device and probably crash barebox. What you
have to do is:

- add a struct list_head member to struct mci and put all mci devices
  to a list during registration
- create a struct mci *mci_get_device_by_name(const char *name)
  function and use it here.

> +     host = mci->host;
> +     if (host == NULL) {
> +             retval = -ENOENT;
> +             goto error;
> +     }
> +     dst = xmalloc(sizeof(*dst) * EXT_CSD_BLOCKSIZE);

xmalloc(EXT_CSD_BLOCKSIZE) is enough here.

> +     if (dst == NULL) {
> +             retval = -ENOMEM;
> +             goto error;
> +     }

xmalloc never fails. You don't need to check the return value.

> +
> +     retval = mci_send_ext_csd(mci, dst);
> +     if (retval != 0)
> +             goto error_with_mem;
> +
> +     if (dst[EXT_CSD_REV] < 3) {
> +             printf("MMC version 4.2 or lower are not supported");
> +             retval = 1;
> +             goto error_with_mem;
> +     }
> +
> +     if (write_operation)
> +             if (!print_field(dst, index)) {
> +                     printf("No field with this index found. Abort write 
> operation!\n");
> +             } else {
> +                     write_field(mci, dst, index, value, always_write);
> +                     printf("\nValue written!\n\n");
> +                     retval = mci_send_ext_csd(mci, dst);
> +                     if (retval != 0)
> +                             goto error_with_mem;
> +                     print_field(dst, index);
> +             }
> +     else
> +             if (print_as_raw)
> +                     print_register_raw(dst, index);
> +             else
> +                     print_register_readable(dst, index);
> +
> +error_with_mem:
> +     free(dst);
> +error:
> +     return retval;
> +}
> +
> +BAREBOX_CMD_HELP_START(extcsd)

Better rename this to mmc-extcsd so that the context of this command is
clear.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to