RE: [PATCH] mmc-utils: Implement alternative boot operation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> Implements the alternative boot operation for eMMCs.
> Note the limitations of the help.
> 
> This is mostly useful for testing purposes if you set up the boot partition
> configuration correctly.
> 
> Usage:
> $ sudo dd if=/dev/mmcblk2boot0 of=bootdatammcblk count=2
> 2+0 records in
> 2+0 records out
> 1024 bytes (1.0 kB, 1.0 KiB) copied, 0.00482308 s, 212 kB/s
> 
> $ sudo ./mmc boot_operation bootdata 2 /dev/mmcblk2
> 
> $ diff -s bootdata bootdatammcblk
> Files bootdata and bootdatammcblk are identical
> 
> Signed-off-by: Christian Loehle <cloehle@xxxxxxxxxxxxxx>
> ---
>  mmc.c      | 12 +++++++++
>  mmc.h      |  1 +
>  mmc_cmds.c | 76
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  mmc_cmds.h |  1 +
>  4 files changed, 90 insertions(+)
> 
> diff --git a/mmc.c b/mmc.c
> index 170ee39..f328585 100644
> --- a/mmc.c
> +++ b/mmc.c
> @@ -255,6 +255,18 @@ static struct Command commands[] = {
>           "Issues a CMD0 GO_PRE_IDLE",
>           NULL
>         },
> +       { do_alt_boot_op, -1,
> +         "boot_operation", "<boot_data_file> <boot_blocks> <device>\n"
> +         "Does the alternative boot operation and writes the specified starting
> blocks of boot data into the requested file.\n\n"
> +         "Note some limitations\n:"
> +         "1. The boot operation must be configured, e.g. for legacy speed:\n"
> +         "mmc-utils bootbus set single_backward retain x8 /dev/mmcblk2\n"
> +         "mmc-utils bootpart enable 1 0 /dev/mmcblk2\n"
> +         "2. The MMC must currently be running at the bus mode that is
> configured for the boot operation (HS200 and HS400 not supported at all).\n"
> +         "3. Most hosts cannot do transfers of the typical size of the boot partition,
> adjust <boot_blocks> accordingly.\n"
A redundant arg?
Since blksz is 512, Maybe just set it to be ext_csd[226] * 256?

> +         "4. The MMC will perform a soft reset, if your system cannot handle that
> do not use the boot operation from mmc-utils.\n",
> +         NULL
> +       },
>         { 0, 0, 0, 0 }
>  };
> 
> diff --git a/mmc.h b/mmc.h
> index 6511dbc..98fad16 100644
> --- a/mmc.h
> +++ b/mmc.h
> @@ -24,6 +24,7 @@
>  #define MMC_GO_IDLE_STATE         0   /* bc                          */
>  #define MMC_GO_IDLE_STATE_ARG          0x0
>  #define MMC_GO_PRE_IDLE_STATE_ARG      0xF0F0F0F0
> +#define MMC_BOOT_INITIATION_ARG                0xFFFFFFFA
>  #define MMC_SWITCH             6       /* ac   [31:0] See below        R1b */
>  #define MMC_SEND_EXT_CSD       8       /* adtc                         R1  */
>  #define MMC_SEND_STATUS                13      /* ac   [31:16] RCA        R1  */
> diff --git a/mmc_cmds.c b/mmc_cmds.c
> index 3db17e1..1da61d4 100644
> --- a/mmc_cmds.c
> +++ b/mmc_cmds.c
> @@ -3101,3 +3101,79 @@ int do_preidle(int nargs, char **argv)
> 
>         return 0;
>  }
> +
> +int do_alt_boot_op(int nargs, char **argv) {
> +       int fd, ret, boot_data_fd;
> +       char *device, *boot_data_file;
> +       struct mmc_ioc_multi_cmd *mioc;
> +       __u8 ext_csd[512];
> +       __u8 *boot_buf;
> +       unsigned int boot_blocks, ext_csd_boot_size;
> +
> +       if (nargs != 4) {
> +               fprintf(stderr, "Usage: mmc boot_op <boot_data_file> <boot_blocks>
> </path/to/mmcblkX>\n");
> +               exit(1);
> +       }
> +       boot_data_file = argv[1];
> +       boot_blocks = strtol(argv[2], NULL, 10);
> +       device = argv[3];
> +
> +       fd = open(device, O_RDWR);
> +       if (fd < 0) {
> +               perror("open device");
> +               exit(1);
> +       }
> +       boot_data_fd = open(boot_data_file, O_WRONLY | O_CREAT, 0644);
> +       if (boot_data_fd < 0) {
> +               perror("open boot data file");
> +               exit(1);
> +       }
> +
> +       ret = read_extcsd(fd, ext_csd);
> +       if (ret) {
> +               perror("read extcsd");
> +               exit(1);
> +       }
One line space please.
Also, need to check alternative boot support: (ext_csd[EXT_CSD_BOOT_INFO] & EXT_CSD_BOOT_INFO_ALT)

> +       ext_csd_boot_size = ext_csd[226] * 128 * 1024;
> +       if (boot_blocks * 512 > ext_csd_boot_size) {
> +               perror("Requested boot size bigger than boot partition");
> +               exit(1);
> +       }
> +
> +       boot_buf = calloc(1, sizeof(__u8) * boot_blocks * 512);
> +       mioc = calloc(1, sizeof(struct mmc_ioc_multi_cmd) +
> +                          2 * sizeof(struct mmc_ioc_cmd));
> +       if (!mioc || !boot_buf) {
> +               perror("Failed to allocate memory");
> +               return -ENOMEM;
> +       }
> +
> +       mioc->num_of_cmds = 2;
> +       mioc->cmds[0].opcode = MMC_GO_IDLE_STATE;
> +       mioc->cmds[0].arg = MMC_GO_PRE_IDLE_STATE_ARG;
> +       mioc->cmds[0].flags = MMC_RSP_NONE | MMC_CMD_AC;
> +       mioc->cmds[0].write_flag = 0;
> +
> +       mioc->cmds[1].opcode = MMC_GO_IDLE_STATE;
> +       mioc->cmds[1].arg = MMC_BOOT_INITIATION_ARG;
> +       mioc->cmds[1].flags = MMC_RSP_NONE | MMC_CMD_ADTC;
> +       mioc->cmds[1].write_flag = 0;
> +       mioc->cmds[1].blksz = 512;
> +       mioc->cmds[1].blocks = boot_blocks;
> +       /* Access time of boot part differs wildly, spec mandates 1s */
> +       mioc->cmds[1].data_timeout_ns = 2 * 1000 * 1000 * 1000;
> +       mmc_ioc_cmd_set_data(mioc->cmds[1], boot_buf);
Don't you get "010" prior to the boot content?
Most cards have their EXT_CSD_PART_CONFIG_ACC_ACK bit set.
So you need to eliminate it from the boot file?
But your compare show that the files are identical - how so?

> +
> +       ret = ioctl(fd, MMC_IOC_MULTI_CMD, mioc);
> +       if (ret)
> +               perror("multi-cmd ioctl error %d\n", ret);
If an error occurred - do you still want to output the boot file?

> +       close(fd);

Don't you need to send CMD1 to terminate the alternative boot sequence?
Without it, isn't the card stack in Card-identification Mode?

> +
> +       ret = DO_IO(write, boot_data_fd, boot_buf, boot_blocks * 512);
> +       if (ret < 0) {
> +               perror("Write error\n");
Free whatever you alloc'ed

> +               exit(1);
> +       }
ditto

Thanks,
Avri
> +       return 0;
> +}
> diff --git a/mmc_cmds.h b/mmc_cmds.h
> index faab362..5f2bef1 100644
> --- a/mmc_cmds.h
> +++ b/mmc_cmds.h
> @@ -49,3 +49,4 @@ int do_erase(int nargs, char **argv);  int
> do_general_cmd_read(int nargs, char **argv);  int do_softreset(int nargs, char
> **argv);  int do_preidle(int nargs, char **argv);
> +int do_alt_boot_op(int nargs, char **argv);
> --
> 2.37.3
> 
> Hyperstone GmbH | Reichenaustr. 39a  | 78467 Konstanz Managing Director:
> Dr. Jan Peter Berns.
> Commercial register of local courts: Freiburg HRB381782





[Index of Archives]     [Linux Memonry Technology]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux