diff mbox

[U-Boot,v1,1/2] part_efi: support padding between the GPT header and partition entries

Message ID 74f10647eab28731bdde19cbd9151a29da28ffea.1487349763.git.philipp.tomsich@theobroma-systems.com
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show

Commit Message

Philipp Tomsich Feb. 17, 2017, 5:31 p.m. UTC
Some architectures require their SPL loader at a fixed address within
the first 16KB of the disk. To avoid an overlap with the partition
entries of the EFI partition table, the first safe offset (in bytes,
from the start of the device) for the entries can be set through
CONFIG_EFI_PARTITION_ENTRIES_OFF.

When formatting a device with an EFI parition table, we may need to
leave a gap between the GPT header (always in LBA 1) and the partition
entries. The GPT header already contains a field to specify the
on-disk location, which has so far always been set to LBA 2. With this
change, a configurable offset will be translated into a LBA address
indicating where to put the entries.

Now also allows an override via device-tree using a config-node.

Tested (exporting an internal MMC formatted with this) against Linux,
MacOS X and Windows.

Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
---
 disk/part_efi.c              | 46 ++++++++++++++++++++++++++++++++++++++++----
 scripts/config_whitelist.txt |  1 +
 2 files changed, 43 insertions(+), 4 deletions(-)

Comments

Simon Glass Feb. 22, 2017, 3:59 a.m. UTC | #1
Hi,

On 17 February 2017 at 10:31, Philipp Tomsich
<philipp.tomsich@theobroma-systems.com> wrote:
> Some architectures require their SPL loader at a fixed address within
> the first 16KB of the disk. To avoid an overlap with the partition
> entries of the EFI partition table, the first safe offset (in bytes,
> from the start of the device) for the entries can be set through
> CONFIG_EFI_PARTITION_ENTRIES_OFF.
>
> When formatting a device with an EFI parition table, we may need to
> leave a gap between the GPT header (always in LBA 1) and the partition
> entries. The GPT header already contains a field to specify the
> on-disk location, which has so far always been set to LBA 2. With this
> change, a configurable offset will be translated into a LBA address
> indicating where to put the entries.
>
> Now also allows an override via device-tree using a config-node.
>
> Tested (exporting an internal MMC formatted with this) against Linux,
> MacOS X and Windows.
>
> Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
> ---
>  disk/part_efi.c              | 46 ++++++++++++++++++++++++++++++++++++++++----
>  scripts/config_whitelist.txt |  1 +
>  2 files changed, 43 insertions(+), 4 deletions(-)

Looks good to me. But there are a few things to tweak, sorry.

Can you please send v2 without all the context lines, and use
CONFIG_OF_CONTROL instead of CONFIG_OF_LIBFDT?

Also you cannot add new CONFIG options. You should add your new option
to a Kconfig file.

For your device tree property, that should be documented in
'Configuration Options' in README.fdt-control. Or better if you can
send a patch to move that section out of that file into
doc/device-tree-bindings/config.txt and then put your new one in
there...

Regards,
Simon
diff mbox

Patch

diff --git a/disk/part_efi.c b/disk/part_efi.c
index 893cbbd..7c4ae69 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -1,22 +1,23 @@ 
 /*
  * Copyright (C) 2008 RuggedCom, Inc.
  * Richard Retanubun <RichardRetanubun@RuggedCom.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 /*
  * NOTE:
  *   when CONFIG_SYS_64BIT_LBA is not defined, lbaint_t is 32 bits; this
  *   limits the maximum size of addressable storage to < 2 Terra Bytes
  */
 #include <asm/unaligned.h>
 #include <common.h>
 #include <command.h>
+#include <fdtdec.h>
 #include <ide.h>
 #include <inttypes.h>
 #include <malloc.h>
 #include <memalign.h>
 #include <part_efi.h>
 #include <linux/ctype.h>
 
@@ -350,48 +351,48 @@  static int set_protective_mbr(struct blk_desc *dev_desc)
 int write_gpt_table(struct blk_desc *dev_desc,
 		gpt_header *gpt_h, gpt_entry *gpt_e)
 {
 	const int pte_blk_cnt = BLOCK_CNT((gpt_h->num_partition_entries
 					   * sizeof(gpt_entry)), dev_desc);
 	u32 calc_crc32;
 
 	debug("max lba: %x\n", (u32) dev_desc->lba);
 	/* Setup the Protective MBR */
 	if (set_protective_mbr(dev_desc) < 0)
 		goto err;
 
 	/* Generate CRC for the Primary GPT Header */
 	calc_crc32 = efi_crc32((const unsigned char *)gpt_e,
 			      le32_to_cpu(gpt_h->num_partition_entries) *
 			      le32_to_cpu(gpt_h->sizeof_partition_entry));
 	gpt_h->partition_entry_array_crc32 = cpu_to_le32(calc_crc32);
 
 	calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
 			      le32_to_cpu(gpt_h->header_size));
 	gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
 
 	/* Write the First GPT to the block right after the Legacy MBR */
 	if (blk_dwrite(dev_desc, 1, 1, gpt_h) != 1)
 		goto err;
 
-	if (blk_dwrite(dev_desc, 2, pte_blk_cnt, gpt_e)
-	    != pte_blk_cnt)
+	if (blk_dwrite(dev_desc, le64_to_cpu(gpt_h->partition_entry_lba),
+		       pte_blk_cnt, gpt_e) != pte_blk_cnt)
 		goto err;
 
 	prepare_backup_gpt_header(gpt_h);
 
 	if (blk_dwrite(dev_desc, (lbaint_t)le64_to_cpu(gpt_h->last_usable_lba)
 		       + 1, pte_blk_cnt, gpt_e) != pte_blk_cnt)
 		goto err;
 
 	if (blk_dwrite(dev_desc, (lbaint_t)le64_to_cpu(gpt_h->my_lba), 1,
 		       gpt_h) != 1)
 		goto err;
 
 	debug("GPT successfully written to block device!\n");
 	return 0;
 
  err:
 	printf("** Can't write to device %d **\n", dev_desc->devnum);
 	return -1;
 }
 
@@ -498,25 +499,62 @@  int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
 	return 0;
 }
 
+static uint32_t partition_entries_offset(struct blk_desc *dev_desc)
+{
+	uint32_t offset_blks;
+	int config_offset;
+
+#if defined(CONFIG_EFI_PARTITION_ENTRIES_OFF)
+	/* Some architectures require their SPL loader at a fixed
+	 * address within the first 16KB of the disk.  To avoid an
+	 * overlap with the partition entries of the EFI partition
+	 * table, the first safe offset (in bytes, from the start of
+	 * the disk) for the entries can be set in
+	 * CONFIG_EFI_PARTITION_ENTRIES_OFF.
+	 */
+	offset_blks =
+		PAD_TO_BLOCKSIZE(CONFIG_EFI_PARTITION_ENTRIES_OFF, dev_desc);
+#else
+	offset_blks = 2;
+#endif
+
+#if defined(CONFIG_OF_LIBFDT)
+	/* Allow the offset of the first partition entires (in bytes
+	   from the start of the device) to be specified as a property
+	   of the device tree '/config' node. */
+	config_offset = fdtdec_get_config_int(gd->fdt_blob,
+					      "u-boot,efi-partition-entries-offset",
+					      -EINVAL);
+	if (config_offset != -EINVAL)
+		offset_blks = PAD_TO_BLOCKSIZE(config_offset, dev_desc);
+#endif
+
+	debug("efi: partition entries offset (in blocks): %d\n", offset_blks);
+
+	return offset_blks;
+}
+
 int gpt_fill_header(struct blk_desc *dev_desc, gpt_header *gpt_h,
 		char *str_guid, int parts_count)
 {
 	gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
 	gpt_h->revision = cpu_to_le32(GPT_HEADER_REVISION_V1);
 	gpt_h->header_size = cpu_to_le32(sizeof(gpt_header));
 	gpt_h->my_lba = cpu_to_le64(1);
 	gpt_h->alternate_lba = cpu_to_le64(dev_desc->lba - 1);
-	gpt_h->first_usable_lba = cpu_to_le64(34);
 	gpt_h->last_usable_lba = cpu_to_le64(dev_desc->lba - 34);
-	gpt_h->partition_entry_lba = cpu_to_le64(2);
+	gpt_h->partition_entry_lba =
+		cpu_to_le64(partition_entries_offset(dev_desc));
+	gpt_h->first_usable_lba =
+		cpu_to_le64(le64_to_cpu(gpt_h->partition_entry_lba) + 32);
 	gpt_h->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS);
 	gpt_h->sizeof_partition_entry = cpu_to_le32(sizeof(gpt_entry));
 	gpt_h->header_crc32 = 0;
 	gpt_h->partition_entry_array_crc32 = 0;
 
 	if (uuid_str_to_bin(str_guid, gpt_h->disk_guid.b, UUID_STR_FORMAT_GUID))
 		return -1;
 
 	return 0;
 }
 
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 6a09ad1..195af92 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -934,6 +934,7 @@  CONFIG_EEPRO100_SROM_WRITE
 CONFIG_EEPROM_BUS_ADDRESS
 CONFIG_EEPROM_CHIP_ADDRESS
 CONFIG_EEPROM_LAYOUT_HELP_STRING
+CONFIG_EFI_PARTITION_ENTRIES_OFF
 CONFIG_EFLASH_PROTSECTORS
 CONFIG_EHCI_DESC_BIG_ENDIAN
 CONFIG_EHCI_HCD_INIT_AFTER_RESET