From patchwork Mon Mar 23 16:34:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11453467 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 89E2D159A for ; Mon, 23 Mar 2020 16:36:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 68C9020735 for ; Mon, 23 Mar 2020 16:36:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Ef2iJrYZ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727559AbgCWQfi (ORCPT ); Mon, 23 Mar 2020 12:35:38 -0400 Received: from mail-lj1-f194.google.com ([209.85.208.194]:43043 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727501AbgCWQfh (ORCPT ); Mon, 23 Mar 2020 12:35:37 -0400 Received: by mail-lj1-f194.google.com with SMTP id g27so6507091ljn.10; Mon, 23 Mar 2020 09:35:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/RLSJi41laq14R6Fyebh+5anpy5ZQa7HSMlFcMs1a5Q=; b=Ef2iJrYZ+VqQJlD1zunGiT/ix1DJWcis4iUic1fpS0zjbCF80XLwo0IiyF1Z2/Ntda 78hsveibseERJXNdYfFw9SriyYlwhJ9hB6MGCcV9DTpLVPMUoq9nkgDu084n0yKLbSbn 6K1B2Yd0aS6y7oZasQYkMF9iCfk8vXvkSqfcKbOb+qCabAWwdLn6zm6Im4BI8ZfsyHBV Jh1tx4l7LF0PaaR1JnWkefwDgfl2rGNwF/udhV//n4gWC3qj8YyQ9ANZwCquKSn7HSi/ a0okrLpe11tagutRMVuV5magv8FsvxyFEILlHAYLt/ddsgSyjzaga85S58bWGCk0BZLE RcFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/RLSJi41laq14R6Fyebh+5anpy5ZQa7HSMlFcMs1a5Q=; b=ecgBaFZQ8H4NidVfYYSpQt0WNk3knJ/+a0c0pvqg4FIB5c4qRYMqTjK0fXHnioAFWs 26StF5CPANCYiu2LSBgvbtfw651XpPwh9GUIgg2/rKZlNINHm4K9cek9p7Aaqww12Khb wnKOXKodH41BdmGvTWIz+1H0oS8zrKqQFRIZovo78sVEFGvZGpPTM+prH8Bj/6p1eJxu 7PfYMj7hgHpSSGS6aaiFisVMZN4JNtnOuQJHAgRTeL6OIm3mm47H5X+5HPt2zMxnOl2k wtsnoyq24vHtGYl9PnUsQ1MIXgkVSjo/injF6Gw0KlKbDCSr+SHVh8Koz2CjODK+oiKz RtEg== X-Gm-Message-State: ANhLgQ1ucqbzlaP0/GTofKnGUDrHr1C/58TvXhrvWO8eOC44TbxrBraN 2t3rqv53Lht8nkjlH0gJIJI= X-Google-Smtp-Source: ADFU+vu8aPwBt+XKez2hsewcNmJHhffh+1MzKUMzZ6fo5sv1njcxQEgPBpIYBy3JVQIe8XKAU8uhiA== X-Received: by 2002:a2e:7a0f:: with SMTP id v15mr14770161ljc.156.1584981334413; Mon, 23 Mar 2020 09:35:34 -0700 (PDT) Received: from localhost.localdomain (94-29-39-224.dynamic.spd-mgts.ru. [94.29.39.224]) by smtp.gmail.com with ESMTPSA id m14sm4820017lfo.25.2020.03.23.09.35.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 09:35:33 -0700 (PDT) From: Dmitry Osipenko To: Jens Axboe , Thierry Reding , Jonathan Hunter , =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= , David Heidelberg , Peter Geis , Stephen Warren , Nicolas Chauvet , Ulf Hansson , Adrian Hunter , Billy Laws Cc: linux-tegra@vger.kernel.org, linux-block@vger.kernel.org, Andrey Danin , Gilles Grandou , Ryan Grachek , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 01/10] mmc: core: Add raw_boot_mult field to mmc_ext_csd Date: Mon, 23 Mar 2020 19:34:22 +0300 Message-Id: <20200323163431.7678-2-digetx@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200323163431.7678-1-digetx@gmail.com> References: <20200323163431.7678-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org In order to support parsing of NVIDIA Tegra Partition Table format, we need to know the BOOT_SIZE_MULT value of the Extended CSD register because NVIDIA's bootloader linearizes the boot0/boot1/main partitions into a single virtual space, and thus, all partition addresses are shifted by the size of boot0 + boot1 partitions. Signed-off-by: Dmitry Osipenko --- drivers/mmc/core/mmc.c | 2 ++ include/linux/mmc/card.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index de94fbe629bd..4b7261fbc332 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -417,6 +417,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; card->ext_csd.raw_hc_erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; + card->ext_csd.raw_boot_mult = + ext_csd[EXT_CSD_BOOT_MULT]; if (card->ext_csd.rev >= 3) { u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT]; card->ext_csd.part_config = ext_csd[EXT_CSD_PART_CONFIG]; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index cf3780a6ccc4..90b1d83ce675 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -108,6 +108,7 @@ struct mmc_ext_csd { u8 raw_hc_erase_gap_size; /* 221 */ u8 raw_erase_timeout_mult; /* 223 */ u8 raw_hc_erase_grp_size; /* 224 */ + u8 raw_boot_mult; /* 226 */ u8 raw_sec_trim_mult; /* 229 */ u8 raw_sec_erase_mult; /* 230 */ u8 raw_sec_feature_support;/* 231 */ From patchwork Mon Mar 23 16:34:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11453463 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EA4826CA for ; Mon, 23 Mar 2020 16:36:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C68B520722 for ; Mon, 23 Mar 2020 16:36:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="tIuzq/gr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727581AbgCWQfj (ORCPT ); Mon, 23 Mar 2020 12:35:39 -0400 Received: from mail-lf1-f66.google.com ([209.85.167.66]:45931 "EHLO mail-lf1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727507AbgCWQfi (ORCPT ); Mon, 23 Mar 2020 12:35:38 -0400 Received: by mail-lf1-f66.google.com with SMTP id v4so7067600lfo.12; Mon, 23 Mar 2020 09:35:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=kWAeNpBn6fpU/PQ3w5gvOGDJx2Ia8b1U9luMqpJSJvQ=; b=tIuzq/gr6LMfw5IhTrkX52zxdsdrWBcVd++BnjQqbifbF/uTfnv3vU/uWT5GolNcGv fzIP6Xj8xKWfGM/c7axoGJBIG2hJJUV3PdBR/SamU9FuWO25HSXAOxPI6xDcHtUIdjS1 F6uLuPUQuP7b+zPugUhBWFGus7uAhAp1Iac4T7BpEU1Fngb/fuyE+C6YTXyRVDcdJYQQ Jv2pU5fKWmWJa4dFyDBdf3k5GR+b+KVG2V4n6iSyvYsGtZNXm1sJxmdTUSZu5cMgQPVv N7EjQhHhyBKZYKEiQ8gvUfdQnle1abEBG6SW5xmv6PS/7VLg68ZHaHlqADSpB+rHxfOD ufBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=kWAeNpBn6fpU/PQ3w5gvOGDJx2Ia8b1U9luMqpJSJvQ=; b=H7Ey5JYaizluCPShEZyGSeWE5pX/vYDbmOYIkaFgZ1vVOwCR6dk1GqbXrWLhBrhW2Y 8z575xNx2ywJoHNtk9/O0oPNDgXR0/fEzBv7NdPo85OXE91ewwhLjlQrgZZ8UuFw65ib FJH+A/PHhr+qSIrMXBwNmqmxlUYbxLddu+FZsvGXqEreZgn6kJzmbK7M+BItkUMf2opj OoPb4ukR+EMo0VdpDzYE7dKqGlazabOrDnB2pAFoU0dpB3/FdTphx4ZSeKeWh0eYnpFc 6ICae/LYsEHLEQvAvjOF6XZNXsk7CJ5dELGxm0GqqdixQYMF15BimtynN5bz5gljkkFk luzw== X-Gm-Message-State: ANhLgQ0M4RMYeifgfD+xhL0V+tWMO49Ro0XxFRLe0ErLKn89vcYTGNV5 cPKmdvOC8f4xYs3EA4XscLsTgnSu X-Google-Smtp-Source: ADFU+vuS8o+ndODomWoUKADlFVTMveigNiAwppJWlBrao3k3C+IGzWVzvm8Hl+ovIgarsZgVtWqVAA== X-Received: by 2002:ac2:4c33:: with SMTP id u19mr13431354lfq.195.1584981335547; Mon, 23 Mar 2020 09:35:35 -0700 (PDT) Received: from localhost.localdomain (94-29-39-224.dynamic.spd-mgts.ru. [94.29.39.224]) by smtp.gmail.com with ESMTPSA id m14sm4820017lfo.25.2020.03.23.09.35.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 09:35:35 -0700 (PDT) From: Dmitry Osipenko To: Jens Axboe , Thierry Reding , Jonathan Hunter , =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= , David Heidelberg , Peter Geis , Stephen Warren , Nicolas Chauvet , Ulf Hansson , Adrian Hunter , Billy Laws Cc: linux-tegra@vger.kernel.org, linux-block@vger.kernel.org, Andrey Danin , Gilles Grandou , Ryan Grachek , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 02/10] mmc: block: Add mmc_bdev_to_card() helper Date: Mon, 23 Mar 2020 19:34:23 +0300 Message-Id: <20200323163431.7678-3-digetx@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200323163431.7678-1-digetx@gmail.com> References: <20200323163431.7678-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org NVIDIA Tegra Partition Table takes into account MMC card's BOOT_SIZE_MULT parameter, and thus, the partition parser needs to retrieve that EXT_CSD value from the block device. There are also some other parts of struct mmc_card that are needed for the partition parser in order to calculate the eMMC offset and verify different things. This patch introduces new helper which takes block device for the input argument and returns the corresponding MMC card. Signed-off-by: Dmitry Osipenko --- drivers/mmc/core/block.c | 15 +++++++++++++++ include/linux/mmc/blkdev.h | 13 +++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 include/linux/mmc/blkdev.h diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 7634894df853..36d84a8e182c 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -306,6 +307,20 @@ static ssize_t force_ro_store(struct device *dev, struct device_attribute *attr, return ret; } +struct mmc_card *mmc_bdev_to_card(struct block_device *bdev) +{ + struct mmc_blk_data *md; + + if (bdev->bd_disk->major != MMC_BLOCK_MAJOR) + return NULL; + + md = mmc_blk_get(bdev->bd_disk); + if (!md) + return NULL; + + return md->queue.card; +} + static int mmc_blk_open(struct block_device *bdev, fmode_t mode) { struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); diff --git a/include/linux/mmc/blkdev.h b/include/linux/mmc/blkdev.h new file mode 100644 index 000000000000..67608c58de70 --- /dev/null +++ b/include/linux/mmc/blkdev.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * linux/include/linux/mmc/blkdev.h + */ +#ifndef LINUX_MMC_BLOCK_DEVICE_H +#define LINUX_MMC_BLOCK_DEVICE_H + +struct block_device; +struct mmc_card; + +struct mmc_card *mmc_bdev_to_card(struct block_device *bdev); + +#endif /* LINUX_MMC_BLOCK_DEVICE_H */ From patchwork Mon Mar 23 16:34:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11453451 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9375E15AB for ; Mon, 23 Mar 2020 16:36:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5F6AE2077D for ; Mon, 23 Mar 2020 16:36:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gk+Vyj1R" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727663AbgCWQfo (ORCPT ); Mon, 23 Mar 2020 12:35:44 -0400 Received: from mail-lf1-f67.google.com ([209.85.167.67]:33674 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727627AbgCWQfn (ORCPT ); Mon, 23 Mar 2020 12:35:43 -0400 Received: by mail-lf1-f67.google.com with SMTP id c20so10785356lfb.0; Mon, 23 Mar 2020 09:35:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=RILIObRT9JS8XulPHlWPQ9vH/RJe3I5zeLXUMy0kxJ0=; b=gk+Vyj1R1kxyD1ehldnOTxnUwn+nfjwX8TCNqq2SOhwe1lJxBWDi5DMYIXC/WnCQuJ exFhGyZUEMvgx5s7hFOiA8mUx3Rv2ndbdgp1cKEpmEJyVwYg3S2oPNp9nF0i14jH89Ik dPmeHleYDYBgm0D3mLbCDwgAmh+pclqSEuBfPyQh8LBsueq6LKQsgF06CatciEjKX1WR s6Morkix+lY4BHl+rJ+J64uylKZmwGsHu02MhW4XA3S19GhlUBag/zrNVvGcSg5H3tsi 5WxPAWQjeF9Z5BQbu2ztVEzYh5iU52mICiDi52Ztg1blULPoIP7UNrGJ5jkBOGF1p9LB FMYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=RILIObRT9JS8XulPHlWPQ9vH/RJe3I5zeLXUMy0kxJ0=; b=C8B3Wbr3hqoIW9zJC+J2BPKXNf4RkByS5fXuHSHYpiVi7ck4UIgSlJao5A0SIxIkrC AhCh3chCWHxrH+/7Ml9tLYv1NCFzK7rwMZgvsvH+WxK/vxTQ/odVMerj6/mSCVbv/D+7 lyIrIZ7yS28DgvaZk+hOTZYwFeXAXz2RLThIM3Q3xkPSX03RtxVyatlXzElF99mZuiBC Y5c3Ob/D0pRTXGxwz5xo2oJnfWQDqR2x4oOMwj7ZFo7D4fGaf+liyZZDEPbp+c25JBTC BgA+eFCj9GSiZ0Kl+GX0RLTdX/xLCBDARzIT3hIq+9+PEOESX693MeySW8kQySAZc6NL ymGQ== X-Gm-Message-State: ANhLgQ2D+sCRNmsKqremRWe7+Ku39ln2IKIJr29f10lhaeSN4aYEVqZ0 lJpbw0v19rLcsE07CydqbiM= X-Google-Smtp-Source: ADFU+vv8Jkwt6S4BvRYnbtskRc4pkAFOtNKOvIA51gHCMmcjbaJVPAStXaS0SIj8dYEHhBdOTh0tJg== X-Received: by 2002:a19:660a:: with SMTP id a10mr13723651lfc.9.1584981336899; Mon, 23 Mar 2020 09:35:36 -0700 (PDT) Received: from localhost.localdomain (94-29-39-224.dynamic.spd-mgts.ru. [94.29.39.224]) by smtp.gmail.com with ESMTPSA id m14sm4820017lfo.25.2020.03.23.09.35.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 09:35:36 -0700 (PDT) From: Dmitry Osipenko To: Jens Axboe , Thierry Reding , Jonathan Hunter , =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= , David Heidelberg , Peter Geis , Stephen Warren , Nicolas Chauvet , Ulf Hansson , Adrian Hunter , Billy Laws Cc: linux-tegra@vger.kernel.org, linux-block@vger.kernel.org, Andrey Danin , Gilles Grandou , Ryan Grachek , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table Date: Mon, 23 Mar 2020 19:34:24 +0300 Message-Id: <20200323163431.7678-4-digetx@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200323163431.7678-1-digetx@gmail.com> References: <20200323163431.7678-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org All NVIDIA Tegra devices use a special partition table format for the internal storage partitioning. Most of Tegra devices have GPT partition in addition to TegraPT, but some older Android consumer-grade devices do not or GPT is placed in a wrong sector, and thus, the TegraPT is needed in order to support these devices properly in the upstream kernel. This patch adds support for NVIDIA Tegra Partition Table format that is used at least by all NVIDIA Tegra20 and Tegra30 devices. Signed-off-by: Dmitry Osipenko --- arch/arm/mach-tegra/tegra.c | 54 ++++ block/partitions/Kconfig | 10 + block/partitions/Makefile | 1 + block/partitions/check.c | 4 + block/partitions/tegra.c | 512 ++++++++++++++++++++++++++++++++++ block/partitions/tegra.h | 8 + include/soc/tegra/bootdata.h | 46 +++ include/soc/tegra/common.h | 9 + include/soc/tegra/partition.h | 91 ++++++ 9 files changed, 735 insertions(+) create mode 100644 block/partitions/tegra.c create mode 100644 block/partitions/tegra.h create mode 100644 include/soc/tegra/bootdata.h create mode 100644 include/soc/tegra/partition.h diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 3882a6c66969..9236819c5a2f 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -28,7 +28,9 @@ #include +#include #include +#include #include #include @@ -62,9 +64,61 @@ u32 tegra_uart_config[3] = { 0, }; +static void __init tegra_boot_config_table_init(void) +{ + struct tegra30_boot_config_table __iomem *t30_bct; + struct tegra20_boot_config_table __iomem *t20_bct; + struct tegra20_boot_info_table __iomem *t20_bit; + u32 iram_end = TEGRA_IRAM_BASE + TEGRA_IRAM_SIZE; + u32 iram_start = TEGRA_IRAM_BASE; + u32 pt_addr, pt_size, bct_size; + + t20_bit = IO_ADDRESS(TEGRA_IRAM_BASE); + + if (of_machine_is_compatible("nvidia,tegra20")) { + bct_size = sizeof(*t20_bct); + + if (t20_bit->bct_size != bct_size || + t20_bit->bct_ptr < iram_start || + t20_bit->bct_ptr > iram_end - bct_size) + return; + + t20_bct = IO_ADDRESS(t20_bit->bct_ptr); + + if (t20_bct->boot_data_version != TEGRA_BOOTDATA_VERSION_T20) + return; + + pt_addr = t20_bct->partition_table_logical_sector_address; + pt_size = t20_bct->partition_table_num_logical_sectors; + + } else if (of_machine_is_compatible("nvidia,tegra30")) { + bct_size = sizeof(*t30_bct); + + if (t20_bit->bct_size != bct_size || + t20_bit->bct_ptr < iram_start || + t20_bit->bct_ptr > iram_end - bct_size) + return; + + t30_bct = IO_ADDRESS(t20_bit->bct_ptr); + + if (t30_bct->boot_data_version != TEGRA_BOOTDATA_VERSION_T30) + return; + + pt_addr = t30_bct->partition_table_logical_sector_address; + pt_size = t30_bct->partition_table_num_logical_sectors; + } else { + return; + } + + pr_info("%s: BCT found in IRAM\n", __func__); + + tegra_partition_table_setup(pt_addr, pt_size); +} + static void __init tegra_init_early(void) { of_register_trusted_foundations(); + tegra_boot_config_table_init(); tegra_cpu_reset_handler_init(); call_firmware_op(l2x0_init); } diff --git a/block/partitions/Kconfig b/block/partitions/Kconfig index 702689a628f0..2e38fde39b9c 100644 --- a/block/partitions/Kconfig +++ b/block/partitions/Kconfig @@ -268,3 +268,13 @@ config CMDLINE_PARTITION help Say Y here if you want to read the partition table from bootargs. The format for the command line is just like mtdparts. + +config TEGRA_PARTITION + bool "NVIDIA Tegra Partition support" if PARTITION_ADVANCED + default y if ARCH_TEGRA + depends on ARCH_TEGRA || COMPILE_TEST + depends on MMC + select MMC_BLOCK + help + Say Y here if you would like to be able to read the hard disk + partition table format used by NVIDIA Tegra machines. diff --git a/block/partitions/Makefile b/block/partitions/Makefile index 2f276b677c81..807319883a18 100644 --- a/block/partitions/Makefile +++ b/block/partitions/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_IBM_PARTITION) += ibm.o obj-$(CONFIG_EFI_PARTITION) += efi.o obj-$(CONFIG_KARMA_PARTITION) += karma.o obj-$(CONFIG_SYSV68_PARTITION) += sysv68.o +obj-$(CONFIG_TEGRA_PARTITION) += tegra.o diff --git a/block/partitions/check.c b/block/partitions/check.c index ffe408fead0c..91268773b6ce 100644 --- a/block/partitions/check.c +++ b/block/partitions/check.c @@ -36,6 +36,7 @@ #include "karma.h" #include "sysv68.h" #include "cmdline.h" +#include "tegra.h" int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/ @@ -108,6 +109,9 @@ static int (*check_part[])(struct parsed_partitions *) = { #endif #ifdef CONFIG_SYSV68_PARTITION sysv68_partition, +#endif +#ifdef CONFIG_TEGRA_PARTITION + tegra_partition, #endif NULL }; diff --git a/block/partitions/tegra.c b/block/partitions/tegra.c new file mode 100644 index 000000000000..4cb8064bf458 --- /dev/null +++ b/block/partitions/tegra.c @@ -0,0 +1,512 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NVIDIA Tegra Partition Table + * + * Copyright (C) 2020 GRATE-DRIVER project + * Copyright (C) 2020 Dmitry Osipenko + * + * Credits for the partition table format: + * + * Andrey Danin (Toshiba AC100 TegraPT format) + * Gilles Grandou (Toshiba AC100 TegraPT format) + * Ryan Grachek (Google TV "Molly" TegraPT format) + * Stephen Warren (Useful suggestions about eMMC/etc) + */ + +#define pr_fmt(fmt) "tegra-partition: " fmt + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "check.h" +#include "tegra.h" + +#define TEGRA_PT_SECTOR_SZ (TEGRA_PT_LOGICAL_SECTOR_SIZE / SECTOR_SIZE) +#define TEGRA_PT_SECTOR(s) (TEGRA_PT_SECTOR_SZ * (s)) + +#define TEGRA_PT_INFO(ptp, fmt, ...) \ + pr_info("%s: " fmt, \ + (ptp)->state->bdev->bd_disk->disk_name, ##__VA_ARGS__) + +#define TEGRA_PT_ERR(ptp, fmt, ...) \ + pr_err("%s: " fmt, \ + (ptp)->state->bdev->bd_disk->disk_name, ##__VA_ARGS__) + +#define TEGRA_PT_PARSE_ERR(ptp, fmt, ...) \ + TEGRA_PT_ERR(ptp, "sector %llu: invalid " fmt, \ + (ptp)->sector, ##__VA_ARGS__) + +struct tegra_partition_table_parser { + struct tegra_partition_table *pt; + struct parsed_partitions *state; + bool pt_entry_checked; + sector_t sector; + int boot_offset; + u32 dev_instance; + u32 dev_id; +}; + +union tegra_partition_table_u { + struct tegra_partition_table pt; + u8 pt_parts[TEGRA_PT_SECTOR_SZ][SECTOR_SIZE]; +}; + +struct tegra_partition_type { + unsigned int type; + char *name; +}; + +static sector_t tegra_pt_sector_address; +static sector_t tegra_pt_sectors_num; + +void tegra_partition_table_setup(sector_t logical_sector_address, + sector_t logical_sectors_num) +{ + tegra_pt_sector_address = TEGRA_PT_SECTOR(logical_sector_address); + tegra_pt_sectors_num = TEGRA_PT_SECTOR(logical_sectors_num); + + pr_info("initialized to sector = %llu sectors_num = %llu\n", + tegra_pt_sector_address, tegra_pt_sectors_num); +} + +/* + * Some partitions are very sensitive, changing data on them may brick device. + * + * For more details about partitions see: + * + * "https://docs.nvidia.com/jetson/l4t/Tegra Linux Driver Package Development Guide/part_config.html" + */ +static const char * const partitions_blacklist[] = { + "BCT", "EBT", "EKS", "GP1", "GPT", "MBR", "PT", +}; + +static bool tegra_partition_name_match(struct tegra_partition *p, + const char *name) +{ + return !strncmp(p->partition_name, name, TEGRA_PT_NAME_SIZE); +} + +static bool tegra_partition_skip(struct tegra_partition *p, + struct tegra_partition_table_parser *ptp, + sector_t sector) +{ + unsigned int i; + + /* skip eMMC boot partitions */ + if (sector < ptp->boot_offset) + return true; + + for (i = 0; i < ARRAY_SIZE(partitions_blacklist); i++) { + if (tegra_partition_name_match(p, partitions_blacklist[i])) + return true; + } + + return false; +} + +static const struct tegra_partition_type tegra_partition_expected_types[] = { + { .type = TEGRA_PT_PART_TYPE_BCT, .name = "BCT", }, + { .type = TEGRA_PT_PART_TYPE_EBT, .name = "EBT", }, + { .type = TEGRA_PT_PART_TYPE_PT, .name = "PT", }, + { .type = TEGRA_PT_PART_TYPE_GP1, .name = "GP1", }, + { .type = TEGRA_PT_PART_TYPE_GPT, .name = "GPT", }, + { .type = TEGRA_PT_PART_TYPE_GENERIC, .name = NULL, }, +}; + +static int tegra_partition_type_valid(struct tegra_partition_table_parser *ptp, + struct tegra_partition *p) +{ + const struct tegra_partition_type *ptype; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(tegra_partition_expected_types); i++) { + ptype = &tegra_partition_expected_types[i]; + + if (ptype->name && !tegra_partition_name_match(p, ptype->name)) + continue; + + if (p->part_info.partition_type == ptype->type) + return 0; + + /* + * Unsure about all possible types, let's emit error and + * allow to continue for now. + */ + if (!ptype->name) + return 1; + } + + return -1; +} + +static bool tegra_partition_valid(struct tegra_partition_table_parser *ptp, + struct tegra_partition *p, + struct tegra_partition *prev, + sector_t sector, + sector_t size) +{ + struct tegra_partition_info *prev_pi = &prev->part_info; + sector_t sect_end = TEGRA_PT_SECTOR(prev_pi->logical_sector_address + + prev_pi->logical_sectors_num); + char *type, name[2][TEGRA_PT_NAME_SIZE + 1]; + int err; + + strscpy(name[0], p->partition_name, sizeof(name[0])); + strscpy(name[1], prev->partition_name, sizeof(name[1])); + + /* validate expected partition name/type */ + err = tegra_partition_type_valid(ptp, p); + if (err) { + TEGRA_PT_PARSE_ERR(ptp, "partition_type: [%s] partition_type=%u\n", + name[0], p->part_info.partition_type); + if (err < 0) + return false; + } + + /* validate partition table BCT addresses */ + if (tegra_partition_name_match(p, "PT")) { + if (sector != tegra_pt_sector_address && + size != tegra_pt_sectors_num) { + TEGRA_PT_PARSE_ERR(ptp, "PT location: sector=%llu size=%llu\n", + sector, size); + return false; + } + + if (ptp->pt_entry_checked) { + TEGRA_PT_PARSE_ERR(ptp, "(duplicated) PT\n"); + return false; + } + + ptp->pt_entry_checked = true; + } + + if (sector + size < sector) { + TEGRA_PT_PARSE_ERR(ptp, "size: [%s] integer overflow sector=%llu size=%llu\n", + name[0], sector, size); + return false; + } + + /* validate allocation_policy=sequential (absolute unsupported) */ + if (p != prev && sect_end > sector) { + TEGRA_PT_PARSE_ERR(ptp, "allocation_policy: [%s] end=%llu [%s] sector=%llu size=%llu\n", + name[1], sect_end, name[0], sector, size); + return false; + } + + if (ptp->dev_instance != p->mount_info.device_instance) { + TEGRA_PT_PARSE_ERR(ptp, "device_instance: [%s] device_instance=%u|%u\n", + name[0], ptp->dev_instance, + p->mount_info.device_instance); + return false; + } + + if (ptp->dev_id != p->mount_info.device_id) { + TEGRA_PT_PARSE_ERR(ptp, "device_id: [%s] device_id=%u|%u\n", + name[0], ptp->dev_id, + p->mount_info.device_id); + return false; + } + + if (p->partition_id > 127) { + TEGRA_PT_PARSE_ERR(ptp, "partition_id: [%s] partition_id=%u\n", + name[0], p->partition_id); + return false; + } + + sect_end = get_capacity(ptp->state->bdev->bd_disk); + + /* eMMC boot partitions are below ptp->boot_offset */ + if (sector < ptp->boot_offset) { + sect_end += ptp->boot_offset; + type = "boot"; + } else { + sector -= ptp->boot_offset; + type = "main"; + } + + /* validate size */ + if (!size || sector + size > sect_end) { + TEGRA_PT_PARSE_ERR(ptp, "size: [%s] %s partition boot_offt=%d end=%llu sector=%llu size=%llu\n", + name[0], type, ptp->boot_offset, sect_end, + sector, size); + return false; + } + + return true; +} + +static bool tegra_partitions_parse(struct tegra_partition_table_parser *ptp, + bool check_only) +{ + struct parsed_partitions *state = ptp->state; + struct tegra_partition_table *pt = ptp->pt; + sector_t sector, size; + int i, slot = 1; + + ptp->pt_entry_checked = false; + + for (i = 0; i < pt->secure.num_partitions; i++) { + struct tegra_partition *p = &pt->partitions[i]; + struct tegra_partition *prev = &pt->partitions[max(i - 1, 0)]; + struct tegra_partition_info *pi = &p->part_info; + + if (slot == state->limit && !check_only) + break; + + sector = TEGRA_PT_SECTOR(pi->logical_sector_address); + size = TEGRA_PT_SECTOR(pi->logical_sectors_num); + + if (!tegra_partition_valid(ptp, p, prev, sector, size)) + return false; + + if (check_only || + tegra_partition_skip(p, ptp, sector)) + continue; + + put_partition(state, slot++, sector - ptp->boot_offset, size); + } + + if (!ptp->pt_entry_checked) { + TEGRA_PT_PARSE_ERR(ptp, "PT: table entry not found\n"); + return false; + } + + return true; +} + +static bool +tegra_partition_table_parsed(struct tegra_partition_table_parser *ptp) +{ + if (ptp->pt->secure.num_partitions == 0 || + ptp->pt->secure.num_partitions > TEGRA_PT_MAX_PARTITIONS) { + TEGRA_PT_PARSE_ERR(ptp, "num_partitions=%u\n", + ptp->pt->secure.num_partitions); + return false; + } + + return tegra_partitions_parse(ptp, true) && + tegra_partitions_parse(ptp, false); +} + +static int +tegra_partition_table_insec_hdr_valid(struct tegra_partition_table_parser *ptp) +{ + if (ptp->pt->insecure.magic != TEGRA_PT_MAGIC || + ptp->pt->insecure.version != TEGRA_PT_VERSION) { + TEGRA_PT_PARSE_ERR(ptp, "insecure header: magic=0x%llx ver=0x%x\n", + ptp->pt->insecure.magic, + ptp->pt->insecure.version); + return 0; + } + + return 1; +} + +static int +tegra_partition_table_sec_hdr_valid(struct tegra_partition_table_parser *ptp) +{ + size_t pt_size = ptp->pt->secure.num_partitions; + + pt_size *= sizeof(ptp->pt->partitions[0]); + pt_size += TEGRA_PT_HEADER_SZ; + + if (ptp->pt->secure.magic != TEGRA_PT_MAGIC || + ptp->pt->secure.version != TEGRA_PT_VERSION || + ptp->pt->secure.length != ptp->pt->insecure.length || + ptp->pt->secure.length < pt_size) { + TEGRA_PT_PARSE_ERR(ptp, "secure header: magic=0x%llx ver=0x%x length=%u|%u|%zu\n", + ptp->pt->secure.magic, + ptp->pt->secure.version, + ptp->pt->secure.length, + ptp->pt->insecure.length, + pt_size); + return 0; + } + + return 1; +} + +static int +tegra_partition_table_unencrypted(struct tegra_partition_table_parser *ptp) +{ + /* AES IV, all zeros if unencrypted */ + if (ptp->pt->secure.random_data[0] || ptp->pt->secure.random_data[1] || + ptp->pt->secure.random_data[2] || ptp->pt->secure.random_data[3]) { + pr_err_once("encrypted partition table unsupported\n"); + return 0; + } + + return 1; +} + +static const u32 tegra20_sdhci_bases[TEGRA_PT_SDHCI_DEVICE_INSTANCES] = { + 0xc8000000, 0xc8000200, 0xc8000400, 0xc8000600, +}; + +static const u32 tegra30_sdhci_bases[TEGRA_PT_SDHCI_DEVICE_INSTANCES] = { + 0x78000000, 0x78000200, 0x78000400, 0x78000600, +}; + +static const struct of_device_id tegra_sdhci_match[] = { + { .compatible = "nvidia,tegra20-sdhci", .data = tegra20_sdhci_bases, }, + { .compatible = "nvidia,tegra30-sdhci", .data = tegra30_sdhci_bases, }, + {} +}; + +static int +tegra_partition_table_emmc_boot_offset(struct tegra_partition_table_parser *ptp) +{ + struct mmc_card *card = mmc_bdev_to_card(ptp->state->bdev); + const struct of_device_id *matched; + const u32 *sdhci_bases; + u32 sdhci_base; + unsigned int i; + int err; + + /* filter out unexpected/untested boot sources */ + if (!card || card->ext_csd.rev < 3 || + !mmc_card_is_blockaddr(card) || + mmc_card_is_removable(card->host)) + return -1; + + /* skip everything unrelated to Tegra eMMC */ + matched = of_match_node(tegra_sdhci_match, card->host->parent->of_node); + if (!matched) + return -1; + + sdhci_bases = matched->data; + + /* figure out SDHCI instance ID by the base address */ + err = of_property_read_u32_index(card->host->parent->of_node, + "reg", 0, &sdhci_base); + if (err) + return -1; + + for (i = 0; i < TEGRA_PT_SDHCI_DEVICE_INSTANCES; i++) { + if (sdhci_base == sdhci_bases[i]) + break; + } + + if (i == TEGRA_PT_SDHCI_DEVICE_INSTANCES) + return -1; + + ptp->dev_id = TEGRA_PT_SDHCI_DEVICE_ID; + ptp->dev_instance = i; + + /* + * eMMC storage has two special boot partitions in addition to the + * main one. NVIDIA's bootloader linearizes eMMC boot0->boot1->main + * accesses, this means that the partition table addresses are shifted + * by the size of boot partitions. In accordance with the eMMC + * specification, the boot partition size is calculated as follows: + * + * boot partition size = 128K byte x BOOT_SIZE_MULT + * + * This function returns number of sectors occupied by the both boot + * partitions. + */ + return card->ext_csd.raw_boot_mult * SZ_128K / + SECTOR_SIZE * MMC_NUM_BOOT_PARTITION; +} + +static int tegra_read_partition_table(struct tegra_partition_table_parser *ptp) +{ + union tegra_partition_table_u *ptu = (typeof(ptu))ptp->pt; + unsigned int i; + Sector sect; + void *part; + + for (i = 0; i < ARRAY_SIZE(ptu->pt_parts); i++) { + /* + * Partition table takes at maximum 4096 bytes, but + * read_part_sector() guarantees only that SECTOR_SIZE will + * be read at minimum. + */ + part = read_part_sector(ptp->state, ptp->sector + i, §); + if (!part) { + TEGRA_PT_ERR(ptp, "failed to read sector %llu\n", + ptp->sector + i); + return 0; + } + + memcpy(ptu->pt_parts[i], part, SECTOR_SIZE); + put_dev_sector(sect); + } + + return 1; +} + +int tegra_partition(struct parsed_partitions *state) +{ + struct tegra_partition_table_parser ptp = {}; + sector_t end_sector; + int ret = 0; + + if (!soc_is_tegra()) + return 0; + + ptp.state = state; + + ptp.boot_offset = tegra_partition_table_emmc_boot_offset(&ptp); + if (ptp.boot_offset < 0) + return 0; + + if (tegra_pt_sector_address < ptp.boot_offset) { + TEGRA_PT_INFO(&ptp, + "scanning eMMC boot partitions unimplemented\n"); + return 0; + } + + ptp.pt = kmalloc(TEGRA_PT_LOGICAL_SECTOR_SIZE, GFP_KERNEL); + if (!ptp.pt) + return 0; + + ptp.sector = tegra_pt_sector_address - ptp.boot_offset; + end_sector = ptp.sector + tegra_pt_sectors_num; + + /* + * Partition table is duplicated till the end_sector. + * If first table is corrupted, we will try next. + */ + while (ptp.sector < end_sector) { + ret = tegra_read_partition_table(&ptp); + if (!ret) + goto next_sector; + + ret = tegra_partition_table_insec_hdr_valid(&ptp); + if (!ret) + goto next_sector; + + ret = tegra_partition_table_unencrypted(&ptp); + if (!ret) + goto next_sector; + + ret = tegra_partition_table_sec_hdr_valid(&ptp); + if (!ret) + goto next_sector; + + ret = tegra_partition_table_parsed(&ptp); + if (ret) + break; +next_sector: + ptp.sector += TEGRA_PT_SECTOR_SZ; + } + + if (ret == 1) + strlcat(state->pp_buf, "\n", PAGE_SIZE); + + kfree(ptp.pt); + + return ret; +} diff --git a/block/partitions/tegra.h b/block/partitions/tegra.h new file mode 100644 index 000000000000..cd1fe0b3a4a1 --- /dev/null +++ b/block/partitions/tegra.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __FS_PART_TEGRA_H__ +#define __FS_PART_TEGRA_H__ + +int tegra_partition(struct parsed_partitions *state); + +#endif /* __FS_PART_TEGRA_H__ */ diff --git a/include/soc/tegra/bootdata.h b/include/soc/tegra/bootdata.h new file mode 100644 index 000000000000..7be207cb2519 --- /dev/null +++ b/include/soc/tegra/bootdata.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_TEGRA_BOOTDATA_H__ +#define __SOC_TEGRA_BOOTDATA_H__ + +#include +#include + +#define TEGRA_BOOTDATA_VERSION_T20 NVBOOT_BOOTDATA_VERSION(0x2, 0x1) +#define TEGRA_BOOTDATA_VERSION_T30 NVBOOT_BOOTDATA_VERSION(0x3, 0x1) + +#define NVBOOT_BOOTDATA_VERSION(a, b) ((((a) & 0xffff) << 16) | \ + ((b) & 0xffff)) +#define NVBOOT_CMAC_AES_HASH_LENGTH 4 + +struct tegra20_boot_info_table { + u32 unused_data1[14]; + u32 bct_size; + u32 bct_ptr; +} __packed; + +struct tegra20_boot_config_table { + u32 crypto_hash[NVBOOT_CMAC_AES_HASH_LENGTH]; + u32 random_aes_blk[NVBOOT_CMAC_AES_HASH_LENGTH]; + u32 boot_data_version; + u32 unused_data1[712]; + u32 unused_consumer_data1; + u16 partition_table_logical_sector_address; + u16 partition_table_num_logical_sectors; + u32 unused_consumer_data[294]; + u32 unused_data[3]; +} __packed; + +struct tegra30_boot_config_table { + u32 crypto_hash[NVBOOT_CMAC_AES_HASH_LENGTH]; + u32 random_aes_blk[NVBOOT_CMAC_AES_HASH_LENGTH]; + u32 boot_data_version; + u32 unused_data1[1016]; + u32 unused_consumer_data1; + u16 partition_table_logical_sector_address; + u16 partition_table_num_logical_sectors; + u32 unused_consumer_data[502]; + u32 unused_data[3]; +} __packed; + +#endif /* __SOC_TEGRA_BOOTDATA_H__ */ diff --git a/include/soc/tegra/common.h b/include/soc/tegra/common.h index 98027a76ce3d..744280ecab5f 100644 --- a/include/soc/tegra/common.h +++ b/include/soc/tegra/common.h @@ -6,6 +6,15 @@ #ifndef __SOC_TEGRA_COMMON_H__ #define __SOC_TEGRA_COMMON_H__ +#include + +#ifdef CONFIG_ARCH_TEGRA bool soc_is_tegra(void); +#else +static inline bool soc_is_tegra(void) +{ + return false; +} +#endif #endif /* __SOC_TEGRA_COMMON_H__ */ diff --git a/include/soc/tegra/partition.h b/include/soc/tegra/partition.h new file mode 100644 index 000000000000..17f5fbdaf49e --- /dev/null +++ b/include/soc/tegra/partition.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_TEGRA_PARTITION_H__ +#define __SOC_TEGRA_PARTITION_H__ + +#include +#include + +#define TEGRA_PT_MAGIC 0xffffffff8f9e8d8bULL +#define TEGRA_PT_VERSION 0x100 +#define TEGRA_PT_LOGICAL_SECTOR_SIZE 4096 +#define TEGRA_PT_AES_HASH_SIZE 4 +#define TEGRA_PT_NAME_SIZE 4 + +#define TEGRA_PT_SDHCI_DEVICE_ID 18 +#define TEGRA_PT_SDHCI_DEVICE_INSTANCES 4 + +#define TEGRA_PT_PART_TYPE_BCT 1 +#define TEGRA_PT_PART_TYPE_EBT 2 +#define TEGRA_PT_PART_TYPE_PT 3 +#define TEGRA_PT_PART_TYPE_GENERIC 6 +#define TEGRA_PT_PART_TYPE_GP1 9 +#define TEGRA_PT_PART_TYPE_GPT 10 + +#define TEGRA_PT_HEADER_SZ \ + (sizeof(struct tegra_partition_header_insecure) + \ + sizeof(struct tegra_partition_header_secure)) \ + +#define TEGRA_PT_MAX_PARTITIONS \ + ((TEGRA_PT_LOGICAL_SECTOR_SIZE - TEGRA_PT_HEADER_SZ) / \ + sizeof(struct tegra_partition)) + +struct tegra_partition_mount_info { + u32 device_id; + u32 device_instance; + u32 device_attr; + u8 mount_path[TEGRA_PT_NAME_SIZE]; + u32 file_system_type; + u32 file_system_attr; +} __packed; + +struct tegra_partition_info { + u32 partition_attr; + u32 __pad1; + u64 logical_sector_address; + u64 logical_sectors_num; + u64 __pad2[2]; + u32 partition_type; + u32 __pad3; +} __packed; + +struct tegra_partition { + u32 partition_id; + u8 partition_name[TEGRA_PT_NAME_SIZE]; + struct tegra_partition_mount_info mount_info; + struct tegra_partition_info part_info; +} __packed; + +struct tegra_partition_header_insecure { + u64 magic; + u32 version; + u32 length; + u32 signature[TEGRA_PT_AES_HASH_SIZE]; +} __packed; + +struct tegra_partition_header_secure { + u32 random_data[TEGRA_PT_AES_HASH_SIZE]; + u64 magic; + u32 version; + u32 length; + u32 num_partitions; + u32 __pad; +} __packed; + +struct tegra_partition_table { + struct tegra_partition_header_insecure insecure; + struct tegra_partition_header_secure secure; + struct tegra_partition partitions[TEGRA_PT_MAX_PARTITIONS]; +} __packed; + +#ifdef CONFIG_TEGRA_PARTITION +void tegra_partition_table_setup(sector_t logical_sector_address, + sector_t logical_sectors_num); +#else +static inline void tegra_partition_table_setup(sector_t logical_sector_address, + sector_t logical_sectors_num) +{ +} +#endif + +#endif /* __SOC_TEGRA_PARTITION_H__ */ From patchwork Mon Mar 23 16:34:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11453461 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 967DC15AB for ; Mon, 23 Mar 2020 16:36:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7557D20774 for ; Mon, 23 Mar 2020 16:36:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="LXue7MQ/" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727630AbgCWQfl (ORCPT ); Mon, 23 Mar 2020 12:35:41 -0400 Received: from mail-lj1-f193.google.com ([209.85.208.193]:46681 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727564AbgCWQfk (ORCPT ); Mon, 23 Mar 2020 12:35:40 -0400 Received: by mail-lj1-f193.google.com with SMTP id v16so8281762ljk.13; Mon, 23 Mar 2020 09:35:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0wrb1jawDZ/OoSKSRa4jhXauQnVpnBi/wzx5vJ7NjQo=; b=LXue7MQ/ynT2Qwn4Q8TkmyOyQlQ4Cl2ZdMW1YqwqkG1D/M0wI9BzolDLdIaer31yzj zOLwVklExyWur1HIb64j6GxGiZxeVjzi1a+yoLrxYoZ7xg6xoz2izPmpZPYWZCHCp+++ DMjQUZPfh+SkW0G0pPW/JHkwWA7sl8Ww9IM/Y5DGKxgIINsREoSx3aVyjswp6BAO51mp 25xipyCqLfeuv17YaDx2+uuQ2w+G1GT7u5dK0Wc9dEO0K2fc9dzxe3UZxs11U5SmFyHH FHjet48tQUbsfS4oZYz/67kQ6em5slQ7Ya31tnTI6xza5GuCsXmToLM5AAGAZoghr2jY MvWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0wrb1jawDZ/OoSKSRa4jhXauQnVpnBi/wzx5vJ7NjQo=; b=ZwrcqWsJD9cslX1JBE9B7brD3mHOygumUCe4VDoKMl9iLAZlYYbXULzXQ7EVbF9rr/ qdN7SQL+2Axsfcy6p+d/v1K1bxjjTy+Ku6osWiRjW/TRp9P+nJaRrKUQXSaJYNumCciu X10vdp+4MCjOOKKcyHKLNekZPmfDAsmUUyBVWrA2FhzhaixpFzzETZvtSAWd74FXxO4z Xen1W88V0kz8vvZ4fiQol4MYbce3wjg+UVR/V4ltzIvs1X4yUe5qbCqvmOOfSAIasKIO 5feM3zEnUtA91IoVHq1F5h04z30LqAL/0JTBrqIEtBDl0qr9ggZVHDfHVYuXUOD1nils eerA== X-Gm-Message-State: ANhLgQ1pCSNB4D2geBdF0Ny42nFZL7WSEoMYPLEaUVhJ/s9SFouEynby nhLigY44/74h5Jx7qILNKbY= X-Google-Smtp-Source: ADFU+vstcQ7obgecuz7XRtqThNdaDgYd6CA+FmepLrt9ZGbs/ZU6P+XLZBTC9u7wsH0SAcNbkpBItg== X-Received: by 2002:a2e:90da:: with SMTP id o26mr14720812ljg.254.1584981338066; Mon, 23 Mar 2020 09:35:38 -0700 (PDT) Received: from localhost.localdomain (94-29-39-224.dynamic.spd-mgts.ru. [94.29.39.224]) by smtp.gmail.com with ESMTPSA id m14sm4820017lfo.25.2020.03.23.09.35.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 09:35:37 -0700 (PDT) From: Dmitry Osipenko To: Jens Axboe , Thierry Reding , Jonathan Hunter , =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= , David Heidelberg , Peter Geis , Stephen Warren , Nicolas Chauvet , Ulf Hansson , Adrian Hunter , Billy Laws Cc: linux-tegra@vger.kernel.org, linux-block@vger.kernel.org, Andrey Danin , Gilles Grandou , Ryan Grachek , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 04/10] block: Introduce GENHD_FL_PART_SCAN_ONCE Date: Mon, 23 Mar 2020 19:34:25 +0300 Message-Id: <20200323163431.7678-5-digetx@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200323163431.7678-1-digetx@gmail.com> References: <20200323163431.7678-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Some NVIDIA Tegra devices store partition table on a boot eMMC partition, and thus, partition-scanner should read out partition table from the boot block device without assigning found partitions to the block device. The new disk flag allows MMC core to enable boot partitions scanning, without changing the old behavior. Signed-off-by: Dmitry Osipenko --- block/genhd.c | 2 +- block/partition-generic.c | 13 ++++++++++++- include/linux/genhd.h | 12 ++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index b210c12c4870..e66a8fcc963b 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -700,7 +700,7 @@ static void register_disk(struct device *parent, struct gendisk *disk, } /* No minors to use for partitions */ - if (!disk_part_scan_enabled(disk)) + if (!disk_part_scan_enabled(disk) && !disk_part_scan_once(disk)) goto exit; /* No such device (e.g., media were just removed) */ diff --git a/block/partition-generic.c b/block/partition-generic.c index 564fae77711d..bd31b71f49f7 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -537,7 +537,7 @@ int blk_add_partitions(struct gendisk *disk, struct block_device *bdev) struct parsed_partitions *state; int ret = -EAGAIN, p, highest; - if (!disk_part_scan_enabled(disk)) + if (!disk_part_scan_enabled(disk) && !disk_part_scan_once(disk)) return 0; state = check_partition(disk, bdev); @@ -580,6 +580,17 @@ int blk_add_partitions(struct gendisk *disk, struct block_device *bdev) goto out_free_state; } + /* + * Partitions were found, but they should stay inactive for a + * scan-only disk. + */ + if (disk_part_scan_once(disk)) { + pr_warn("%s: ignoring partition table on scan-only block device\n", + disk->disk_name); + ret = 0; + goto out_free_state; + } + /* tell userspace that the media / partition table may have changed */ kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index d5c75df64bba..79831481142f 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -179,6 +179,12 @@ struct hd_struct { * Implies ``GENHD_FL_SUPPRESS_PARTITION_INFO`` and * ``GENHD_FL_NO_PART_SCAN``. * Used for multipath devices. + * + * ``GENHD_FL_PART_SCAN_ONCE`` (0x0800): the block device will be scanned for + * partition table presence, but found partition won't be assigned to the + * block device. + * Used for embedded devices with a non-standard partition table, where + * partition table is stored on a separate block device. */ #define GENHD_FL_REMOVABLE 0x0001 /* 2 is unused (used to be GENHD_FL_DRIVERFS) */ @@ -191,6 +197,7 @@ struct hd_struct { #define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE 0x0100 #define GENHD_FL_NO_PART_SCAN 0x0200 #define GENHD_FL_HIDDEN 0x0400 +#define GENHD_FL_PART_SCAN_ONCE 0x0800 enum { DISK_EVENT_MEDIA_CHANGE = 1 << 0, /* media changed */ @@ -292,6 +299,11 @@ static inline bool disk_part_scan_enabled(struct gendisk *disk) !(disk->flags & GENHD_FL_NO_PART_SCAN); } +static inline bool disk_part_scan_once(struct gendisk *disk) +{ + return !!(disk->flags & GENHD_FL_PART_SCAN_ONCE); +} + static inline dev_t disk_devt(struct gendisk *disk) { return MKDEV(disk->major, disk->first_minor); From patchwork Mon Mar 23 16:34:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11453433 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 97BDF6CA for ; Mon, 23 Mar 2020 16:35:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7729920722 for ; Mon, 23 Mar 2020 16:35:45 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="CyNyeMKW" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727659AbgCWQfo (ORCPT ); Mon, 23 Mar 2020 12:35:44 -0400 Received: from mail-lj1-f194.google.com ([209.85.208.194]:43052 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727507AbgCWQfm (ORCPT ); Mon, 23 Mar 2020 12:35:42 -0400 Received: by mail-lj1-f194.google.com with SMTP id g27so6507421ljn.10; Mon, 23 Mar 2020 09:35:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=w0YlAmpluZ5D3NO8kHqv749YNcVtvXYMv+8BYDY6gX8=; b=CyNyeMKW8PFLFOs7Bf7yjiDE4vIvnA+m7J9nEYRxdr+Gx1hmxopSIb5ynvJR2d9yYu FYzHnpeLwnV7RWIcWnXZnyTP+PsSoYJ5rbQjBQ5kWKyzAeJgpJ8yjaureGlZGmefXBvh EY+bpzSo2CeGLmzEfaVHgMJ9F/SalVmxfsm+vZouSgpfMu8I0HWYpK9c4dNMlk60iH2S p/AnZlnl3PKdLdg1R6EfJiBS3XoSqkrtGMqe7AqPuh+JxJRNEkEe7UvpTE3HrtLrgJZI sSWP/L9WQstfoR8glEAbL3+37AIMouj+vfXg5vc0e56Ltz+1BPzomgmMYe1cEv57J2Ap 4frA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=w0YlAmpluZ5D3NO8kHqv749YNcVtvXYMv+8BYDY6gX8=; b=Hb51vSoE5wnThK8bahflY4zf+i67/F8c9U88AQsl4zr50tR7sfBB63LfXkDkKtKJ21 1CY8fyH56PEKd7EeAgWmOzS3HfYLv/dG2c4qU/l+Yiu/Je3GkQYbOA8e/Mnb9Nyhq/LZ cRaiSf3edZWLpWmSnqmcgePLdie5BJecOHjPptIV/IuhWba5jecIbSsw7L7Ir80Undo+ /QwazAYRfN5dMAhD/6Swvu8S1B2LUR+CZHo1hUQo+6HK/CbBbcVxMcnOXALoldxnPvHN BR5fmR+MIY/+OCDbYKkOYhNDcfQ/4x6dRyOsVBIxUYdy6QQqSvZHyxXY1jjeHWxjD6TS EKuw== X-Gm-Message-State: ANhLgQ2V88b/V4OCIlEVOYRxMZZ5NJCE+38nuEjy0PMn56sz5ULkius+ m1W5yxI04BIMSRjqtoRk6ik= X-Google-Smtp-Source: ADFU+vuaNbeMeWKlKJCFpCe6dFW/Y2Ycr+EGB6ZeJQNghi8JRS+awpjDqrGdi02SL38G0Vf4wvZl5w== X-Received: by 2002:a2e:984d:: with SMTP id e13mr13623932ljj.275.1584981339297; Mon, 23 Mar 2020 09:35:39 -0700 (PDT) Received: from localhost.localdomain (94-29-39-224.dynamic.spd-mgts.ru. [94.29.39.224]) by smtp.gmail.com with ESMTPSA id m14sm4820017lfo.25.2020.03.23.09.35.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 09:35:38 -0700 (PDT) From: Dmitry Osipenko To: Jens Axboe , Thierry Reding , Jonathan Hunter , =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= , David Heidelberg , Peter Geis , Stephen Warren , Nicolas Chauvet , Ulf Hansson , Adrian Hunter , Billy Laws Cc: linux-tegra@vger.kernel.org, linux-block@vger.kernel.org, Andrey Danin , Gilles Grandou , Ryan Grachek , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 05/10] mmc: block: Add mmc_bdev_to_part_type() helper Date: Mon, 23 Mar 2020 19:34:26 +0300 Message-Id: <20200323163431.7678-6-digetx@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200323163431.7678-1-digetx@gmail.com> References: <20200323163431.7678-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org NVIDIA Tegra Partition Table parser needs to know eMMC boot partition ID that is associated with the block device in order to validate and parse partition table properly. This patch adds new mmc_bdev_to_part_type() helper which takes block device for the input and returns a corresponding MMC card partition ID (part_type). This is needed by tegra-partition parser in order to distinguish boot0 eMMC partition from boot1. Signed-off-by: Dmitry Osipenko --- drivers/mmc/core/block.c | 16 ++++++++++++++++ include/linux/mmc/blkdev.h | 1 + 2 files changed, 17 insertions(+) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 36d84a8e182c..2cee57c7388d 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -321,6 +321,22 @@ struct mmc_card *mmc_bdev_to_card(struct block_device *bdev) return md->queue.card; } +int mmc_bdev_to_part_type(struct block_device *bdev) +{ + struct mmc_blk_data *md; + struct mmc_card *card; + + card = mmc_bdev_to_card(bdev); + if (!card) + return -EINVAL; + + md = mmc_blk_get(bdev->bd_disk); + if (!md) + return -EINVAL; + + return md->part_type; +} + static int mmc_blk_open(struct block_device *bdev, fmode_t mode) { struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); diff --git a/include/linux/mmc/blkdev.h b/include/linux/mmc/blkdev.h index 67608c58de70..24e73ac02b4b 100644 --- a/include/linux/mmc/blkdev.h +++ b/include/linux/mmc/blkdev.h @@ -9,5 +9,6 @@ struct block_device; struct mmc_card; struct mmc_card *mmc_bdev_to_card(struct block_device *bdev); +int mmc_bdev_to_part_type(struct block_device *bdev); #endif /* LINUX_MMC_BLOCK_DEVICE_H */ From patchwork Mon Mar 23 16:34:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11453445 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A15E4159A for ; Mon, 23 Mar 2020 16:36:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 80FD420786 for ; Mon, 23 Mar 2020 16:36:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="m2OUE5YV" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727678AbgCWQfp (ORCPT ); Mon, 23 Mar 2020 12:35:45 -0400 Received: from mail-lj1-f193.google.com ([209.85.208.193]:34998 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727652AbgCWQfo (ORCPT ); Mon, 23 Mar 2020 12:35:44 -0400 Received: by mail-lj1-f193.google.com with SMTP id u12so15350976ljo.2; Mon, 23 Mar 2020 09:35:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=YN6wlr+SxSHAMt4dIT8x49SccG7CxZ44xau7TZEGR7U=; b=m2OUE5YVVMVA0++Y1OYwALT15/EvoPyUi4xHb4jj/G033Qc4tP7oVxev1xyzMwCFIZ 5hMl9UKZI5avvD9l6uIIwTbVwKcpKYBIUCXsNAeWyPH6phcrMsucH7U4i38LY/ZU5/xT 9YFy3E8Z3OtHJ9h7SqzhAxeYiogxXSkwPFfrskfkBEScQGXWdoIlo12mUcrtLdlDbTVN b7PYkiHUBlm42Jt8fe9OpbWBhm54g2bq5MsReESziQNUebeX9bJ9lGQ0Y3Oy7E+nWYTA X2m4NYw/DnFWQfo/4HpvU56akoSMquuplCoTUke1FyT7ePQDX2ws1auWkTcp6v/3os82 ELmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=YN6wlr+SxSHAMt4dIT8x49SccG7CxZ44xau7TZEGR7U=; b=hyqi4gWyt1797RBvDrzhXBMjSG92/YUcFuVwXDENny6h+YpMtHmksyy3fMNr5Rt/7g dkfeXhU2jMmuoYNfTT3shpb0tuAC2vEuiXJRxFZIT+9E3AJKBTU7zdGNStqMnT89Guve TRYjTcy+z+YdMurWAu0qXweKKZBp5hJb82b+CDfj0BsXowVBfQZZpv0W1xpW+Ma/2fDc ztItvMWLs85GRPEYm3ixTaFQ3bwcoHdDWnQHaVRUNjuONjR60KDXVR2hpfP+l2r4HJrp gg1iWU2rX2sVX/xDSM2gyTZHdeUNyecR5ZpCT2LOOUe9OEZhzRZY8VV7wqvEEY8hJ5dl 6QtQ== X-Gm-Message-State: ANhLgQ3awCzXmfLFcAY0Qt30vBtK3tJ5/2g6xfnAm8Okb/8TwXFOFYQn h2w1kNBEL7PMpmmpEMswHYyOeYNA X-Google-Smtp-Source: ADFU+vsAVKfLP8wIKNQtB9y9of/X+P2shjDrovtop+vKqr+VzzqMO6JjwELSsjcYxmtIVFjb7DvKvw== X-Received: by 2002:a2e:b88b:: with SMTP id r11mr14425033ljp.116.1584981340449; Mon, 23 Mar 2020 09:35:40 -0700 (PDT) Received: from localhost.localdomain (94-29-39-224.dynamic.spd-mgts.ru. [94.29.39.224]) by smtp.gmail.com with ESMTPSA id m14sm4820017lfo.25.2020.03.23.09.35.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 09:35:40 -0700 (PDT) From: Dmitry Osipenko To: Jens Axboe , Thierry Reding , Jonathan Hunter , =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= , David Heidelberg , Peter Geis , Stephen Warren , Nicolas Chauvet , Ulf Hansson , Adrian Hunter , Billy Laws Cc: linux-tegra@vger.kernel.org, linux-block@vger.kernel.org, Andrey Danin , Gilles Grandou , Ryan Grachek , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 06/10] mmc: block: Add mmc_bdev_to_area_type() helper Date: Mon, 23 Mar 2020 19:34:27 +0300 Message-Id: <20200323163431.7678-7-digetx@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200323163431.7678-1-digetx@gmail.com> References: <20200323163431.7678-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org NVIDIA Tegra Partition Table parser needs to know eMMC partition type in order to validate and parse partition table properly. This patch adds new mmc_bdev_to_area_type() helper which takes block device for the input and returns a corresponding MMC card partition type. This allows tegra-partition parser to distinguish boot eMMC partition from the main eMMC partition. Signed-off-by: Dmitry Osipenko --- drivers/mmc/core/block.c | 16 ++++++++++++++++ include/linux/mmc/blkdev.h | 1 + 2 files changed, 17 insertions(+) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 2cee57c7388d..ec69b613ee92 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -337,6 +337,22 @@ int mmc_bdev_to_part_type(struct block_device *bdev) return md->part_type; } +int mmc_bdev_to_area_type(struct block_device *bdev) +{ + struct mmc_blk_data *md; + struct mmc_card *card; + + card = mmc_bdev_to_card(bdev); + if (!card) + return -EINVAL; + + md = mmc_blk_get(bdev->bd_disk); + if (!md) + return -EINVAL; + + return md->area_type; +} + static int mmc_blk_open(struct block_device *bdev, fmode_t mode) { struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); diff --git a/include/linux/mmc/blkdev.h b/include/linux/mmc/blkdev.h index 24e73ac02b4b..5fa5ef35ac25 100644 --- a/include/linux/mmc/blkdev.h +++ b/include/linux/mmc/blkdev.h @@ -10,5 +10,6 @@ struct mmc_card; struct mmc_card *mmc_bdev_to_card(struct block_device *bdev); int mmc_bdev_to_part_type(struct block_device *bdev); +int mmc_bdev_to_area_type(struct block_device *bdev); #endif /* LINUX_MMC_BLOCK_DEVICE_H */ From patchwork Mon Mar 23 16:34:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11453459 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2FC6F159A for ; Mon, 23 Mar 2020 16:36:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0361C20774 for ; Mon, 23 Mar 2020 16:36:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hnxrr2z1" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727798AbgCWQgF (ORCPT ); Mon, 23 Mar 2020 12:36:05 -0400 Received: from mail-lj1-f196.google.com ([209.85.208.196]:44769 "EHLO mail-lj1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727646AbgCWQfo (ORCPT ); Mon, 23 Mar 2020 12:35:44 -0400 Received: by mail-lj1-f196.google.com with SMTP id w4so15289435lji.11; Mon, 23 Mar 2020 09:35:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MD6xGZ4xORI+tNtNZZDwyKjUfBMMQlzk74IcvklWY7A=; b=hnxrr2z14XgP3gYDZJf1VnWxpBTjP+LA97XCUK7xTr7Cya02gHwDGMsxt+If5NdrZG UFANZiVW2p7/l9DtPiu7w2o5/4m0USqs4MvPhYLO/M6qyQCsvncX+mCg2dZJFricfchL LWXeq7O1PG41a+mE9bqcnWyWjxopRLzYDTmkQkHDVIhID7yF6vPKXcF/Jlc/pWCFx899 kgJfkQsWJCUpGfL/wuRLooRukLDrkBykqF+mAK9BHwzRb7lcwczsy8wyPN5IblZ9glyn msn0ZsQ0IAyK6VLYikcsjcHzX5lbY5z/Qr9UYPtn2eYcTzXqY0U4a5TLJZ1wb32XN0xj t1CA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MD6xGZ4xORI+tNtNZZDwyKjUfBMMQlzk74IcvklWY7A=; b=XPqHakrbvNvyc4Xzzs1D7/RLewpT6x91Pe9+BcFS8kRXb4meB538opmT+HIltZyjnv JuhitmE6QslC2cyZmeufVTAV2b4UJSFtoMKwqF+ibsLndiWXWsmU/yEuyNJEnudOx8p4 t1SWNJ+4+rblAWqoRyKrzUpjibkMjHAx3ZLzElTQioLjvZCGKv3OXai34VgQlEdrhAnc q3Wbx6MMKELL47C/DnSkYqQ3sF/jQlv0g4T83I85cjzr1Ui8dQbhcdZE0FHRkXV7Qhkr kEspxXor0tlahJq1M1adF32yrWBkv+uxf0YzBfhWbRdVt7hEf7XcQdY2cIvzstXSBOHZ u1QA== X-Gm-Message-State: ANhLgQ19YwL2mKTJO7hixJUT9ru/xk15P0fglW+LAh9/VUepcoRviInz Qr9uhz9np5H3A4+tgrH3ZQw= X-Google-Smtp-Source: ADFU+vuiTGI7tGqS5jeAw/PSMsEFiIhB8ZSLCL1XV0mlcTGg0/REiOy/H7BcJXDm+lBefKsMAZkh1w== X-Received: by 2002:a2e:9017:: with SMTP id h23mr14685724ljg.144.1584981341741; Mon, 23 Mar 2020 09:35:41 -0700 (PDT) Received: from localhost.localdomain (94-29-39-224.dynamic.spd-mgts.ru. [94.29.39.224]) by smtp.gmail.com with ESMTPSA id m14sm4820017lfo.25.2020.03.23.09.35.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 09:35:41 -0700 (PDT) From: Dmitry Osipenko To: Jens Axboe , Thierry Reding , Jonathan Hunter , =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= , David Heidelberg , Peter Geis , Stephen Warren , Nicolas Chauvet , Ulf Hansson , Adrian Hunter , Billy Laws Cc: linux-tegra@vger.kernel.org, linux-block@vger.kernel.org, Andrey Danin , Gilles Grandou , Ryan Grachek , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 07/10] mmc: block: Add MMC_QUIRK_RESCAN_MAIN_BLKDEV Date: Mon, 23 Mar 2020 19:34:28 +0300 Message-Id: <20200323163431.7678-8-digetx@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200323163431.7678-1-digetx@gmail.com> References: <20200323163431.7678-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org NVIDIA Tegra Partition Table location isn't restricted by the main eMMC partition. This patch introduces new MMC-card quirk which is needed by some NVIDIA Tegra devices in order to set up partition table if it is stored on a eMMC boot partition. The tegra-partition parser will read out FS partition table from the eMMC boot partition and stash it for the main eMMC partition. In this case block device of the main eMMC partition needs to be re-scanned in order to assign the stashed partition table to the main MMC block device by tegra-partition parser. This patch adds new MMC card flag that is applied by tegra-partition parser to the scanned MMC card if partition table is found on a boot eMMC partition. This flag tells MMC_BLOCK core that main MMC partition needs to be re-scanned once all block devices of the MMC card are instantiated. Signed-off-by: Dmitry Osipenko --- drivers/mmc/core/block.c | 31 +++++++++++++++++++++++++++++++ include/linux/mmc/card.h | 1 + 2 files changed, 32 insertions(+) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index ec69b613ee92..2c2bec114fd6 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -2955,6 +2955,27 @@ static void mmc_blk_remove_debugfs(struct mmc_card *card, #endif /* CONFIG_DEBUG_FS */ +static int mmc_blk_rescan_disk(struct mmc_blk_data *md) +{ + struct block_device *bdev; + + bdev = blkdev_get_by_dev(disk_devt(md->disk), FMODE_READ | FMODE_EXCL, + md); + if (IS_ERR(bdev)) { + pr_err("%s: %s: failed to get block device\n", + __func__, md->disk->disk_name); + return PTR_ERR(bdev); + } + + mutex_lock(&bdev->bd_mutex); + bdev_disk_changed(bdev, false); + mutex_unlock(&bdev->bd_mutex); + + blkdev_put(bdev, FMODE_READ | FMODE_EXCL); + + return 0; +} + static int mmc_blk_probe(struct mmc_card *card) { struct mmc_blk_data *md, *part_md; @@ -2998,6 +3019,16 @@ static int mmc_blk_probe(struct mmc_card *card) goto out; } + /* + * Quirk for NVIDIA Tegra devices that store FS partition table + * on a boot partition. Tegra-partition scanner found partition + * table on a boot MMC partition and stashed it for the main MMC + * partition if MMC_QUIRK_RESCAN_MAIN_BLKDEV is set, and thus, + * the main partition needs to be re-scanned. + */ + if (card->quirks & MMC_QUIRK_RESCAN_MAIN_BLKDEV) + mmc_blk_rescan_disk(md); + /* Add two debugfs entries */ mmc_blk_add_debugfs(card, md); diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 90b1d83ce675..550d50e57cc4 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -270,6 +270,7 @@ struct mmc_card { #define MMC_QUIRK_BROKEN_IRQ_POLLING (1<<11) /* Polling SDIO_CCCR_INTx could create a fake interrupt */ #define MMC_QUIRK_TRIM_BROKEN (1<<12) /* Skip trim */ #define MMC_QUIRK_BROKEN_HPI (1<<13) /* Disable broken HPI support */ +#define MMC_QUIRK_RESCAN_MAIN_BLKDEV (1<<14) /* Main partition needs to be re-scanned after instantiating all partitions */ bool reenable_cmdq; /* Re-enable Command Queue */ From patchwork Mon Mar 23 16:34:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11453441 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C9AE915AB for ; Mon, 23 Mar 2020 16:36:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A999C20780 for ; Mon, 23 Mar 2020 16:36:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nXoD7Lgk" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727711AbgCWQfr (ORCPT ); Mon, 23 Mar 2020 12:35:47 -0400 Received: from mail-lf1-f68.google.com ([209.85.167.68]:33683 "EHLO mail-lf1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727671AbgCWQfr (ORCPT ); Mon, 23 Mar 2020 12:35:47 -0400 Received: by mail-lf1-f68.google.com with SMTP id c20so10785581lfb.0; Mon, 23 Mar 2020 09:35:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PNUW8UPO4mmlNCoO/hi+s09smb8KB9KTLjiOmh4I/TY=; b=nXoD7LgkcBotLjD1LYcKthzHM4CbwCYJQbZ2BYwSBm5Bq9t822+sUewc37047Tkz1V vRFTmC4e08tfGKjtvADWPXlNic8qOiTheRYIjqeVChCUgG4L0M4hTBg3N1a5IITNWV6A 2BQOVu29XqqFk6+jafwbJCSuK4nxR0VqQB0SSFXjpv1DT4uLIT0FsJvC4JYH/UfCY7aM 2VcpLdwrpMnTVWbi9riZWAvq3pnEFleol1W2P+l9SvjpQWysB1QVVxcgG++BbJGeuEjS 7qVRkUqVn9E8MMVJHMRrmHN1rGU4UjSRI6C76QSy9kDFZ418TQnUv4Z2PHpylzx0kRv3 p8eg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PNUW8UPO4mmlNCoO/hi+s09smb8KB9KTLjiOmh4I/TY=; b=N3BTKxCUtGs+/drh/vFrGpkhNkF3KaQkiGTx+aFmblJZXEgcBZACMY6cdpkT8vUBqz WsVFf1j6/V2V5sSc0kt/kE+59g99tFIpiSwpJfLhzcLkD6eoOWYQPc+QbUuIgqu1Csxp Kg2HE3BDfshdadGVQdUD1wpwuBE6xnYvOvtYtPzfEJs1OAW9gT4SGJWQtiXSFYBtKt94 KII8hw/gooRZAplLEeGzXzGsyqZykCbqal0G6JPzCI+EVjdJj9XsfLqJmxtMeMgY94NN KTxTdjN7bgHywGzJ7zOJVnfiQNgYMCmT4NHJ7iKXaOeQQmMUft5CMIrqYyvGZGJddGKT LBBA== X-Gm-Message-State: ANhLgQ0woiZX9f0wivHunZbx9Rz65Z0/ImdV+b/8U+gvAArbR4fIZ5Y6 WYbDUlXYyQIQOJT7h9Sls90= X-Google-Smtp-Source: ADFU+vvY9IK1Nh7xDm+lse/+L4JK9O+uzzO3t7BI36zVpgJ8+9EmUWUJ/vezzXL4quIyV8j5cT/iaw== X-Received: by 2002:a05:6512:10c4:: with SMTP id k4mr13490533lfg.98.1584981342888; Mon, 23 Mar 2020 09:35:42 -0700 (PDT) Received: from localhost.localdomain (94-29-39-224.dynamic.spd-mgts.ru. [94.29.39.224]) by smtp.gmail.com with ESMTPSA id m14sm4820017lfo.25.2020.03.23.09.35.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 09:35:42 -0700 (PDT) From: Dmitry Osipenko To: Jens Axboe , Thierry Reding , Jonathan Hunter , =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= , David Heidelberg , Peter Geis , Stephen Warren , Nicolas Chauvet , Ulf Hansson , Adrian Hunter , Billy Laws Cc: linux-tegra@vger.kernel.org, linux-block@vger.kernel.org, Andrey Danin , Gilles Grandou , Ryan Grachek , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 08/10] mmc: block: Support partition-table scanning on boot partitions Date: Mon, 23 Mar 2020 19:34:29 +0300 Message-Id: <20200323163431.7678-9-digetx@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200323163431.7678-1-digetx@gmail.com> References: <20200323163431.7678-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Some NVIDIA Tegra devices store partition table on a boot eMMC partition, and thus, boot partitions need to be scanned. This patch enables scanning of the boot MMC partitions, but only if MMC host allows to do that. This patch adds new scan_mmc_boot_partitions field to the struct MMC host, which should be set to true by the platform-specific SDHCI drivers if MMC boot partitions scanning is desired. Signed-off-by: Dmitry Osipenko --- drivers/mmc/core/block.c | 26 ++++++++++++++++++++++++++ include/linux/mmc/host.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 2c2bec114fd6..d22498bd9968 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -2334,6 +2334,22 @@ static inline int mmc_blk_readonly(struct mmc_card *card) !(card->csd.cmdclass & CCC_BLOCK_WRITE); } +static bool mmc_blk_boot_part_scan(struct mmc_blk_data *md, + struct mmc_card *card) +{ + if (!(md->area_type & MMC_BLK_DATA_AREA_BOOT)) + return false; + + /* + * Platform driver shall explicitly allow the boot partitions + * scanning because this is a non-standard behavior. + */ + if (!card->host->scan_mmc_boot_partitions) + return false; + + return true; +} + static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, struct device *parent, sector_t size, @@ -2414,6 +2430,16 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, md->disk->flags |= GENHD_FL_NO_PART_SCAN | GENHD_FL_SUPPRESS_PARTITION_INFO; + /* + * Some embedded devices store FS partition table on a boot eMMC + * partition (NVIDIA Tegra for example). In this case partition + * scanner will scan the boot partitions, but the found partitions + * won't be assigned to the boot block device. It's up to a + * partition scanner what to do with the found partitions. + */ + if (mmc_blk_boot_part_scan(md, card)) + md->disk->flags |= GENHD_FL_PART_SCAN_ONCE; + /* * As discussed on lkml, GENHD_FL_REMOVABLE should: * diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c318fb5b6a94..e3d47c7e9c48 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -468,6 +468,8 @@ struct mmc_host { /* Host Software Queue support */ bool hsq_enabled; + bool scan_mmc_boot_partitions; + unsigned long private[] ____cacheline_aligned; }; From patchwork Mon Mar 23 16:34:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11453447 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CC6FD15AB for ; Mon, 23 Mar 2020 16:36:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AB56B20786 for ; Mon, 23 Mar 2020 16:36:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="rG5Hq3wW" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727695AbgCWQfq (ORCPT ); Mon, 23 Mar 2020 12:35:46 -0400 Received: from mail-lf1-f67.google.com ([209.85.167.67]:40008 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727670AbgCWQfq (ORCPT ); Mon, 23 Mar 2020 12:35:46 -0400 Received: by mail-lf1-f67.google.com with SMTP id j17so10756612lfe.7; Mon, 23 Mar 2020 09:35:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hkYPIPdOfV7br4C4RHUcphVGjfFEoNa4bM1BVezoPBk=; b=rG5Hq3wWvpFqgAS9rq9wpDrYRFkZtPlx87cRxnzG6q8IHm5vYnFrMkt+57dJND+mNc WSoNJf2y6rVAuBSeRYTAposgo3Rjhu1myiVTZedwXbRZdHZ20Ps7+LyESzNkAbHqw40s oedHQ378rv2wH2q2B2zPzvMTfTWPuk5qWn6Is5gE5zo9oyeXVSk6+Ndi4R2yL7qy8U8O jJd4bpGGWwDp6DnvaepPrwqFeQ9nd9pXSDL/+QFjz6IKIxOmvXSOfAxv5cPTr1yBWTSO eit1KUMzdGp3X0/MajYzM+xc0mXDb/9PH9wkKcxktz6K24RyobU4ZR8yqNhZVlm8QYGd xp/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hkYPIPdOfV7br4C4RHUcphVGjfFEoNa4bM1BVezoPBk=; b=BEZO3gGvQ55pT97vS214sQWPyDolmQCtGWbYb3peO/N8t5bkujI6OiX9YIAN6qBuFd elA/2c+5qfk5vpIJR5sX4s9Ba1dtiYLoDcGLGrpxad5LAeOPazzR5AKvrkucoxqGq63E B0ZOgkRxZlaN2udgPoKruF4Ib/tPUjMfuNBFHmnp3GDZKv1fDvHJHYtn9CRZdblaJg1V LhzhclkvVoMofS0YaTWtHXkPOfEoi2KPqLPzUjUAI9VBm3Go2PEWRj7w8ulUeAvn23hf HLvhCToPTg1d+GJNPgUyqKFz+HOL5rY2xMdnmTJVUd4VyWiNUn3rg6InIiaUq9iR6SWX f4mg== X-Gm-Message-State: ANhLgQ1+ijkA2nO1lrgnClx3eCzTLbWd3XrMDui15Nr38jfOdb6ZYVkm gk4Y5jTpL+Ope4owxoVB5Ro= X-Google-Smtp-Source: ADFU+vtCz1E3FwWgwg/vbftXiI9QdeSSSVnbOJ9AhJmWkWw2WyRvdU/qRlRfzyhbeUClGTO342m4PA== X-Received: by 2002:a19:c005:: with SMTP id q5mr4712508lff.216.1584981344049; Mon, 23 Mar 2020 09:35:44 -0700 (PDT) Received: from localhost.localdomain (94-29-39-224.dynamic.spd-mgts.ru. [94.29.39.224]) by smtp.gmail.com with ESMTPSA id m14sm4820017lfo.25.2020.03.23.09.35.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 09:35:43 -0700 (PDT) From: Dmitry Osipenko To: Jens Axboe , Thierry Reding , Jonathan Hunter , =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= , David Heidelberg , Peter Geis , Stephen Warren , Nicolas Chauvet , Ulf Hansson , Adrian Hunter , Billy Laws Cc: linux-tegra@vger.kernel.org, linux-block@vger.kernel.org, Andrey Danin , Gilles Grandou , Ryan Grachek , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 09/10] mmc: sdhci-tegra: Enable boot partitions scanning on Tegra20 and Tegra30 Date: Mon, 23 Mar 2020 19:34:30 +0300 Message-Id: <20200323163431.7678-10-digetx@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200323163431.7678-1-digetx@gmail.com> References: <20200323163431.7678-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Consumer-grade devices usually have a custom NVIDIA Tegra Partition table used by built-in eMMC storage. On some devices partition table resides on a boot eMMC partition, and thus, the boot partitions need to be scanned. Signed-off-by: Dmitry Osipenko --- drivers/mmc/host/sdhci-tegra.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 3e2c5101291d..364572eaed8a 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -100,6 +100,7 @@ #define NVQUIRK_NEEDS_PAD_CONTROL BIT(7) #define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8) #define NVQUIRK_CQHCI_DCMD_R1B_CMD_TIMING BIT(9) +#define NVQUIRK_SCAN_BOOT_PARTITIONS BIT(10) /* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */ #define SDHCI_TEGRA_CQE_BASE_ADDR 0xF000 @@ -1304,7 +1305,8 @@ static const struct sdhci_tegra_soc_data soc_data_tegra20 = { .pdata = &sdhci_tegra20_pdata, .dma_mask = DMA_BIT_MASK(32), .nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 | - NVQUIRK_ENABLE_BLOCK_GAP_DET, + NVQUIRK_ENABLE_BLOCK_GAP_DET | + NVQUIRK_SCAN_BOOT_PARTITIONS, }; static const struct sdhci_pltfm_data sdhci_tegra30_pdata = { @@ -1333,7 +1335,8 @@ static const struct sdhci_tegra_soc_data soc_data_tegra30 = { .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 | NVQUIRK_ENABLE_SDR50 | NVQUIRK_ENABLE_SDR104 | - NVQUIRK_HAS_PADCALIB, + NVQUIRK_HAS_PADCALIB | + NVQUIRK_SCAN_BOOT_PARTITIONS, }; static const struct sdhci_ops tegra114_sdhci_ops = { @@ -1586,6 +1589,9 @@ static int sdhci_tegra_probe(struct platform_device *pdev) /* HW busy detection is supported, but R1B responses are required. */ host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_NEED_RSP_BUSY; + if (tegra_host->soc_data->nvquirks & NVQUIRK_SCAN_BOOT_PARTITIONS) + host->mmc->scan_mmc_boot_partitions = true; + tegra_sdhci_parse_dt(host); tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power", From patchwork Mon Mar 23 16:34:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 11453437 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BF09D15AB for ; Mon, 23 Mar 2020 16:35:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 93DE820753 for ; Mon, 23 Mar 2020 16:35:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HmajspLK" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727772AbgCWQfz (ORCPT ); Mon, 23 Mar 2020 12:35:55 -0400 Received: from mail-lj1-f193.google.com ([209.85.208.193]:44775 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727689AbgCWQfs (ORCPT ); Mon, 23 Mar 2020 12:35:48 -0400 Received: by mail-lj1-f193.google.com with SMTP id w4so15289678lji.11; Mon, 23 Mar 2020 09:35:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=QniCpQjPJXTAwB46jjMW57nPV4Kx9N7fme8aB82yFro=; b=HmajspLKp94NMbwJgNkK9F+3DreNcShuPTxmQie5bnGBkmLFBLrZ1hdjQgG36En68G RIKiSvCWyf/i9H0sVfcccBxhhCujmIFtVk5uqwOt5NyMDsXSfqVLEZb7DrGuwrlvHpie RZh7HUEufQo8Cgb7Y/kx+cMg2SYz3Rc6PRKqVEPmF0n4aI90H9eWEgs0LI1eOptut6rL JrhOJVQPEA1vZwDwLDqlVQ07gYPWC/hHh9wKABaAJoS7UkFzeefnauZUXEaEx1OHF9ol ObYrl65IwlTFNeb3MKgeyVTDUHQqj7m+GLuuiQebM5/8fP8nVYpSX5P3GUVtB36pYGvA Wj3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=QniCpQjPJXTAwB46jjMW57nPV4Kx9N7fme8aB82yFro=; b=Lx/2ogsCNtkaFawTZKPgWUbO5/khdKYT4rmYpkwaaTbZ0L7EF0o/L12Wib37hhYDv8 91A8MEFoPuXlKv7/7NGjYTM77APwOoBMtlZ6C2kAroYYkPov/BpaLG1aC4PxuPGmeMsN 5F28D9xs/hvAKidFpANzFvdt64a4d3QaetSaJGUhLuRb0AYbuHAF5dzVtlp6MvEPz1A2 sbWylfCqua6VrY3BLUlfFQG1m0hCnNmJ9N4JonLzEDi4oFIv8Q1spC1eAC46fc11KQou vHSZKnPqbl69azdMzqkpKx8d0z+sUA4A+lEB4E0+7Jp7MBNJktl1u5K7yUyzKYZCpKVw N4WA== X-Gm-Message-State: ANhLgQ17ttWrLUnmXRhXrg6htB2zix0bfA0vdFOvljnPUcZcm4xFZiZ5 RmKMsbJpaXPXNTWjIEGWa4Q= X-Google-Smtp-Source: ADFU+vv7x9KQTUFEfdMp/RNH6gi82I774PfSv5dAfz6Culd+uLgWQ7cCiPrxd20mWcn/9n44DuCr5w== X-Received: by 2002:a2e:9a54:: with SMTP id k20mr7111758ljj.272.1584981345380; Mon, 23 Mar 2020 09:35:45 -0700 (PDT) Received: from localhost.localdomain (94-29-39-224.dynamic.spd-mgts.ru. [94.29.39.224]) by smtp.gmail.com with ESMTPSA id m14sm4820017lfo.25.2020.03.23.09.35.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Mar 2020 09:35:44 -0700 (PDT) From: Dmitry Osipenko To: Jens Axboe , Thierry Reding , Jonathan Hunter , =?utf-8?b?TWljaGHFgiBNaXJvc8WCYXc=?= , David Heidelberg , Peter Geis , Stephen Warren , Nicolas Chauvet , Ulf Hansson , Adrian Hunter , Billy Laws Cc: linux-tegra@vger.kernel.org, linux-block@vger.kernel.org, Andrey Danin , Gilles Grandou , Ryan Grachek , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 10/10] partitions/tegra: Implement eMMC boot partitions scanning Date: Mon, 23 Mar 2020 19:34:31 +0300 Message-Id: <20200323163431.7678-11-digetx@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200323163431.7678-1-digetx@gmail.com> References: <20200323163431.7678-1-digetx@gmail.com> MIME-Version: 1.0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Some NVIDIA Tegra devices store partition table on eMMC boot partition. In order to support this case, the tegra-partition parser will read out partition table from a boot partition and stash it for the main eMMC partition. Signed-off-by: Dmitry Osipenko --- block/partitions/tegra.c | 122 +++++++++++++++++++++++++++++++++++---- 1 file changed, 111 insertions(+), 11 deletions(-) diff --git a/block/partitions/tegra.c b/block/partitions/tegra.c index 4cb8064bf458..09c300330f81 100644 --- a/block/partitions/tegra.c +++ b/block/partitions/tegra.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,10 @@ struct tegra_partition_table_parser { struct tegra_partition_table *pt; struct parsed_partitions *state; + struct mmc_card *card; bool pt_entry_checked; + unsigned int boot_id; + bool snapshot_mode; sector_t sector; int boot_offset; u32 dev_instance; @@ -67,6 +71,7 @@ struct tegra_partition_type { char *name; }; +static struct tegra_partition_table *scratch_pt; static sector_t tegra_pt_sector_address; static sector_t tegra_pt_sectors_num; @@ -224,6 +229,10 @@ static bool tegra_partition_valid(struct tegra_partition_table_parser *ptp, return false; } + /* size will be validated when ptp->snapshot_mode=false */ + if (ptp->snapshot_mode && size) + return true; + sect_end = get_capacity(ptp->state->bdev->bd_disk); /* eMMC boot partitions are below ptp->boot_offset */ @@ -254,6 +263,9 @@ static bool tegra_partitions_parse(struct tegra_partition_table_parser *ptp, sector_t sector, size; int i, slot = 1; + if (ptp->snapshot_mode && !check_only) + return true; + ptp->pt_entry_checked = false; for (i = 0; i < pt->secure.num_partitions; i++) { @@ -369,6 +381,7 @@ tegra_partition_table_emmc_boot_offset(struct tegra_partition_table_parser *ptp) { struct mmc_card *card = mmc_bdev_to_card(ptp->state->bdev); const struct of_device_id *matched; + int part_type, area_type; const u32 *sdhci_bases; u32 sdhci_base; unsigned int i; @@ -404,6 +417,32 @@ tegra_partition_table_emmc_boot_offset(struct tegra_partition_table_parser *ptp) ptp->dev_id = TEGRA_PT_SDHCI_DEVICE_ID; ptp->dev_instance = i; + area_type = mmc_bdev_to_area_type(ptp->state->bdev); + + if (WARN_ON(area_type < 0)) + return -1; + + switch (area_type) { + case MMC_BLK_DATA_AREA_BOOT: + part_type = mmc_bdev_to_part_type(ptp->state->bdev); + + if (WARN_ON(part_type < 0)) + return -1; + + ptp->boot_id = part_type - EXT_CSD_PART_CONFIG_ACC_BOOT0; + ptp->snapshot_mode = true; + break; + + case MMC_BLK_DATA_AREA_MAIN: + break; + + default: + TEGRA_PT_ERR(ptp, "unexpected area_type: %u\n", area_type); + return -1; + } + + ptp->card = card; + /* * eMMC storage has two special boot partitions in addition to the * main one. NVIDIA's bootloader linearizes eMMC boot0->boot1->main @@ -427,6 +466,9 @@ static int tegra_read_partition_table(struct tegra_partition_table_parser *ptp) Sector sect; void *part; + if (scratch_pt) + return 1; + for (i = 0; i < ARRAY_SIZE(ptu->pt_parts); i++) { /* * Partition table takes at maximum 4096 bytes, but @@ -462,18 +504,64 @@ int tegra_partition(struct parsed_partitions *state) if (ptp.boot_offset < 0) return 0; - if (tegra_pt_sector_address < ptp.boot_offset) { - TEGRA_PT_INFO(&ptp, - "scanning eMMC boot partitions unimplemented\n"); - return 0; - } + /* + * Some devices store partition table on boot MMC partition. + * In this case a "snapshot mode" will be used, which will + * only read->check->store partition table, the stored table + * will be used for the main MMC partition later on. + */ + if (ptp.snapshot_mode) { + sector_t boot_start, boot_end, boot_size; - ptp.pt = kmalloc(TEGRA_PT_LOGICAL_SECTOR_SIZE, GFP_KERNEL); - if (!ptp.pt) - return 0; + /* partition is already snapshoted, no need to proceed */ + if (scratch_pt) + return 0; + + boot_size = ptp.boot_offset / MMC_NUM_BOOT_PARTITION; + boot_start = ptp.boot_id * boot_size; + boot_end = boot_start + boot_size; - ptp.sector = tegra_pt_sector_address - ptp.boot_offset; - end_sector = ptp.sector + tegra_pt_sectors_num; + /* + * Bail out if partition table isn't located here, at this MMC + * partition. + */ + if (tegra_pt_sector_address < boot_start || + tegra_pt_sector_address >= boot_end) + return 0; + + ptp.boot_offset = boot_start; + + /* + * Note that mmc_blk_probe() always registers boot partitions + * after the main and we rely on this feature, otherwise + * scratch_pt won't be released (although this is not a big + * deal). + */ + ptp.pt = kmalloc(TEGRA_PT_LOGICAL_SECTOR_SIZE, GFP_KERNEL); + if (!ptp.pt) + return 0; + + ptp.sector = tegra_pt_sector_address - ptp.boot_offset; + end_sector = ptp.sector + tegra_pt_sectors_num; + + } else if (scratch_pt) { + TEGRA_PT_INFO(&ptp, "using stashed partition table\n"); + + ptp.pt = scratch_pt; + ptp.sector = 0; + end_sector = 1; + + } else { + if (tegra_pt_sector_address < ptp.boot_offset) + return 0; + + ptp.pt = kmalloc(TEGRA_PT_LOGICAL_SECTOR_SIZE, GFP_KERNEL); + if (!ptp.pt) + return 0; + + ptp.sector = tegra_pt_sector_address - ptp.boot_offset; + end_sector = ptp.sector + tegra_pt_sectors_num; + } /* * Partition table is duplicated till the end_sector. @@ -503,9 +591,21 @@ int tegra_partition(struct parsed_partitions *state) ptp.sector += TEGRA_PT_SECTOR_SZ; } - if (ret == 1) + if (ret == 1) { + if (ptp.snapshot_mode) { + ptp.card->quirks |= MMC_QUIRK_RESCAN_MAIN_BLKDEV; + scratch_pt = ptp.pt; + + strlcat(state->pp_buf, + " stashed tegra-partition table\n", PAGE_SIZE); + + return ret; + } + strlcat(state->pp_buf, "\n", PAGE_SIZE); + } + scratch_pt = NULL; kfree(ptp.pt); return ret;