From patchwork Thu Feb 15 15:10:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Babic X-Patchwork-Id: 1899381 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.a=rsa-sha256 header.s=20230601 header.b=SewuogXv; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=googlegroups.com (client-ip=2a00:1450:4864:20::137; helo=mail-lf1-x137.google.com; envelope-from=swupdate+bncbaabb2gsxcxamgqey3wnoay@googlegroups.com; receiver=patchwork.ozlabs.org) Received: from mail-lf1-x137.google.com (mail-lf1-x137.google.com [IPv6:2a00:1450:4864:20::137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TbJR13PPqz23j8 for ; Fri, 16 Feb 2024 02:10:37 +1100 (AEDT) Received: by mail-lf1-x137.google.com with SMTP id 2adb3069b0e04-50e91f9d422sf1259229e87.2 for ; Thu, 15 Feb 2024 07:10:37 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708009833; cv=pass; d=google.com; s=arc-20160816; b=tlOR+G//m1x3MHIXxlOFr5SgRHjUPP9DBQrgMqQczcpURqVfU0YjE9AMLRNNIr6K/P 2eRsL0UePEns6XBWaeSybpeEjdCkXE8EG9x/HtooCPzMnMmX3JX/BPQg35jJo5weNN6S J34dlGavvy9918LIg4t/EhW0AJqCYhYfDMOPk2aG9xA2isKljCsLjuT0mXgd852Ch5av y+jH755u20Q1OqZ5zNXHFiTYBm2LSxO40Mu52nSxnxERX61SNtB1+V5IZ+3I9Hu/NFHK qtFjM8+UVsbWNR4q2EEWgI3CoTxPohlhyU/TYzrq0vK4imY5Fy255KbTlofdcVdKbiO9 z+GQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:ui-outboundreport:mime-version :message-id:date:subject:cc:to:from:sender:dkim-signature; bh=MqgvQrvJMR5fN2lKohSbkOm+vXY5jAAsdB8ED0eCMvg=; fh=YwYsb/1ntsV7kUlZ1RPUpaP13Va3UAVOe3iZvsHzRoI=; b=yMNqwLmx3+GzuzweJuceAEDz9LyD+Q+2iNUUvUl7jDs6Oup8ELnrqKFLEckgFaj2ZZ Jx945vk9Y8wzMyVEyY1P8Kj+pqgacO46NhsqzcwPNYlSXxx7Jgqu0zugGEshrK7QFm5v +TEcAe1B0g2qCphGcoCtGP1rVVyDW5Ot6aBAxBuwxUqsHYKAsuvzuI+V0/czsXBCQZHs 4vjNyQ4yEKMEFfujFVYEy6RzwP1AJbfOfGMq6S7Xi9Jcf5pc/oLYKz3bMH6u2yPMTMoc AzK1MSnnhukkKdjYpcV/OXqPqvrVYSXXpfiUzcGAeFMLLLMe/bK+vMwN8BGZtSXSZ9+3 w+zw==; darn=patchwork.ozlabs.org ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@swupdate.org header.s=s1-ionos header.b=P3B7DVML; spf=pass (google.com: domain of stefano.babic@swupdate.org designates 212.227.17.13 as permitted sender) smtp.mailfrom=stefano.babic@swupdate.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20230601; t=1708009833; x=1708614633; darn=patchwork.ozlabs.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:ui-outboundreport:mime-version:message-id:date :subject:cc:to:from:sender:from:to:cc:subject:date:message-id :reply-to; bh=MqgvQrvJMR5fN2lKohSbkOm+vXY5jAAsdB8ED0eCMvg=; b=SewuogXvrRsynYoagLFAGnFUaYZqY7qpXgxPqJSveV5Vdh4Zmvyz2xrHUYevqudQyr 9lMq6sz4yI0077VE4+2Cf0JFm/9wEvFJaGaQshnwfptCxBBuxTy+aSB0chcF8iU1NC0J k03ZuXOJpI122GBs8iwm2AF7CyEgC6hhbcG8iC8D95QrVB8Ufbh7k5HjjqYvvnskK4od dqaDlikI5ajbEO4yi0Yk15sPkyPtI6F59ZsnydzUIl+x1Q/Ns/mHXVvizAwSJ2+B82Yx KmifJh1w93EaUNMXG+3V7zYsO266UEXeumhu8FAoUu+xlcqzixGDBwxqNkTencVDDOs5 l6bQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708009833; x=1708614633; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :x-spam-checked-in-group:list-id:mailing-list:precedence :x-original-authentication-results:x-original-sender :ui-outboundreport:mime-version:message-id:date:subject:cc:to:from :x-beenthere:x-gm-message-state:sender:from:to:cc:subject:date :message-id:reply-to; bh=MqgvQrvJMR5fN2lKohSbkOm+vXY5jAAsdB8ED0eCMvg=; b=b93IiDD7YWfBp0z67cZpO/d+XNLOszef4LKnb90VHpO7JznENiyWuF6ZBKAoQ9sbyP i3oRR6ImCROR7DEi2yIK1LTT6tpTrusQQOpg3zkUULKJ76/NwpJZtnVYjviLjMEnACXp P0M/luHyy/7tCs04OCk4hoTwxKoMaadRtWt0kvsBeqKAfWYZKlLdLNsFjADPk0QRkJ2b V/p2lqw2Ht98FvKrPQkavsuU/uf2dg8t9jjWEFgAFr44PSkwI9UT7z1jZKdJBCV8r6E/ 5KM1ryPImcAgF5O7DvwoiH5HO4N3NExM4USRFn+MOFT3y2hNWeM2eor/ANWvNJtFvYCq SXpQ== Sender: swupdate@googlegroups.com X-Forwarded-Encrypted: i=2; AJvYcCV8UGNu3BF8Muq2tTT9DqOi15ZS30gn/3xSSzSCFx9+CXc9AZkmMGb8HCFzqBRSwB0dGPgqxVNo2HJidSggSFlTDDnZ+UAgJocdm+lGpA== X-Gm-Message-State: AOJu0Yws9LkTdz2AR0nJ/9WfqnktHovsAX05wWMqDnHU2OZpGbVFaT23 dI6DTQg7w8N1qaerAGVrVW21TxrCupZNVpS9LmjtZufFr10obkCg X-Google-Smtp-Source: AGHT+IFAehGmoPV3FZxKPBIbMCuknO2PsKbXLHyQGEoVtE1bKoBXez50WoKC9ToEWmjMDESlr9/njQ== X-Received: by 2002:a05:6512:3d9e:b0:511:61b4:65c1 with SMTP id k30-20020a0565123d9e00b0051161b465c1mr1963913lfv.39.1708009832861; Thu, 15 Feb 2024 07:10:32 -0800 (PST) X-BeenThere: swupdate@googlegroups.com Received: by 2002:a05:6512:3d04:b0:511:79ee:feb4 with SMTP id d4-20020a0565123d0400b0051179eefeb4ls1494032lfv.0.-pod-prod-04-eu; Thu, 15 Feb 2024 07:10:31 -0800 (PST) X-Received: by 2002:a05:6512:3d9e:b0:511:61b4:65c1 with SMTP id k30-20020a0565123d9e00b0051161b465c1mr1963814lfv.39.1708009830627; Thu, 15 Feb 2024 07:10:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1708009830; cv=none; d=google.com; s=arc-20160816; b=OkwjXjS+YgPCymNP4J+xBxAbaREZw24s/FyGlwWwOTZBSeEJh52SGSkKKKFdJZLYpI MhVYIaF4RwhAb0oeW+p4XxK3wRk64yh5KEFh5IPZCU5GXd7TBTWZIa/1c3RY/ftMDtSF b4TgntezgE0r8svgGPPsDULonhRmpwG9UDn4s438S2rD9iMAuAGFu+Bn0RynyBp+wsSu dQ27XL19DpJJ7fiirSmWZqtNEyvifF43xqhNkRDt2R1ccJuNv8tU621GnvxVBhqeKpxZ WV8W65OOMxrosTqiXCq1Vqz6V0dLWHND4rEkHiatFFbSFESnOqne+0C+9Se+/R7vHJMN rGyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=ui-outboundreport:content-transfer-encoding:mime-version:message-id :date:subject:cc:to:from:dkim-signature; bh=Nw5HnpOcqJdCux5GrDbHgfSoZ1qzYaGyahJjMul86HQ=; fh=TiEWcqMcKpHk5s7uErzpntoONrNfOXwKpI5P8bIlggk=; b=nSyigQ+VuafGgBIxFpDK6flUrlSMVRBlzJahVQjtFJD89odibHdRJNerDc38z9LkiJ Ny71U/X4uFEvGtjp0+bsK/WSa5QWonG6R6U0XVww2l+vhmWghJ51nj2jDbVY6S11d7vc huSzqz24PKqpffVxwltmsbvj0CPd29MB1m78Eps8dUJLCwLyy6HXNUOfspyqFrqLGqhg Ng8tnL0Id9oeCfkvy34vmORC4cfAgv3+gGQ73vmZYDvhADrMPrqa8PG/kmDZO6mHDO+D rpz00T1BT3qKDEQkhkrY4XV8wffALcqOj5txPnV3+Hswtj5rMhje2kYOPHtsJTFlG1pg bC8g==; dara=google.com ARC-Authentication-Results: i=1; gmr-mx.google.com; dkim=pass header.i=@swupdate.org header.s=s1-ionos header.b=P3B7DVML; spf=pass (google.com: domain of stefano.babic@swupdate.org designates 212.227.17.13 as permitted sender) smtp.mailfrom=stefano.babic@swupdate.org Received: from mout.kundenserver.de (mout.kundenserver.de. [212.227.17.13]) by gmr-mx.google.com with ESMTPS id b26-20020a0565120b9a00b0050e69030a77si49751lfv.6.2024.02.15.07.10.30 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Feb 2024 07:10:30 -0800 (PST) Received-SPF: pass (google.com: domain of stefano.babic@swupdate.org designates 212.227.17.13 as permitted sender) client-ip=212.227.17.13; X-UI-Sender-Class: 55c96926-9e95-11ee-ae09-1f7a4046a0f6 Received: from paperino.fritz.box ([88.217.136.221]) by mrelayeu.kundenserver.de (mreue108 [213.165.67.113]) with ESMTPSA (Nemesis) id 1MgNpJ-1r2PhC37yJ-00hran; Thu, 15 Feb 2024 16:10:29 +0100 From: Stefano Babic To: swupdate@googlegroups.com Cc: Stefano Babic Subject: [swupdate] [PATCH 1/2] handler: eMMC internal register Date: Thu, 15 Feb 2024 16:10:25 +0100 Message-Id: <20240215151026.115341-1-stefano.babic@swupdate.org> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Provags-ID: V03:K1:/ATwMw0cSCke0JMwPFWxADpVrlAFZBuKt5dmgth21PUgc3SoK6D xILoWACwGpn/y3nZmJsUYFiewi5NuaF7pFngEol/2pS3elje4CEFFhCDCXJjv3kPs+/mtXR bWA/qXgzlPcItoo6cl/UwcwMWhhANhT8+f9deh4dbg1IEj+ql1pLXiI1IdjkrF9rX2+6G0Z ayAm/goBaCR/3CVGvKECg== X-Spam-Flag: NO UI-OutboundReport: notjunk:1;M01:P0:bHd3+gt052U=;QmG5AbB+rEz0dmGrxg10vCEy+UC R6fw9E88f7G6pT/TRpRBMZUSyy6C9GK/Tq9ClJuHbFUZllL9oyzLzDbPFPCED/ow0Rox0hPUS onUIM+i0gl9D4+yFvrkLNhLoV2b7KXq/V1qaHeBkQGSMIJfI8SKO7fqUiBHYldfFylqCLQtzv 03t9rfycUTaQ/Lk/P8/RBh5wg3dIv6KC1ISvbJ/Vpn6KY1ca+VvxR/d2CKVrIrZ6A6wrxbf4O zLSf04BulhOS1Mrk8Sju4cwRihAqCjqeVaT7W63PWtvl8iVuuXPP8W3Ft7RfZkxIr0/Utw1ZG auGDziYc4U25cUTDOtDztWKoHq0wu+EpSjBP4UUrunjs8L6nswDW/hQzQ9+PUFSLNjaXD+Hsd MQGXRNusu1Y7yeP2oqBhume68uSVCGgAzPHcVk7UkZSBBvrgr8K+JPGU3JYxmsrxW+UTcXBU4 xW4dbXtpTDEKccvwqzQ+WsRaF9RjiZzvLJwRjm+O/J+wwsYjijqTKOxpIKa6Y/tqk9GoERcL4 3szz6gS4GSGQtcyYqnTdW1mUIWikE1VCmHndGSY5yx9SFGtmzNLRuOLaNRLO1zW3ivbUUPahK tDfnuIWS9qv8wu75Mqe6bDRu3MuryooDc9bSJFObA+LT7ChYKq4lP281PShsXanS4c8JjC2iu ZVeNadq7LpfTpFjzbgiy8nH7G1/m85GTdPQbbejkCQ6ZQdfzJJHWiJwoSF6WACg4bSsgvS0ob jOMHwg5OadkLPn1EPGhVWtp8HhTPPmLHBKT7FJ7uEBn8umUoF3pEl4= X-Original-Sender: stefano.babic@swupdate.org X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@swupdate.org header.s=s1-ionos header.b=P3B7DVML; spf=pass (google.com: domain of stefano.babic@swupdate.org designates 212.227.17.13 as permitted sender) smtp.mailfrom=stefano.babic@swupdate.org Precedence: list Mailing-list: list swupdate@googlegroups.com; contact swupdate+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: swupdate@googlegroups.com X-Google-Group-Id: 605343134186 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , This adds support for managing hardware functions in eMMC device. First version of the handler supports toggeling of the hardware boot partitions. Signed-off-by: Stefano Babic --- corelib/Makefile | 3 +- corelib/emmc.h | 140 ++++++++++++++++++++++++++++++++++++ corelib/emmc_utils.c | 110 ++++++++++++++++++++++++++++ handlers/Config.in | 11 +++ handlers/Makefile | 1 + handlers/emmc_csd_handler.c | 67 +++++++++++++++++ include/util.h | 4 ++ 7 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 corelib/emmc.h create mode 100644 corelib/emmc_utils.c create mode 100644 handlers/emmc_csd_handler.c -- 2.34.1 diff --git a/corelib/Makefile b/corelib/Makefile index 7e706d87..5917e379 100644 --- a/corelib/Makefile +++ b/corelib/Makefile @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: GPL-2.0-only -lib-y += multipart_parser.o \ +lib-y += emmc_utils.o \ + multipart_parser.o \ parsing_library_libjson.o \ server_utils.o lib-$(CONFIG_DOWNLOAD) += downloader.o diff --git a/corelib/emmc.h b/corelib/emmc.h new file mode 100644 index 00000000..35f8a304 --- /dev/null +++ b/corelib/emmc.h @@ -0,0 +1,140 @@ +/* + * (C) Copyright 2024 + * Stefano Babic, stefano.babic@swupdate.org + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#pragma once + +/* From kernel linux/mmc/mmc.h */ +#define MMC_SEND_EXT_CSD 8 /* adtc R1 */ +#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 */ +#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ + +/* From kernel linux/mmc/core.h */ +#define MMC_RSP_NONE 0 /* no response */ +#define MMC_RSP_PRESENT (1 << 0) +#define MMC_RSP_136 (1 << 1) /* 136 bit response */ +#define MMC_RSP_CRC (1 << 2) /* expect valid crc */ +#define MMC_RSP_BUSY (1 << 3) /* card may send busy */ +#define MMC_RSP_OPCODE (1 << 4) /* response contains opcode */ + +#define MMC_CMD_AC (0 << 5) +#define MMC_CMD_ADTC (1 << 5) +#define MMC_CMD_BC (2 << 5) + +#define MMC_RSP_SPI_S1 (1 << 7) /* one status byte */ +#define MMC_RSP_SPI_BUSY (1 << 10) /* card may send busy */ + +#define MMC_RSP_SPI_R1 (MMC_RSP_SPI_S1) +#define MMC_RSP_SPI_R1B (MMC_RSP_SPI_S1|MMC_RSP_SPI_BUSY) + +#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) +#define MMC_RSP_R1B (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY) + +/* + * EXT_CSD fields + */ +#define EXT_CSD_S_CMD_SET 504 +#define EXT_CSD_HPI_FEATURE 503 +#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */ +#define EXT_CSD_SUPPORTED_MODES 493 /* RO */ +#define EXT_CSD_FFU_FEATURES 492 /* RO */ +#define EXT_CSD_FFU_ARG_3 490 /* RO */ +#define EXT_CSD_FFU_ARG_2 489 /* RO */ +#define EXT_CSD_FFU_ARG_1 488 /* RO */ +#define EXT_CSD_FFU_ARG_0 487 /* RO */ +#define EXT_CSD_CMDQ_DEPTH 307 /* RO */ +#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */ +#define EXT_CSD_NUM_OF_FW_SEC_PROG_3 305 /* RO */ +#define EXT_CSD_NUM_OF_FW_SEC_PROG_2 304 /* RO */ +#define EXT_CSD_NUM_OF_FW_SEC_PROG_1 303 /* RO */ +#define EXT_CSD_NUM_OF_FW_SEC_PROG_0 302 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */ +#define EXT_CSD_PRE_EOL_INFO 267 /* RO */ +#define EXT_CSD_FIRMWARE_VERSION 254 /* RO */ +#define EXT_CSD_CACHE_SIZE_3 252 +#define EXT_CSD_CACHE_SIZE_2 251 +#define EXT_CSD_CACHE_SIZE_1 250 +#define EXT_CSD_CACHE_SIZE_0 249 +#define EXT_CSD_SEC_FEATURE_SUPPORT 231 +#define EXT_CSD_BOOT_INFO 228 /* R/W */ +#define EXT_CSD_BOOT_MULT 226 /* RO */ +#define EXT_CSD_HC_ERASE_GRP_SIZE 224 +#define EXT_CSD_HC_WP_GRP_SIZE 221 +#define EXT_CSD_SEC_COUNT_3 215 +#define EXT_CSD_SEC_COUNT_2 214 +#define EXT_CSD_SEC_COUNT_1 213 +#define EXT_CSD_SEC_COUNT_0 212 +#define EXT_CSD_PART_SWITCH_TIME 199 +#define EXT_CSD_REV 192 +#define EXT_CSD_BOOT_CFG 179 +#define EXT_CSD_PART_CONFIG 179 +#define EXT_CSD_BOOT_BUS_CONDITIONS 177 +#define EXT_CSD_ERASE_GROUP_DEF 175 +#define EXT_CSD_BOOT_WP_STATUS 174 +#define EXT_CSD_BOOT_WP 173 +#define EXT_CSD_USER_WP 171 +#define EXT_CSD_FW_CONFIG 169 /* R/W */ +#define EXT_CSD_WR_REL_SET 167 +#define EXT_CSD_WR_REL_PARAM 166 +#define EXT_CSD_SANITIZE_START 165 +#define EXT_CSD_BKOPS_EN 163 /* R/W */ +#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ +#define EXT_CSD_PARTITIONING_SUPPORT 160 /* RO */ +#define EXT_CSD_MAX_ENH_SIZE_MULT_2 159 +#define EXT_CSD_MAX_ENH_SIZE_MULT_1 158 +#define EXT_CSD_MAX_ENH_SIZE_MULT_0 157 +#define EXT_CSD_PARTITIONS_ATTRIBUTE 156 /* R/W */ +#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ +#define EXT_CSD_GP_SIZE_MULT_4_2 154 +#define EXT_CSD_GP_SIZE_MULT_4_1 153 +#define EXT_CSD_GP_SIZE_MULT_4_0 152 +#define EXT_CSD_GP_SIZE_MULT_3_2 151 +#define EXT_CSD_GP_SIZE_MULT_3_1 150 +#define EXT_CSD_GP_SIZE_MULT_3_0 149 +#define EXT_CSD_GP_SIZE_MULT_2_2 148 +#define EXT_CSD_GP_SIZE_MULT_2_1 147 +#define EXT_CSD_GP_SIZE_MULT_2_0 146 +#define EXT_CSD_GP_SIZE_MULT_1_2 145 +#define EXT_CSD_GP_SIZE_MULT_1_1 144 +#define EXT_CSD_GP_SIZE_MULT_1_0 143 +#define EXT_CSD_ENH_SIZE_MULT_2 142 +#define EXT_CSD_ENH_SIZE_MULT_1 141 +#define EXT_CSD_ENH_SIZE_MULT_0 140 +#define EXT_CSD_ENH_START_ADDR_3 139 +#define EXT_CSD_ENH_START_ADDR_2 138 +#define EXT_CSD_ENH_START_ADDR_1 137 +#define EXT_CSD_ENH_START_ADDR_0 136 +#define EXT_CSD_NATIVE_SECTOR_SIZE 63 /* R */ +#define EXT_CSD_USE_NATIVE_SECTOR 62 /* R/W */ +#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ +#define EXT_CSD_EXT_PARTITIONS_ATTRIBUTE_1 53 +#define EXT_CSD_EXT_PARTITIONS_ATTRIBUTE_0 52 +#define EXT_CSD_CACHE_CTRL 33 +#define EXT_CSD_MODE_CONFIG 30 +#define EXT_CSD_MODE_OPERATION_CODES 29 /* W */ +#define EXT_CSD_FFU_STATUS 26 /* R */ +#define EXT_CSD_SECURE_REMOVAL_TYPE 16 /* R/W */ +#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */ + + +/* + * EXT_CSD field definitions + */ +#define EXT_CSD_CONFIG_SECRM_TYPE (0x30) +#define EXT_CSD_SUPPORTED_SECRM_TYPE (0x0f) +#define EXT_CSD_FFU_INSTALL (0x01) +#define EXT_CSD_FFU_MODE (0x01) +#define EXT_CSD_NORMAL_MODE (0x00) +#define EXT_CSD_FFU (1<<0) +#define EXT_CSD_UPDATE_DISABLE (1<<0) +#define EXT_CSD_HPI_SUPP (1<<0) +#define EXT_CSD_HPI_IMPL (1<<1) +#define EXT_CSD_CMD_SET_NORMAL (1<<0) + + diff --git a/corelib/emmc_utils.c b/corelib/emmc_utils.c new file mode 100644 index 00000000..f12c7867 --- /dev/null +++ b/corelib/emmc_utils.c @@ -0,0 +1,110 @@ +/* + * (C) Copyright 2024 + * Stefano Babic, stefano.babic@swupdate.org + * + * SPDX-License-Identifier: GPL-2.0-only + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "emmc.h" +#include "util.h" + +/* + * Code taken from mmc-utils, mmc_cmds.c + */ +static int emmc_read_extcsd(int fd, __u8 *ext_csd) +{ + int ret = 0; + struct mmc_ioc_cmd idata; + memset(&idata, 0, sizeof(idata)); + memset(ext_csd, 0, sizeof(__u8) * 512); + idata.write_flag = 0; + idata.opcode = MMC_SEND_EXT_CSD; + idata.arg = 0; + idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + idata.blksz = 512; + idata.blocks = 1; + mmc_ioc_cmd_set_data(idata, ext_csd); + + ret = ioctl(fd, MMC_IOC_CMD, &idata); + if (ret) + ERROR("eMMC ioctl return error %d", ret); + + return ret; +} + +static void fill_switch_cmd(struct mmc_ioc_cmd *cmd, __u8 index, __u8 value) +{ + cmd->opcode = MMC_SWITCH; + cmd->write_flag = 1; + cmd->arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | + (value << 8) | EXT_CSD_CMD_SET_NORMAL; + cmd->flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; +} + +static int emmc_write_extcsd_value(int fd, __u8 index, __u8 value, unsigned int timeout_ms) +{ + int ret = 0; + struct mmc_ioc_cmd idata = {}; + + fill_switch_cmd(&idata, index, value); + + /* Kernel will set cmd_timeout_ms if 0 is set */ + idata.cmd_timeout_ms = timeout_ms; + + ret = ioctl(fd, MMC_IOC_CMD, &idata); + if (ret) + ERROR("eMMC ioctl return error %d", ret); + + return ret; +} /* end of imported code */ + +int emmc_get_active_bootpart(int fd) +{ + int ret; + uint8_t extcsd[512]; + int active; + + ret = emmc_read_extcsd(fd, extcsd); + + if (ret) + return -1; + + /* + * Return partition number starting from 0 + * This corresponds to mmcblkXboot0 and mmcblkXboot1 + */ + active = ((extcsd[EXT_CSD_PART_CONFIG] & 0x38) >> 3) - 1; + + return active; +} + +int emmc_write_bootpart(int fd, int bootpart) +{ + uint8_t value; + int ret; + uint8_t extcsd[512]; + + /* + * Do not clear BOOT_ACK + */ + ret = emmc_read_extcsd(fd, extcsd); + value = extcsd[EXT_CSD_PART_CONFIG] & (1 << 6); + + bootpart = ((bootpart + 1) & 0x3) << 3; + value |= bootpart; + + ret = emmc_write_extcsd_value(fd, EXT_CSD_PART_CONFIG, value, 0); + + return ret; +} diff --git a/handlers/Config.in b/handlers/Config.in index b01d033d..ca473646 100644 --- a/handlers/Config.in +++ b/handlers/Config.in @@ -140,6 +140,17 @@ config EMBEDDED_LUA_HANDLER_SOURCE Path to the Lua handler source code file to be embedded into the SWUpdate binary. + +config EMMC_HANDLER + bool "eMMC handler" + default n + help + This handler allows to switch the boot partitions via + the eMMC internal CSD register. One common use case is to + upgrade the bootloader, using the two hardware partitions + with a dual-copy concept. This guarantees that the upgrade + is power-cut safe. + config RAW bool "raw" default n diff --git a/handlers/Makefile b/handlers/Makefile index 24fd487c..12d4aeb8 100644 --- a/handlers/Makefile +++ b/handlers/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_BTRFS_FILESYSTEM) += btrfs_handler.o obj-$(CONFIG_COPY) += copy_handler.o obj-$(CONFIG_CFI) += flash_handler.o obj-$(CONFIG_DELTA) += delta_handler.o delta_downloader.o zchunk_range.o +obj-$(CONFIG_EMMC_HANDLER) += emmc_csd_handler.o obj-$(CONFIG_DISKFORMAT_HANDLER) += diskformat_handler.o obj-$(CONFIG_DISKPART) += diskpart_handler.o obj-$(CONFIG_UNIQUEUUID) += uniqueuuid_handler.o diff --git a/handlers/emmc_csd_handler.c b/handlers/emmc_csd_handler.c new file mode 100644 index 00000000..f71dd1a1 --- /dev/null +++ b/handlers/emmc_csd_handler.c @@ -0,0 +1,67 @@ +/* + * (C) Copyright 2024 + * Stefano Babic, stefano.babic@swupdate.org + * + * SPDX-License-Identifier: GPL-2.0-only + */ +/* + * This handler manages the CSD register accoriding to eMMC + * specifications. Base for this handler are the mmcutils, + * see: + * https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "swupdate_image.h" +#include "handler.h" +#include "util.h" + +void emmc_csd_handler(void); + +static int emmc_boot_toggle(struct img_type *img, void *data) +{ + int active, ret; + struct script_handler_data *script_data = data; + if (script_data->scriptfn == PREINSTALL) + return 0; + + /* Open the device (partition) */ + int fdin = open(img->device, O_RDONLY); + if (fdin < 0) { + ERROR("Failed to open %s: %s", img->device, strerror(errno)); + return -ENODEV; + } + + active = emmc_get_active_bootpart(fdin); + if (active < 0) { + ERROR("Current HW boot partition cannot be retrieved"); + close(fdin); + return -1; + } + + active = (active == 0) ? 1 : 0; + + ret = emmc_write_bootpart(fdin, active); + + if (ret) + ERROR("Failure writing CSD register"); + + close(fdin); + return ret; +} + +__attribute__((constructor)) +void emmc_csd_handler(void) +{ + register_handler("emmc_boot_toggle", emmc_boot_toggle, + SCRIPT_HANDLER | NO_DATA_HANDLER, NULL); +} diff --git a/include/util.h b/include/util.h index 490014e7..e1350633 100644 --- a/include/util.h +++ b/include/util.h @@ -272,3 +272,7 @@ int swupdate_umount(const char *dir); /* Date / Time utilities */ char *swupdate_time_iso8601(struct timeval *tv); + +/* eMMC functions */ +int emmc_write_bootpart(int fd, int bootpart); +int emmc_get_active_bootpart(int fd);