[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