linux-efi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/3] Support EFI partition on NVIDIA Tegra devices
@ 2021-08-17  1:36 Dmitry Osipenko
  2021-08-17  1:36 ` [PATCH v4 1/3] mmc: core: Add raw_boot_mult field to mmc_ext_csd Dmitry Osipenko
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Dmitry Osipenko @ 2021-08-17  1:36 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Ulf Hansson, Adrian Hunter, Christoph Hellwig, Davidlohr Bueso,
	Ion Agorria, Svyatoslav Ryhel
  Cc: linux-tegra, linux-block, linux-efi

This series adds the most minimal EFI partition support for NVIDIA Tegra
consumer devices, like Android tablets and game consoles, making theirs
EMMC accessible out-of-the-box using downstream bootloader and mainline
Linux kernel.  EMMC now works on Acer A500 tablet and Ouya game console
that are already well supported in mainline and internal storage is the
only biggest thing left to support.

Changelog:

v4: - Rebased on top of recent linux-next.

v3: - Removed unnecessary v1 hunk that was left by accident in efi.c of v2.

v2: - This is continuation of [1] where Davidlohr Bueso suggested that it
      should be better to avoid supporting in mainline the custom gpt_sector
      kernel cmdline parameter that downstream Android kernels use.  We can
      do this for the devices that are already mainlined, so I dropped the
      cmdline from the v2 and left only the variant with a fixed GPT address.

[1] https://lore.kernel.org/linux-efi/20210327212100.3834-3-digetx@gmail.com/T/

Dmitry Osipenko (3):
  mmc: core: Add raw_boot_mult field to mmc_ext_csd
  mmc: block: Add mmc_bdev_to_card() helper
  partitions/efi: Support NVIDIA Tegra devices

 block/partitions/Kconfig   |  8 ++++
 block/partitions/Makefile  |  1 +
 block/partitions/check.h   |  2 +
 block/partitions/core.c    |  3 ++
 block/partitions/efi.c     |  9 +++++
 block/partitions/tegra.c   | 75 ++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/block.c   | 15 ++++++++
 drivers/mmc/core/mmc.c     |  2 +
 include/linux/mmc/blkdev.h | 13 +++++++
 include/linux/mmc/card.h   |  1 +
 10 files changed, 129 insertions(+)
 create mode 100644 block/partitions/tegra.c
 create mode 100644 include/linux/mmc/blkdev.h

-- 
2.32.0


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

* [PATCH v4 1/3] mmc: core: Add raw_boot_mult field to mmc_ext_csd
  2021-08-17  1:36 [PATCH v4 0/3] Support EFI partition on NVIDIA Tegra devices Dmitry Osipenko
@ 2021-08-17  1:36 ` Dmitry Osipenko
  2021-08-17  1:36 ` [PATCH v4 2/3] mmc: block: Add mmc_bdev_to_card() helper Dmitry Osipenko
  2021-08-17  1:36 ` [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices Dmitry Osipenko
  2 siblings, 0 replies; 12+ messages in thread
From: Dmitry Osipenko @ 2021-08-17  1:36 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Ulf Hansson, Adrian Hunter, Christoph Hellwig, Davidlohr Bueso,
	Ion Agorria, Svyatoslav Ryhel
  Cc: linux-tegra, linux-block, linux-efi

Bootloader of NVIDIA Tegra devices 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.  The offset needs to
be known in order to find the EFI entry on EMMC storage of Tegra devices.

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 838726b68ff3..29e58ffae379 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -418,6 +418,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 74e6c0624d27..37f975875102 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -109,6 +109,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.32.0


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

* [PATCH v4 2/3] mmc: block: Add mmc_bdev_to_card() helper
  2021-08-17  1:36 [PATCH v4 0/3] Support EFI partition on NVIDIA Tegra devices Dmitry Osipenko
  2021-08-17  1:36 ` [PATCH v4 1/3] mmc: core: Add raw_boot_mult field to mmc_ext_csd Dmitry Osipenko
@ 2021-08-17  1:36 ` Dmitry Osipenko
  2021-08-17  4:37   ` Christoph Hellwig
  2021-08-17  1:36 ` [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices Dmitry Osipenko
  2 siblings, 1 reply; 12+ messages in thread
From: Dmitry Osipenko @ 2021-08-17  1:36 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Ulf Hansson, Adrian Hunter, Christoph Hellwig, Davidlohr Bueso,
	Ion Agorria, Svyatoslav Ryhel
  Cc: linux-tegra, linux-block, linux-efi

Add mmc_bdev_to_card() helper which is needed for checking EMMC
parameters by partition table parser in order to find EFI entry
on NVIDIA Tegra devices.

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 672cc505ce37..7e9a486073fd 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -42,6 +42,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>
@@ -357,6 +358,20 @@ static const struct attribute_group *mmc_disk_attr_groups[] = {
 	NULL,
 };
 
+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.32.0


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

* [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices
  2021-08-17  1:36 [PATCH v4 0/3] Support EFI partition on NVIDIA Tegra devices Dmitry Osipenko
  2021-08-17  1:36 ` [PATCH v4 1/3] mmc: core: Add raw_boot_mult field to mmc_ext_csd Dmitry Osipenko
  2021-08-17  1:36 ` [PATCH v4 2/3] mmc: block: Add mmc_bdev_to_card() helper Dmitry Osipenko
@ 2021-08-17  1:36 ` Dmitry Osipenko
  2021-08-17  4:43   ` Christoph Hellwig
                     ` (2 more replies)
  2 siblings, 3 replies; 12+ messages in thread
From: Dmitry Osipenko @ 2021-08-17  1:36 UTC (permalink / raw)
  To: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Ulf Hansson, Adrian Hunter, Christoph Hellwig, Davidlohr Bueso,
	Ion Agorria, Svyatoslav Ryhel
  Cc: linux-tegra, linux-block, linux-efi

NVIDIA Tegra consumer devices have EMMC storage that has GPT entry at a
non-standard location. Support looking up GPT entry at a special sector
to enable such devices.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 block/partitions/Kconfig  |  8 +++++
 block/partitions/Makefile |  1 +
 block/partitions/check.h  |  2 ++
 block/partitions/core.c   |  3 ++
 block/partitions/efi.c    |  9 +++++
 block/partitions/tegra.c  | 75 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 98 insertions(+)
 create mode 100644 block/partitions/tegra.c

diff --git a/block/partitions/Kconfig b/block/partitions/Kconfig
index 278593b8e4e9..5db25e7efbb7 100644
--- a/block/partitions/Kconfig
+++ b/block/partitions/Kconfig
@@ -267,3 +267,11 @@ 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 EFI_PARTITION && MMC_BLOCK && (ARCH_TEGRA || COMPILE_TEST)
+	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 a7f05cdb02a8..83cb70c6d08d 100644
--- a/block/partitions/Makefile
+++ b/block/partitions/Makefile
@@ -20,3 +20,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.h b/block/partitions/check.h
index d5b28e309d64..bd4b66443cf4 100644
--- a/block/partitions/check.h
+++ b/block/partitions/check.h
@@ -22,6 +22,7 @@ struct parsed_partitions {
 	int limit;
 	bool access_beyond_eod;
 	char *pp_buf;
+	sector_t force_gpt_sector;
 };
 
 typedef struct {
@@ -67,4 +68,5 @@ int osf_partition(struct parsed_partitions *state);
 int sgi_partition(struct parsed_partitions *state);
 int sun_partition(struct parsed_partitions *state);
 int sysv68_partition(struct parsed_partitions *state);
+int tegra_partition_forced_gpt(struct parsed_partitions *state);
 int ultrix_partition(struct parsed_partitions *state);
diff --git a/block/partitions/core.c b/block/partitions/core.c
index 9265936df77e..bbfbb1621581 100644
--- a/block/partitions/core.c
+++ b/block/partitions/core.c
@@ -82,6 +82,9 @@ static int (*check_part[])(struct parsed_partitions *) = {
 #endif
 #ifdef CONFIG_SYSV68_PARTITION
 	sysv68_partition,
+#endif
+#ifdef CONFIG_TEGRA_PARTITION
+	tegra_partition_forced_gpt,
 #endif
 	NULL
 };
diff --git a/block/partitions/efi.c b/block/partitions/efi.c
index aaa3dc487cb5..4ad151176204 100644
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -619,6 +619,15 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
         if (!good_agpt && force_gpt)
                 good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes);
 
+	/*
+	 * The force_gpt_sector is used by NVIDIA Tegra partition parser in
+	 * order to convey a non-standard location of the GPT entry for lookup.
+	 * By default force_gpt_sector is set to 0 and has no effect.
+	 */
+	if (!good_agpt && force_gpt && state->force_gpt_sector)
+		good_agpt = is_gpt_valid(state, state->force_gpt_sector,
+					 &agpt, &aptes);
+
         /* The obviously unsuccessful case */
         if (!good_pgpt && !good_agpt)
                 goto fail;
diff --git a/block/partitions/tegra.c b/block/partitions/tegra.c
new file mode 100644
index 000000000000..4937e9f62398
--- /dev/null
+++ b/block/partitions/tegra.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#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/mmc/blkdev.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include <soc/tegra/common.h>
+
+#include "check.h"
+
+static const struct of_device_id tegra_sdhci_match[] = {
+	{ .compatible = "nvidia,tegra20-sdhci", },
+	{ .compatible = "nvidia,tegra30-sdhci", },
+	{ .compatible = "nvidia,tegra114-sdhci", },
+	{ .compatible = "nvidia,tegra124-sdhci", },
+	{}
+};
+
+int tegra_partition_forced_gpt(struct parsed_partitions *state)
+{
+	struct gendisk *disk = state->disk;
+	struct block_device *bdev = disk->part0;
+	struct mmc_card *card = mmc_bdev_to_card(bdev);
+	int ret, boot_offset;
+
+	if (!soc_is_tegra())
+		return 0;
+
+	/* filter out unrelated and untested boot sources */
+	if (!card || card->ext_csd.rev < 3 ||
+	    !mmc_card_is_blockaddr(card) ||
+	     mmc_card_is_removable(card->host) ||
+	     bdev_logical_block_size(bdev) != SZ_512 ||
+	    !of_match_node(tegra_sdhci_match, card->host->parent->of_node)) {
+		pr_debug("%s: unexpected boot source\n", disk->disk_name);
+		return 0;
+	}
+
+	/*
+	 * 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.
+	 */
+	boot_offset = card->ext_csd.raw_boot_mult * SZ_128K /
+		      SZ_512 * MMC_NUM_BOOT_PARTITION;
+
+	/*
+	 * The fixed GPT entry address is calculated like this:
+	 *
+	 * gpt_sector = ext_csd.sectors_num - ext_csd.boot_sectors_num - 1
+	 *
+	 * This algorithm is defined by NVIDIA and used by Android devices.
+	 */
+	state->force_gpt_sector  = get_capacity(disk);
+	state->force_gpt_sector -= boot_offset + 1;
+
+	ret = efi_partition(state);
+	state->force_gpt_sector = 0;
+
+	return ret;
+}
-- 
2.32.0


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

* Re: [PATCH v4 2/3] mmc: block: Add mmc_bdev_to_card() helper
  2021-08-17  1:36 ` [PATCH v4 2/3] mmc: block: Add mmc_bdev_to_card() helper Dmitry Osipenko
@ 2021-08-17  4:37   ` Christoph Hellwig
  2021-08-17 16:10     ` Dmitry Osipenko
  0 siblings, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2021-08-17  4:37 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, Micha?? Miros??aw,
	David Heidelberg, Peter Geis, Ulf Hansson, Adrian Hunter,
	Christoph Hellwig, Davidlohr Bueso, Ion Agorria,
	Svyatoslav Ryhel, linux-tegra, linux-block, linux-efi

On Tue, Aug 17, 2021 at 04:36:42AM +0300, Dmitry Osipenko wrote:
> +	if (bdev->bd_disk->major != MMC_BLOCK_MAJOR)
> +		return NULL;

The major is a dangerous check as we have all kinds of ways to override
it.  Please check the block device operations as they must be unique.

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

* Re: [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices
  2021-08-17  1:36 ` [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices Dmitry Osipenko
@ 2021-08-17  4:43   ` Christoph Hellwig
  2021-08-17 16:11     ` Dmitry Osipenko
  2021-08-17  8:24   ` Ulf Hansson
  2021-08-17 14:11   ` Thierry Reding
  2 siblings, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2021-08-17  4:43 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, Micha?? Miros??aw,
	David Heidelberg, Peter Geis, Ulf Hansson, Adrian Hunter,
	Christoph Hellwig, Davidlohr Bueso, Ion Agorria,
	Svyatoslav Ryhel, linux-tegra, linux-block, linux-efi

Just curious, why not add a new block_device_operations member
'alternative_gpt_sector', then move all the code calculating it to
the mmc layer?

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

* Re: [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices
  2021-08-17  1:36 ` [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices Dmitry Osipenko
  2021-08-17  4:43   ` Christoph Hellwig
@ 2021-08-17  8:24   ` Ulf Hansson
  2021-08-17 16:16     ` Dmitry Osipenko
  2021-08-17 14:11   ` Thierry Reding
  2 siblings, 1 reply; 12+ messages in thread
From: Ulf Hansson @ 2021-08-17  8:24 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Adrian Hunter, Christoph Hellwig, Davidlohr Bueso, Ion Agorria,
	Svyatoslav Ryhel, linux-tegra, linux-block, linux-efi

On Tue, 17 Aug 2021 at 03:37, Dmitry Osipenko <digetx@gmail.com> wrote:
>
> NVIDIA Tegra consumer devices have EMMC storage that has GPT entry at a
> non-standard location. Support looking up GPT entry at a special sector
> to enable such devices.
>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  block/partitions/Kconfig  |  8 +++++
>  block/partitions/Makefile |  1 +
>  block/partitions/check.h  |  2 ++
>  block/partitions/core.c   |  3 ++
>  block/partitions/efi.c    |  9 +++++
>  block/partitions/tegra.c  | 75 +++++++++++++++++++++++++++++++++++++++
>  6 files changed, 98 insertions(+)
>  create mode 100644 block/partitions/tegra.c
>
> diff --git a/block/partitions/Kconfig b/block/partitions/Kconfig
> index 278593b8e4e9..5db25e7efbb7 100644
> --- a/block/partitions/Kconfig
> +++ b/block/partitions/Kconfig
> @@ -267,3 +267,11 @@ 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 EFI_PARTITION && MMC_BLOCK && (ARCH_TEGRA || COMPILE_TEST)
> +       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 a7f05cdb02a8..83cb70c6d08d 100644
> --- a/block/partitions/Makefile
> +++ b/block/partitions/Makefile
> @@ -20,3 +20,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.h b/block/partitions/check.h
> index d5b28e309d64..bd4b66443cf4 100644
> --- a/block/partitions/check.h
> +++ b/block/partitions/check.h
> @@ -22,6 +22,7 @@ struct parsed_partitions {
>         int limit;
>         bool access_beyond_eod;
>         char *pp_buf;
> +       sector_t force_gpt_sector;
>  };
>
>  typedef struct {
> @@ -67,4 +68,5 @@ int osf_partition(struct parsed_partitions *state);
>  int sgi_partition(struct parsed_partitions *state);
>  int sun_partition(struct parsed_partitions *state);
>  int sysv68_partition(struct parsed_partitions *state);
> +int tegra_partition_forced_gpt(struct parsed_partitions *state);
>  int ultrix_partition(struct parsed_partitions *state);
> diff --git a/block/partitions/core.c b/block/partitions/core.c
> index 9265936df77e..bbfbb1621581 100644
> --- a/block/partitions/core.c
> +++ b/block/partitions/core.c
> @@ -82,6 +82,9 @@ static int (*check_part[])(struct parsed_partitions *) = {
>  #endif
>  #ifdef CONFIG_SYSV68_PARTITION
>         sysv68_partition,
> +#endif
> +#ifdef CONFIG_TEGRA_PARTITION
> +       tegra_partition_forced_gpt,
>  #endif
>         NULL
>  };
> diff --git a/block/partitions/efi.c b/block/partitions/efi.c
> index aaa3dc487cb5..4ad151176204 100644
> --- a/block/partitions/efi.c
> +++ b/block/partitions/efi.c
> @@ -619,6 +619,15 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
>          if (!good_agpt && force_gpt)
>                  good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes);
>
> +       /*
> +        * The force_gpt_sector is used by NVIDIA Tegra partition parser in
> +        * order to convey a non-standard location of the GPT entry for lookup.
> +        * By default force_gpt_sector is set to 0 and has no effect.
> +        */
> +       if (!good_agpt && force_gpt && state->force_gpt_sector)
> +               good_agpt = is_gpt_valid(state, state->force_gpt_sector,
> +                                        &agpt, &aptes);
> +
>          /* The obviously unsuccessful case */
>          if (!good_pgpt && !good_agpt)
>                  goto fail;
> diff --git a/block/partitions/tegra.c b/block/partitions/tegra.c
> new file mode 100644
> index 000000000000..4937e9f62398
> --- /dev/null
> +++ b/block/partitions/tegra.c
> @@ -0,0 +1,75 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#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/mmc/blkdev.h>
> +#include <linux/mmc/card.h>
> +#include <linux/mmc/host.h>
> +
> +#include <soc/tegra/common.h>
> +
> +#include "check.h"
> +
> +static const struct of_device_id tegra_sdhci_match[] = {
> +       { .compatible = "nvidia,tegra20-sdhci", },
> +       { .compatible = "nvidia,tegra30-sdhci", },
> +       { .compatible = "nvidia,tegra114-sdhci", },
> +       { .compatible = "nvidia,tegra124-sdhci", },
> +       {}
> +};
> +
> +int tegra_partition_forced_gpt(struct parsed_partitions *state)
> +{
> +       struct gendisk *disk = state->disk;
> +       struct block_device *bdev = disk->part0;
> +       struct mmc_card *card = mmc_bdev_to_card(bdev);
> +       int ret, boot_offset;
> +
> +       if (!soc_is_tegra())
> +               return 0;
> +
> +       /* filter out unrelated and untested boot sources */
> +       if (!card || card->ext_csd.rev < 3 ||
> +           !mmc_card_is_blockaddr(card) ||
> +            mmc_card_is_removable(card->host) ||
> +            bdev_logical_block_size(bdev) != SZ_512 ||
> +           !of_match_node(tegra_sdhci_match, card->host->parent->of_node)) {

I think you need to convince Rob Herring that the location of the GPT
table in the eMMC flash memory is allowed to depend on the compatible
string of the sdhci controller.

In any case, I think Christoph raised some interesting ideas in his
reply. Moving more of this code into the mmc core/block layer seems
reasonable to me as well.

> +               pr_debug("%s: unexpected boot source\n", disk->disk_name);
> +               return 0;
> +       }
> +
> +       /*
> +        * 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.
> +        */
> +       boot_offset = card->ext_csd.raw_boot_mult * SZ_128K /
> +                     SZ_512 * MMC_NUM_BOOT_PARTITION;
> +
> +       /*
> +        * The fixed GPT entry address is calculated like this:
> +        *
> +        * gpt_sector = ext_csd.sectors_num - ext_csd.boot_sectors_num - 1
> +        *
> +        * This algorithm is defined by NVIDIA and used by Android devices.
> +        */
> +       state->force_gpt_sector  = get_capacity(disk);
> +       state->force_gpt_sector -= boot_offset + 1;
> +
> +       ret = efi_partition(state);
> +       state->force_gpt_sector = 0;
> +
> +       return ret;
> +}
> --
> 2.32.0
>

Kind regards
Uffe

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

* Re: [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices
  2021-08-17  1:36 ` [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices Dmitry Osipenko
  2021-08-17  4:43   ` Christoph Hellwig
  2021-08-17  8:24   ` Ulf Hansson
@ 2021-08-17 14:11   ` Thierry Reding
  2021-08-17 16:10     ` Dmitry Osipenko
  2 siblings, 1 reply; 12+ messages in thread
From: Thierry Reding @ 2021-08-17 14:11 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jens Axboe, Jonathan Hunter, Michał Mirosław,
	David Heidelberg, Peter Geis, Ulf Hansson, Adrian Hunter,
	Christoph Hellwig, Davidlohr Bueso, Ion Agorria,
	Svyatoslav Ryhel, linux-tegra, linux-block, linux-efi

[-- Attachment #1: Type: text/plain, Size: 1217 bytes --]

On Tue, Aug 17, 2021 at 04:36:43AM +0300, Dmitry Osipenko wrote:
[...]
> diff --git a/block/partitions/tegra.c b/block/partitions/tegra.c
> new file mode 100644
> index 000000000000..4937e9f62398
> --- /dev/null
> +++ b/block/partitions/tegra.c
> @@ -0,0 +1,75 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#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/mmc/blkdev.h>
> +#include <linux/mmc/card.h>
> +#include <linux/mmc/host.h>
> +
> +#include <soc/tegra/common.h>
> +
> +#include "check.h"
> +
> +static const struct of_device_id tegra_sdhci_match[] = {
> +	{ .compatible = "nvidia,tegra20-sdhci", },
> +	{ .compatible = "nvidia,tegra30-sdhci", },
> +	{ .compatible = "nvidia,tegra114-sdhci", },

I know of a couple of OEM devices using the above SoCs that support this
alternate GPT sector mechanism...

> +	{ .compatible = "nvidia,tegra124-sdhci", },

... but I'm unaware of any using this. The only one that I could imagine
employing this quirk is the SHIELD Tablet K1 (a.k.a. ST8), but I thought
it had been changed on that device already. Do you know specifics?

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 2/3] mmc: block: Add mmc_bdev_to_card() helper
  2021-08-17  4:37   ` Christoph Hellwig
@ 2021-08-17 16:10     ` Dmitry Osipenko
  0 siblings, 0 replies; 12+ messages in thread
From: Dmitry Osipenko @ 2021-08-17 16:10 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, Micha?? Miros??aw,
	David Heidelberg, Peter Geis, Ulf Hansson, Adrian Hunter,
	Davidlohr Bueso, Ion Agorria, Svyatoslav Ryhel, linux-tegra,
	linux-block, linux-efi

17.08.2021 07:37, Christoph Hellwig пишет:
> On Tue, Aug 17, 2021 at 04:36:42AM +0300, Dmitry Osipenko wrote:
>> +	if (bdev->bd_disk->major != MMC_BLOCK_MAJOR)
>> +		return NULL;
> 
> The major is a dangerous check as we have all kinds of ways to override
> it.  Please check the block device operations as they must be unique.
> 

Alright, thank you for the suggestion.

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

* Re: [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices
  2021-08-17 14:11   ` Thierry Reding
@ 2021-08-17 16:10     ` Dmitry Osipenko
  0 siblings, 0 replies; 12+ messages in thread
From: Dmitry Osipenko @ 2021-08-17 16:10 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jens Axboe, Jonathan Hunter, Michał Mirosław,
	David Heidelberg, Peter Geis, Ulf Hansson, Adrian Hunter,
	Christoph Hellwig, Davidlohr Bueso, Ion Agorria,
	Svyatoslav Ryhel, linux-tegra, linux-block, linux-efi

17.08.2021 17:11, Thierry Reding пишет:
> On Tue, Aug 17, 2021 at 04:36:43AM +0300, Dmitry Osipenko wrote:
> [...]
>> diff --git a/block/partitions/tegra.c b/block/partitions/tegra.c
>> new file mode 100644
>> index 000000000000..4937e9f62398
>> --- /dev/null
>> +++ b/block/partitions/tegra.c
>> @@ -0,0 +1,75 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +#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/mmc/blkdev.h>
>> +#include <linux/mmc/card.h>
>> +#include <linux/mmc/host.h>
>> +
>> +#include <soc/tegra/common.h>
>> +
>> +#include "check.h"
>> +
>> +static const struct of_device_id tegra_sdhci_match[] = {
>> +	{ .compatible = "nvidia,tegra20-sdhci", },
>> +	{ .compatible = "nvidia,tegra30-sdhci", },
>> +	{ .compatible = "nvidia,tegra114-sdhci", },
> 
> I know of a couple of OEM devices using the above SoCs that support this
> alternate GPT sector mechanism...
> 
>> +	{ .compatible = "nvidia,tegra124-sdhci", },
> 
> ... but I'm unaware of any using this. The only one that I could imagine
> employing this quirk is the SHIELD Tablet K1 (a.k.a. ST8), but I thought
> it had been changed on that device already. Do you know specifics?

Nexus 9 tablet (T132) needs that.

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

* Re: [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices
  2021-08-17  4:43   ` Christoph Hellwig
@ 2021-08-17 16:11     ` Dmitry Osipenko
  0 siblings, 0 replies; 12+ messages in thread
From: Dmitry Osipenko @ 2021-08-17 16:11 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter, Micha?? Miros??aw,
	David Heidelberg, Peter Geis, Ulf Hansson, Adrian Hunter,
	Davidlohr Bueso, Ion Agorria, Svyatoslav Ryhel, linux-tegra,
	linux-block, linux-efi

17.08.2021 07:43, Christoph Hellwig пишет:
> Just curious, why not add a new block_device_operations member
> 'alternative_gpt_sector', then move all the code calculating it to
> the mmc layer?
> 

That will work too.

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

* Re: [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices
  2021-08-17  8:24   ` Ulf Hansson
@ 2021-08-17 16:16     ` Dmitry Osipenko
  0 siblings, 0 replies; 12+ messages in thread
From: Dmitry Osipenko @ 2021-08-17 16:16 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Jens Axboe, Thierry Reding, Jonathan Hunter,
	Michał Mirosław, David Heidelberg, Peter Geis,
	Adrian Hunter, Christoph Hellwig, Davidlohr Bueso, Ion Agorria,
	Svyatoslav Ryhel, linux-tegra, linux-block, linux-efi

17.08.2021 11:24, Ulf Hansson пишет:
>> +int tegra_partition_forced_gpt(struct parsed_partitions *state)
>> +{
>> +       struct gendisk *disk = state->disk;
>> +       struct block_device *bdev = disk->part0;
>> +       struct mmc_card *card = mmc_bdev_to_card(bdev);
>> +       int ret, boot_offset;
>> +
>> +       if (!soc_is_tegra())
>> +               return 0;
>> +
>> +       /* filter out unrelated and untested boot sources */
>> +       if (!card || card->ext_csd.rev < 3 ||
>> +           !mmc_card_is_blockaddr(card) ||
>> +            mmc_card_is_removable(card->host) ||
>> +            bdev_logical_block_size(bdev) != SZ_512 ||
>> +           !of_match_node(tegra_sdhci_match, card->host->parent->of_node)) {
> I think you need to convince Rob Herring that the location of the GPT
> table in the eMMC flash memory is allowed to depend on the compatible
> string of the sdhci controller.

I'll CC Rob on the next revision, although I think he doesn't care much
about this.

> In any case, I think Christoph raised some interesting ideas in his
> reply. Moving more of this code into the mmc core/block layer seems
> reasonable to me as well.

Will prepare v5, thanks.

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

end of thread, other threads:[~2021-08-17 16:16 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-17  1:36 [PATCH v4 0/3] Support EFI partition on NVIDIA Tegra devices Dmitry Osipenko
2021-08-17  1:36 ` [PATCH v4 1/3] mmc: core: Add raw_boot_mult field to mmc_ext_csd Dmitry Osipenko
2021-08-17  1:36 ` [PATCH v4 2/3] mmc: block: Add mmc_bdev_to_card() helper Dmitry Osipenko
2021-08-17  4:37   ` Christoph Hellwig
2021-08-17 16:10     ` Dmitry Osipenko
2021-08-17  1:36 ` [PATCH v4 3/3] partitions/efi: Support NVIDIA Tegra devices Dmitry Osipenko
2021-08-17  4:43   ` Christoph Hellwig
2021-08-17 16:11     ` Dmitry Osipenko
2021-08-17  8:24   ` Ulf Hansson
2021-08-17 16:16     ` Dmitry Osipenko
2021-08-17 14:11   ` Thierry Reding
2021-08-17 16:10     ` 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).