[PATCH] mmc: rpmb: Fix driver routing memory alignment with tmp buffer

Timothée Cercueil litchi.pi at protonmail.com
Tue Jun 15 10:53:06 CEST 2021

From: litchipi <litchi.pi at protonmail.com>

Fix mmc_rpmb_route_frames() implementation to comply with most MMC
drivers that expect some alignment of MMC data frames in memory.

When called from drivers/tee/optee/rpmb.c, the address passed is not
aligned properly. OP-TEE OS inserts a 6-byte header before a raw RPMB
frame which makes RPMB data buffer not 32bit aligned. To prevent breaking
ABI with OPTEE-OS RPC memrefs, allocate a temporary buffer to copy the
data into an aligned memory.

Many RPMB drivers implicitly expect 32bit alignment of the eMMC frame
including arm_pl180_mmci.c, sandbox_mmc.c and stm32_sdmmc2.c

Signed-off-by: Timothée Cercueil <timothee.cercueil at st.com>
Signed-off-by: Timothée Cercueil <litchi.pi at protonmail.com>
 drivers/mmc/rpmb.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

Changes since v1:
	- Fixed the Signed-off-by errors from previous patch.
	- This patch follows the subject discussed at: https://lists.denx.de/pipermail/u-boot/2021-June/451687.html
	- Changed the commit log 1st line

diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c
index ea7e506666..b68d98573c 100644
--- a/drivers/mmc/rpmb.c
+++ b/drivers/mmc/rpmb.c
@@ -480,10 +480,24 @@ int mmc_rpmb_route_frames(struct mmc *mmc, void *req, unsigned long reqlen,
 	 * and possibly just delay an eventual error which will be harder
 	 * to track down.
+	void *rpmb_data = NULL;
+	int ret;

 	if (reqlen % sizeof(struct s_rpmb) || rsplen % sizeof(struct s_rpmb))
 		return -EINVAL;

-	return rpmb_route_frames(mmc, req, reqlen / sizeof(struct s_rpmb),
-				 rsp, rsplen / sizeof(struct s_rpmb));
+	if (!IS_ALIGNED((uintptr_t)req, ARCH_DMA_MINALIGN)) {
+		/* Memory alignment is required by MMC driver */
+		rpmb_data = malloc(reqlen);
+		if (!rpmb_data)
+			return -ENOMEM;
+		memcpy(rpmb_data, req, reqlen);
+		req = rpmb_data;
+	}
+	ret = rpmb_route_frames(mmc, req, reqlen / sizeof(struct s_rpmb),
+				rsp, rsplen / sizeof(struct s_rpmb));
+	free(rpmb_data);
+	return ret;

More information about the U-Boot mailing list