linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table
@ 2020-03-23 16:34 Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 01/10] mmc: core: Add raw_boot_mult field to mmc_ext_csd Dmitry Osipenko
                   ` (11 more replies)
  0 siblings, 12 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:34 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

Some NVIDIA Tegra devices have GPT entry at a wrong location and others may
even not have it at all. So either a custom workaround for GPT parsing or
TegraPT support is needed for those devices if we want to support them in
upstream kernel. The former solution was already rejected [1], let's try
the latter.

[1] https://patchwork.ozlabs.org/patch/1240809/

Big thanks to everyone who helped with figuring out the TegraPT format!

Changelog:

v3: - Fixed "BUG: KASAN: slab-out-of-bounds in tegra_partition". Thanks to
      Peter Geis for noticing the problem.

    - The MMC boot partitions scanning is now opt-in. See this patch:

        mmc: block: Support partition-table scanning on boot partitions

    - The found MMC boot partitions won't be assigned to the MMC boot
      block device ever due to the new GENHD_FL_PART_SCAN_ONCE flag.

      This makes us to ensure that the old behavior of the MMC core is
      preserved for a non-Tegra MMC-block users.

    New patches in v3:

        block: Introduce GENHD_FL_PART_SCAN_ONCE
        mmc: sdhci-tegra: Enable boot partitions scanning on Tegra20 and Tegra30

v2: - Addressed v1 review comments from Stephen Warren by using BIT for
      locating BCT position in IRAM.

    - Added more validations to the TegraPT parser: partition type is
      verified, eMMC instance ID is verified.

    - TegraPT parser now doesn't touch any devices other than eMMC.

    - EKS (encrypted keys) partition is blacklisted now.

    - Implemented eMMC boot partitions scanning. These new patches are
      added in a result:

        mmc: block: Add mmc_bdev_to_part_type() helper
        mmc: block: Add mmc_bdev_to_area_type() helper
        mmc: block: Add MMC_QUIRK_RESCAN_MAIN_BLKDEV
        mmc: block: Enable partition-table scanning for boot partitions
        partitions/tegra: Implement eMMC boot partitions scanning

Dmitry Osipenko (10):
  mmc: core: Add raw_boot_mult field to mmc_ext_csd
  mmc: block: Add mmc_bdev_to_card() helper
  partitions: Introduce NVIDIA Tegra Partition Table
  block: Introduce GENHD_FL_PART_SCAN_ONCE
  mmc: block: Add mmc_bdev_to_part_type() helper
  mmc: block: Add mmc_bdev_to_area_type() helper
  mmc: block: Add MMC_QUIRK_RESCAN_MAIN_BLKDEV
  mmc: block: Support partition-table scanning on boot partitions
  mmc: sdhci-tegra: Enable boot partitions scanning on Tegra20 and
    Tegra30
  partitions/tegra: Implement eMMC boot partitions scanning

 arch/arm/mach-tegra/tegra.c    |  54 +++
 block/genhd.c                  |   2 +-
 block/partition-generic.c      |  13 +-
 block/partitions/Kconfig       |  10 +
 block/partitions/Makefile      |   1 +
 block/partitions/check.c       |   4 +
 block/partitions/tegra.c       | 612 +++++++++++++++++++++++++++++++++
 block/partitions/tegra.h       |   8 +
 drivers/mmc/core/block.c       | 104 ++++++
 drivers/mmc/core/mmc.c         |   2 +
 drivers/mmc/host/sdhci-tegra.c |  10 +-
 include/linux/genhd.h          |  12 +
 include/linux/mmc/blkdev.h     |  15 +
 include/linux/mmc/card.h       |   2 +
 include/linux/mmc/host.h       |   2 +
 include/soc/tegra/bootdata.h   |  46 +++
 include/soc/tegra/common.h     |   9 +
 include/soc/tegra/partition.h  |  91 +++++
 18 files changed, 993 insertions(+), 4 deletions(-)
 create mode 100644 block/partitions/tegra.c
 create mode 100644 block/partitions/tegra.h
 create mode 100644 include/linux/mmc/blkdev.h
 create mode 100644 include/soc/tegra/bootdata.h
 create mode 100644 include/soc/tegra/partition.h

-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 01/10] mmc: core: Add raw_boot_mult field to mmc_ext_csd
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
@ 2020-03-23 16:34 ` Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 02/10] mmc: block: Add mmc_bdev_to_card() helper Dmitry Osipenko
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:34 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

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 <digetx@gmail.com>
---
 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 */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 02/10] mmc: block: Add mmc_bdev_to_card() helper
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 01/10] mmc: core: Add raw_boot_mult field to mmc_ext_csd Dmitry Osipenko
@ 2020-03-23 16:34 ` Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:34 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

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 <digetx@gmail.com>
---
 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 <linux/debugfs.h>
 
 #include <linux/mmc/ioctl.h>
+#include <linux/mmc/blkdev.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
@@ -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 */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 01/10] mmc: core: Add raw_boot_mult field to mmc_ext_csd Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 02/10] mmc: block: Add mmc_bdev_to_card() helper Dmitry Osipenko
@ 2020-03-23 16:34 ` Dmitry Osipenko
  2020-03-23 19:17   ` Michał Mirosław
  2020-03-23 16:34 ` [PATCH v3 04/10] block: Introduce GENHD_FL_PART_SCAN_ONCE Dmitry Osipenko
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:34 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

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 <digetx@gmail.com>
---
 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 <linux/firmware/trusted_foundations.h>
 
+#include <soc/tegra/bootdata.h>
 #include <soc/tegra/fuse.h>
+#include <soc/tegra/partition.h>
 #include <soc/tegra/pmc.h>
 
 #include <asm/firmware.h>
@@ -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 <digetx@gmail.com>
+ *
+ * Credits for the partition table format:
+ *
+ *   Andrey Danin <danindrey@mail.ru>       (Toshiba AC100 TegraPT format)
+ *   Gilles Grandou <gilles@grandou.net>    (Toshiba AC100 TegraPT format)
+ *   Ryan Grachek <ryan@edited.us>          (Google TV "Molly" TegraPT format)
+ *   Stephen Warren <swarren@wwwdotorg.org> (Useful suggestions about eMMC/etc)
+ */
+
+#define pr_fmt(fmt) "tegra-partition: " fmt
+
+#include <linux/blkdev.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <linux/mmc/blkdev.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include <soc/tegra/common.h>
+#include <soc/tegra/partition.h>
+
+#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, &sect);
+		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 <linux/compiler.h>
+#include <linux/types.h>
+
+#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 <linux/types.h>
+
+#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 <linux/compiler.h>
+#include <linux/types.h>
+
+#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__ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 04/10] block: Introduce GENHD_FL_PART_SCAN_ONCE
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
                   ` (2 preceding siblings ...)
  2020-03-23 16:34 ` [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
@ 2020-03-23 16:34 ` Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 05/10] mmc: block: Add mmc_bdev_to_part_type() helper Dmitry Osipenko
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:34 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

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 <digetx@gmail.com>
---
 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);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 05/10] mmc: block: Add mmc_bdev_to_part_type() helper
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
                   ` (3 preceding siblings ...)
  2020-03-23 16:34 ` [PATCH v3 04/10] block: Introduce GENHD_FL_PART_SCAN_ONCE Dmitry Osipenko
@ 2020-03-23 16:34 ` Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 06/10] mmc: block: Add mmc_bdev_to_area_type() helper Dmitry Osipenko
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:34 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

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 <digetx@gmail.com>
---
 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 */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 06/10] mmc: block: Add mmc_bdev_to_area_type() helper
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
                   ` (4 preceding siblings ...)
  2020-03-23 16:34 ` [PATCH v3 05/10] mmc: block: Add mmc_bdev_to_part_type() helper Dmitry Osipenko
@ 2020-03-23 16:34 ` Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 07/10] mmc: block: Add MMC_QUIRK_RESCAN_MAIN_BLKDEV Dmitry Osipenko
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:34 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

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 <digetx@gmail.com>
---
 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 */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 07/10] mmc: block: Add MMC_QUIRK_RESCAN_MAIN_BLKDEV
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
                   ` (5 preceding siblings ...)
  2020-03-23 16:34 ` [PATCH v3 06/10] mmc: block: Add mmc_bdev_to_area_type() helper Dmitry Osipenko
@ 2020-03-23 16:34 ` Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 08/10] mmc: block: Support partition-table scanning on boot partitions Dmitry Osipenko
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:34 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

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 <digetx@gmail.com>
---
 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 */
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 08/10] mmc: block: Support partition-table scanning on boot partitions
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
                   ` (6 preceding siblings ...)
  2020-03-23 16:34 ` [PATCH v3 07/10] mmc: block: Add MMC_QUIRK_RESCAN_MAIN_BLKDEV Dmitry Osipenko
@ 2020-03-23 16:34 ` Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 09/10] mmc: sdhci-tegra: Enable boot partitions scanning on Tegra20 and Tegra30 Dmitry Osipenko
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:34 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

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 <digetx@gmail.com>
---
 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;
 };
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 09/10] mmc: sdhci-tegra: Enable boot partitions scanning on Tegra20 and Tegra30
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
                   ` (7 preceding siblings ...)
  2020-03-23 16:34 ` [PATCH v3 08/10] mmc: block: Support partition-table scanning on boot partitions Dmitry Osipenko
@ 2020-03-23 16:34 ` Dmitry Osipenko
  2020-03-23 16:34 ` [PATCH v3 10/10] partitions/tegra: Implement eMMC boot partitions scanning Dmitry Osipenko
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:34 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

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 <digetx@gmail.com>
---
 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",
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 10/10] partitions/tegra: Implement eMMC boot partitions scanning
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
                   ` (8 preceding siblings ...)
  2020-03-23 16:34 ` [PATCH v3 09/10] mmc: sdhci-tegra: Enable boot partitions scanning on Tegra20 and Tegra30 Dmitry Osipenko
@ 2020-03-23 16:34 ` Dmitry Osipenko
  2020-03-23 16:49 ` [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
  2020-03-23 18:07 ` Michał Mirosław
  11 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:34 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

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 <digetx@gmail.com>
---
 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 <linux/mmc/blkdev.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
 
 #include <soc/tegra/common.h>
 #include <soc/tegra/partition.h>
@@ -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;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
                   ` (9 preceding siblings ...)
  2020-03-23 16:34 ` [PATCH v3 10/10] partitions/tegra: Implement eMMC boot partitions scanning Dmitry Osipenko
@ 2020-03-23 16:49 ` Dmitry Osipenko
  2020-03-23 18:07 ` Michał Mirosław
  11 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 16:49 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Stephen Warren, Nicolas Chauvet, Ulf Hansson, Adrian Hunter,
	Billy Laws
  Cc: linux-tegra, linux-block, Andrey Danin, Gilles Grandou,
	Ryan Grachek, linux-mmc, linux-kernel

23.03.2020 19:34, Dmitry Osipenko пишет:
> Some NVIDIA Tegra devices have GPT entry at a wrong location and others may
> even not have it at all. So either a custom workaround for GPT parsing or
> TegraPT support is needed for those devices if we want to support them in
> upstream kernel. The former solution was already rejected [1], let's try
> the latter.
> 
> [1] https://patchwork.ozlabs.org/patch/1240809/
> 
> Big thanks to everyone who helped with figuring out the TegraPT format!
> 
> Changelog:
> 
> v3: - Fixed "BUG: KASAN: slab-out-of-bounds in tegra_partition". Thanks to
>       Peter Geis for noticing the problem.
> 
>     - The MMC boot partitions scanning is now opt-in. See this patch:
> 
>         mmc: block: Support partition-table scanning on boot partitions
> 
>     - The found MMC boot partitions won't be assigned to the MMC boot
>       block device ever due to the new GENHD_FL_PART_SCAN_ONCE flag.
> 
>       This makes us to ensure that the old behavior of the MMC core is
>       preserved for a non-Tegra MMC-block users.
> 
>     New patches in v3:
> 
>         block: Introduce GENHD_FL_PART_SCAN_ONCE
>         mmc: sdhci-tegra: Enable boot partitions scanning on Tegra20 and Tegra30

I forgot to mention that the TegraPT Kconfig entry now depends on MMC,
which was suggested by Randy Dunlap in the review comment to the v2.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table
  2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
                   ` (10 preceding siblings ...)
  2020-03-23 16:49 ` [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
@ 2020-03-23 18:07 ` Michał Mirosław
  2020-03-23 19:44   ` Dmitry Osipenko
  11 siblings, 1 reply; 20+ messages in thread
From: Michał Mirosław @ 2020-03-23 18:07 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, David Heidelberg,
	Peter Geis, Stephen Warren, Nicolas Chauvet, Ulf Hansson,
	Adrian Hunter, Billy Laws, linux-tegra, linux-block,
	Andrey Danin, Gilles Grandou, Ryan Grachek, linux-mmc,
	linux-kernel

On Mon, Mar 23, 2020 at 07:34:21PM +0300, Dmitry Osipenko wrote:
> Some NVIDIA Tegra devices have GPT entry at a wrong location and others may
> even not have it at all. So either a custom workaround for GPT parsing or
> TegraPT support is needed for those devices if we want to support them in
> upstream kernel. The former solution was already rejected [1], let's try
> the latter.
[...]

Hi Dmitry,

This amusing use of whole-device offsets in the TegraPT makes it take
a lot of hacks to support it. Have you considered to first join the MMC
hardware partitions using DM and its linear target and only then processing
the partition table dividing just the merged device?

Best Regards,
Michał Mirosław

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table
  2020-03-23 16:34 ` [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
@ 2020-03-23 19:17   ` Michał Mirosław
  2020-03-23 19:59     ` Dmitry Osipenko
  0 siblings, 1 reply; 20+ messages in thread
From: Michał Mirosław @ 2020-03-23 19:17 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, David Heidelberg,
	Peter Geis, Stephen Warren, Nicolas Chauvet, Ulf Hansson,
	Adrian Hunter, Billy Laws, linux-tegra, linux-block,
	Andrey Danin, Gilles Grandou, Ryan Grachek, linux-mmc,
	linux-kernel

On Mon, Mar 23, 2020 at 07:34:24PM +0300, Dmitry Osipenko wrote:
> 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 <digetx@gmail.com>
> ---
>  arch/arm/mach-tegra/tegra.c   |  54 ++++
[...]

Please split off this part and make the information available to
userspace (pt_addr + pt_size) if found. This would make it easier
to support use the partition table later in initrd instead.

Best Regards
Michał Mirosław

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table
  2020-03-23 18:07 ` Michał Mirosław
@ 2020-03-23 19:44   ` Dmitry Osipenko
  0 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 19:44 UTC (permalink / raw)
  To: Michał Mirosław
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, David Heidelberg,
	Peter Geis, Stephen Warren, Nicolas Chauvet, Ulf Hansson,
	Adrian Hunter, Billy Laws, linux-tegra, linux-block,
	Andrey Danin, Gilles Grandou, Ryan Grachek, linux-mmc,
	linux-kernel

23.03.2020 21:07, Michał Mirosław пишет:
> On Mon, Mar 23, 2020 at 07:34:21PM +0300, Dmitry Osipenko wrote:
>> Some NVIDIA Tegra devices have GPT entry at a wrong location and others may
>> even not have it at all. So either a custom workaround for GPT parsing or
>> TegraPT support is needed for those devices if we want to support them in
>> upstream kernel. The former solution was already rejected [1], let's try
>> the latter.
> [...]
> 
> Hi Dmitry,
> 
> This amusing use of whole-device offsets in the TegraPT makes it take
> a lot of hacks to support it. Have you considered to first join the MMC
> hardware partitions using DM and its linear target and only then processing
> the partition table dividing just the merged device?

Hello Michał,

Thank you very much for the suggestion! I had a thought about that and
it's not apparent to me how to determine when the joining needs to be
done and when not.

The joining shouldn't be done for devices that aren't booting from eMMC
because then the alt GPT entry will be found on a joined block device
and this shouldn't happen.

Actually, maybe we could create a new MMC device-tree property, telling
that the joining needs to be performed. Perhaps this indeed could result
in a less hackery, I'll give it a try and see how it goes.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table
  2020-03-23 19:17   ` Michał Mirosław
@ 2020-03-23 19:59     ` Dmitry Osipenko
  2020-03-23 21:35       ` Michał Mirosław
  0 siblings, 1 reply; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 19:59 UTC (permalink / raw)
  To: Michał Mirosław
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, David Heidelberg,
	Peter Geis, Stephen Warren, Nicolas Chauvet, Ulf Hansson,
	Adrian Hunter, Billy Laws, linux-tegra, linux-block,
	Andrey Danin, Gilles Grandou, Ryan Grachek, linux-mmc,
	linux-kernel

23.03.2020 22:17, Michał Mirosław пишет:
> On Mon, Mar 23, 2020 at 07:34:24PM +0300, Dmitry Osipenko wrote:
>> 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 <digetx@gmail.com>
>> ---
>>  arch/arm/mach-tegra/tegra.c   |  54 ++++
> [...]
> 
> Please split off this part and make the information available to
> userspace (pt_addr + pt_size) if found. This would make it easier
> to support use the partition table later in initrd instead.

Please clarify what do you mean by "use the partition table later in
initrd instead".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table
  2020-03-23 19:59     ` Dmitry Osipenko
@ 2020-03-23 21:35       ` Michał Mirosław
  2020-03-23 23:22         ` Dmitry Osipenko
  0 siblings, 1 reply; 20+ messages in thread
From: Michał Mirosław @ 2020-03-23 21:35 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, David Heidelberg,
	Peter Geis, Stephen Warren, Nicolas Chauvet, Ulf Hansson,
	Adrian Hunter, Billy Laws, linux-tegra, linux-block,
	Andrey Danin, Gilles Grandou, Ryan Grachek, linux-mmc,
	linux-kernel

On Mon, Mar 23, 2020 at 10:59:52PM +0300, Dmitry Osipenko wrote:
> 23.03.2020 22:17, Michał Mirosław пишет:
> > On Mon, Mar 23, 2020 at 07:34:24PM +0300, Dmitry Osipenko wrote:
> >> 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 <digetx@gmail.com>
> >> ---
> >>  arch/arm/mach-tegra/tegra.c   |  54 ++++
> > [...]
> > 
> > Please split off this part and make the information available to
> > userspace (pt_addr + pt_size) if found. This would make it easier
> > to support use the partition table later in initrd instead.
> 
> Please clarify what do you mean by "use the partition table later in
> initrd instead".

Configure device-mapper to span eMMC boot+data partitions and then ask
(modified) kpartx to partition the resulting device. All before rootfs
is mounted and switched to in initrd.

Best Regards
Michał Mirosław

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table
  2020-03-23 21:35       ` Michał Mirosław
@ 2020-03-23 23:22         ` Dmitry Osipenko
  2020-03-24 20:52           ` Michał Mirosław
  0 siblings, 1 reply; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-23 23:22 UTC (permalink / raw)
  To: Michał Mirosław
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, David Heidelberg,
	Peter Geis, Stephen Warren, Nicolas Chauvet, Ulf Hansson,
	Adrian Hunter, Billy Laws, linux-tegra, linux-block,
	Andrey Danin, Gilles Grandou, Ryan Grachek, linux-mmc,
	linux-kernel

24.03.2020 00:35, Michał Mirosław пишет:
> On Mon, Mar 23, 2020 at 10:59:52PM +0300, Dmitry Osipenko wrote:
>> 23.03.2020 22:17, Michał Mirosław пишет:
>>> On Mon, Mar 23, 2020 at 07:34:24PM +0300, Dmitry Osipenko wrote:
>>>> 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 <digetx@gmail.com>
>>>> ---
>>>>  arch/arm/mach-tegra/tegra.c   |  54 ++++
>>> [...]
>>>
>>> Please split off this part and make the information available to
>>> userspace (pt_addr + pt_size) if found. This would make it easier
>>> to support use the partition table later in initrd instead.
>>
>> Please clarify what do you mean by "use the partition table later in
>> initrd instead".
> 
> Configure device-mapper to span eMMC boot+data partitions and then ask
> (modified) kpartx to partition the resulting device. All before rootfs
> is mounted and switched to in initrd.

The whole point of this series is to make partition handling generic in
the kernel, avoiding the need to customize anything.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table
  2020-03-23 23:22         ` Dmitry Osipenko
@ 2020-03-24 20:52           ` Michał Mirosław
  2020-03-25  0:27             ` Dmitry Osipenko
  0 siblings, 1 reply; 20+ messages in thread
From: Michał Mirosław @ 2020-03-24 20:52 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, David Heidelberg,
	Peter Geis, Stephen Warren, Nicolas Chauvet, Ulf Hansson,
	Adrian Hunter, Billy Laws, linux-tegra, linux-block,
	Andrey Danin, Gilles Grandou, Ryan Grachek, linux-mmc,
	linux-kernel

On Tue, Mar 24, 2020 at 02:22:34AM +0300, Dmitry Osipenko wrote:
> 24.03.2020 00:35, Michał Mirosław пишет:
> > On Mon, Mar 23, 2020 at 10:59:52PM +0300, Dmitry Osipenko wrote:
> >> 23.03.2020 22:17, Michał Mirosław пишет:
> >>> On Mon, Mar 23, 2020 at 07:34:24PM +0300, Dmitry Osipenko wrote:
> >>>> 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 <digetx@gmail.com>
> >>>> ---
> >>>>  arch/arm/mach-tegra/tegra.c   |  54 ++++
> >>> [...]
> >>>
> >>> Please split off this part and make the information available to
> >>> userspace (pt_addr + pt_size) if found. This would make it easier
> >>> to support use the partition table later in initrd instead.
> >>
> >> Please clarify what do you mean by "use the partition table later in
> >> initrd instead".
> > 
> > Configure device-mapper to span eMMC boot+data partitions and then ask
> > (modified) kpartx to partition the resulting device. All before rootfs
> > is mounted and switched to in initrd.
> 
> The whole point of this series is to make partition handling generic in
> the kernel, avoiding the need to customize anything.

Yes, but at least for diagnostic purposes, it would be nice to have the
values from BCT exposed somewhere in /sys.

Best Regards,
Michał Mirosław

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table
  2020-03-24 20:52           ` Michał Mirosław
@ 2020-03-25  0:27             ` Dmitry Osipenko
  0 siblings, 0 replies; 20+ messages in thread
From: Dmitry Osipenko @ 2020-03-25  0:27 UTC (permalink / raw)
  To: Michał Mirosław
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, David Heidelberg,
	Peter Geis, Stephen Warren, Nicolas Chauvet, Ulf Hansson,
	Adrian Hunter, Billy Laws, linux-tegra, linux-block,
	Andrey Danin, Gilles Grandou, Ryan Grachek, linux-mmc,
	linux-kernel

24.03.2020 23:52, Michał Mirosław пишет:
> On Tue, Mar 24, 2020 at 02:22:34AM +0300, Dmitry Osipenko wrote:
>> 24.03.2020 00:35, Michał Mirosław пишет:
>>> On Mon, Mar 23, 2020 at 10:59:52PM +0300, Dmitry Osipenko wrote:
>>>> 23.03.2020 22:17, Michał Mirosław пишет:
>>>>> On Mon, Mar 23, 2020 at 07:34:24PM +0300, Dmitry Osipenko wrote:
>>>>>> 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 <digetx@gmail.com>
>>>>>> ---
>>>>>>  arch/arm/mach-tegra/tegra.c   |  54 ++++
>>>>> [...]
>>>>>
>>>>> Please split off this part and make the information available to
>>>>> userspace (pt_addr + pt_size) if found. This would make it easier
>>>>> to support use the partition table later in initrd instead.
>>>>
>>>> Please clarify what do you mean by "use the partition table later in
>>>> initrd instead".
>>>
>>> Configure device-mapper to span eMMC boot+data partitions and then ask
>>> (modified) kpartx to partition the resulting device. All before rootfs
>>> is mounted and switched to in initrd.
>>
>> The whole point of this series is to make partition handling generic in
>> the kernel, avoiding the need to customize anything.
> 
> Yes, but at least for diagnostic purposes, it would be nice to have the
> values from BCT exposed somewhere in /sys.

It could be useful indeed, but for now I'm not sure that it should be a
part of this patchset. I'll keep it mind, thank you for the suggestion.

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2020-03-25  0:27 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-23 16:34 [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
2020-03-23 16:34 ` [PATCH v3 01/10] mmc: core: Add raw_boot_mult field to mmc_ext_csd Dmitry Osipenko
2020-03-23 16:34 ` [PATCH v3 02/10] mmc: block: Add mmc_bdev_to_card() helper Dmitry Osipenko
2020-03-23 16:34 ` [PATCH v3 03/10] partitions: Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
2020-03-23 19:17   ` Michał Mirosław
2020-03-23 19:59     ` Dmitry Osipenko
2020-03-23 21:35       ` Michał Mirosław
2020-03-23 23:22         ` Dmitry Osipenko
2020-03-24 20:52           ` Michał Mirosław
2020-03-25  0:27             ` Dmitry Osipenko
2020-03-23 16:34 ` [PATCH v3 04/10] block: Introduce GENHD_FL_PART_SCAN_ONCE Dmitry Osipenko
2020-03-23 16:34 ` [PATCH v3 05/10] mmc: block: Add mmc_bdev_to_part_type() helper Dmitry Osipenko
2020-03-23 16:34 ` [PATCH v3 06/10] mmc: block: Add mmc_bdev_to_area_type() helper Dmitry Osipenko
2020-03-23 16:34 ` [PATCH v3 07/10] mmc: block: Add MMC_QUIRK_RESCAN_MAIN_BLKDEV Dmitry Osipenko
2020-03-23 16:34 ` [PATCH v3 08/10] mmc: block: Support partition-table scanning on boot partitions Dmitry Osipenko
2020-03-23 16:34 ` [PATCH v3 09/10] mmc: sdhci-tegra: Enable boot partitions scanning on Tegra20 and Tegra30 Dmitry Osipenko
2020-03-23 16:34 ` [PATCH v3 10/10] partitions/tegra: Implement eMMC boot partitions scanning Dmitry Osipenko
2020-03-23 16:49 ` [PATCH v3 00/10] Introduce NVIDIA Tegra Partition Table Dmitry Osipenko
2020-03-23 18:07 ` Michał Mirosław
2020-03-23 19:44   ` Dmitry Osipenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).