[PATCH] mmc: Set write protect for eMMC user area
Peng Fan
peng.fan at oss.nxp.com
Thu Jul 17 07:19:49 CEST 2025
On Tue, Jul 15, 2025 at 06:04:07PM +0300, Роман wrote:
>
>From 29246e776674a73e4dd93ee15f7c94cb5d99a797 Mon Sep 17 00:00:00 2001
>From: Urovsky R <urovsky at swemel.ru>
>Date: Sat, 12 Jul 2025 19:29:53 +0300
>Subject: [PATCH] mmc: Set write protect for eMMC user area
>
>Set write protect configuration for the specified region of the user area for the device.
>Available modes for region are: 'none', 'temp', 'poweron'.
>'perm' mode not realized. You better use mmc-utils from Linux for that mode.
>The idea and most of the source code take from project "mmc-utils"
Please explain a bit here why you wanna introduce this in U-Boot and
the benefit.
>
>Signed-off-by: Urovsky Roman <rour at inbox.ru>
>---
> cmd/mmc.c | 373 ++++++++++++++++++++++++++++++++++++++++++++++
> drivers/mmc/mmc.c | 2 +-
> include/mmc.h | 16 ++
Please also update doc/usage/cmd/mmc.rst
> 3 files changed, 390 insertions(+), 1 deletion(-)
>
>diff --git a/cmd/mmc.c b/cmd/mmc.c
>index 5340a58be8e..d8c6def4a1a 100644
>--- a/cmd/mmc.c
>+++ b/cmd/mmc.c
>@@ -18,6 +18,26 @@
> #include <vsprintf.h>
> #include <linux/ctype.h>
>
>+extern int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms);
>+extern int mmc_send_cmd_retry(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data, uint retries);
This is in mmc_private.h, please not use extern and run checkpatch.pl for your
patch.
To add write protect, need put code under drivers/mmc/ and export API to
cmd/mmc.c
>+
>+#define WP_BLKS_PER_QUERY 32
>+
>+#define WPTYPE_NONE 0
>+#define WPTYPE_TEMP 1
>+#define WPTYPE_PWRON 2
>+#define WPTYPE_PERM 3
>+
>+static int do_writeprotect_user_get(void);
>+static int do_writeprotect_user_set(int argc, char *const argv[]);
>+
>+static char *prot_desc[] = {
>+ "No",
>+ "Temporary",
>+ "Power-on",
>+ "Permanent"
>+};
>+
> static int curr_device = -1;
>
> static void print_mmcinfo(struct mmc *mmc)
>@@ -1228,10 +1248,33 @@ static int do_mmc_reg(struct cmd_tbl *cmdtp, int flag,
> }
> #endif
>
>+int do_mmc_user_wp(struct cmd_tbl *cmdtp, int flag,
>+ int argc, char * const argv[])
>+{
>+ int err;
>+/*
>+ printf("argc = %d\n", argc);
>+ for (int i = 0; i < argc; i++) {
>+ printf("argv[%d] = %s\n", i, argv[i]);
>+ }
>+*/
Drop this.
>+ if ( argc >= 2 ) {
>+ err = do_writeprotect_user_set(argc, argv);
>+
>+ if (err)
>+ return CMD_RET_FAILURE;
>+ }
>+
>+ do_writeprotect_user_get();
check return value?
>+
>+ return CMD_RET_SUCCESS;
>+}
>+
> static struct cmd_tbl cmd_mmc[] = {
> U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""),
> U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""),
> U_BOOT_CMD_MKENT(wp, 2, 0, do_mmc_boot_wp, "", ""),
>+ U_BOOT_CMD_MKENT(user-wp, 4, 0, do_mmc_user_wp, "", ""),
> #if CONFIG_IS_ENABLED(MMC_WRITE)
> U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""),
> U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""),
>@@ -1315,6 +1358,15 @@ U_BOOT_CMD(
> " PART - [0|1]\n"
> " : 0 - first boot partition, 1 - second boot partition\n"
> " if not assigned, write protect all boot partitions\n"
>+ "mmc user-wp - Get the write protect info for user area\n"
>+ "mmc user-wp [type] all - Set the write protect for the full region of the user area\n"
>+ "mmc user-wp [type] [start-block] [blocks] - Set the write protect for the specified region of the user area\n"
>+ " type: \n"
>+ " none - Clear temporary write protection\n"
>+ " temp - Set temporary write protection\n"
>+ " pwron - Set write protection until the next power on\n"
>+ " start-block - specifies the first block of the protected area. 'all' - to protect all user area\n"
>+ " blocks - specifies the size of the protected area in blocks \n"
> #if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
> "mmc hwpartition <USER> <GP> <MODE> - does hardware partitioning\n"
> " arguments (sizes in 512-byte blocks):\n"
>@@ -1366,3 +1418,324 @@ U_BOOT_CMD(
> "display MMC info",
> "- display info of the current MMC device"
> );
>+
>+
>+static int get_wp_group_size_in_blks(u8 *ext_csd, u32 *size)
>+{
>+ u8 ext_csd_rev = ext_csd[EXT_CSD_REV];
>+
>+ if ((ext_csd_rev < 5) || (ext_csd[EXT_CSD_ERASE_GROUP_DEF] == 0)) {
>+ printf("EXT_CSD_REV = %d\n", ext_csd[EXT_CSD_REV]);
>+ printf("EXT_CSD_ERASE_GROUP_DEF = %d\n", ext_csd[EXT_CSD_ERASE_GROUP_DEF]);
>+ return 1;
>+ }
>+
>+ *size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] *
>+ ext_csd[EXT_CSD_HC_WP_GRP_SIZE] * 1024;
Add blank line.
>+ return 0;
>+}
>+
>+
>+static int send_write_protect_type(struct mmc *mmc, u32 blk_addr, u64 *group_bits)
>+{
>+ int ret = 0;
>+
>+ struct mmc_cmd cmd;
>+ struct mmc_data data;
>+
>+ u8 buf[8] = {0};
>+ u64 bits = 0;
>+ int x;
>+
>+
Extra blank line.
>+ /* Get the Card Status Register */
>+ cmd.cmdidx = MMC_SEND_WRITE_PROT_TYPE;
>+ cmd.resp_type = MMC_RSP_R1 | MMC_CMD_ADTC;
>+ cmd.cmdarg = blk_addr;
>+
>+ data.dest = (char *)buf;
>+ data.blocks = 1;
>+ data.blocksize = 8;
>+ data.flags = MMC_DATA_READ;
>+
>+ ret = mmc_send_cmd(mmc, &cmd, &data);
>+ if ( ret != 0 ) {
>+ printf("Error: mmc_send_cmd()\n");
>+ return 1;
>+ }
>+
>+
>+ for (x = 0; x < sizeof(buf); x++)
>+ bits |= (u64)(buf[7 - x]) << (x * 8);
>+ *group_bits = bits;
>+
>+ return 0;
>+}
>+
>+
Extra blank line.
Please cleanup your patch first and run checkpatch,
I will look into details on V2.
Thanks,
Peng
More information about the U-Boot
mailing list